【问题标题】:Does res.writehead actually write to the head of my html page?res.writehead 是否真的写入我的 html 页面的头部?
【发布时间】:2013-11-05 13:04:02
【问题描述】:

在我的 node.js 网页中,我正在制作类似于 Facebook 链接预览的页面预览。我正在调用以获取页面的 html,并使用它来创建预览。

$.ajax({
    type: 'GET',
    data: { "html": url },
    url: "/htmlTest",
    success: function (data) {
            imgArray = [];
            $('img', data).each(function () {
                imgArray.push(this.src);
            });
  ...

这是处理请求的服务器端代码。

app.get('/htmlTest', function (req, res) {
    res.writeHead(200, { 'content-type': 'text/html' });
        request(req.query.html, function (error, response, body) {
            if (error) {
                res.write(error.toString());
                res.end('\n');
            }
            else if (response.statusCode == 200) {
                res.write(body);
                res.end('\n');
            }
        })
});

现在我注意到的是,它只会将其他页面使用的任何 CSS 插入到我的页面中,这真的会搞砸一切。为什么会这样?

另外,当我在做的时候,有没有人对 facebook 样式的页面预览有更好的想法?

【问题讨论】:

  • res.writeHead(200, { 'content-type': 'text/html' }); 似乎只是在写一个标题(不是 html 内容),虽然我还没有深入节点。您的问题更有可能是由res.write(body); 引起的
  • 你知道什么是标题吗?我建议你学习并理解 HTTP 协议本身是如何工作的,因为尝试使用 Node.js 使任何事情都富有成效。 HTTP 响应包含两个不同的部分 - 标头(内容类型/状态/等)和正文(实际有效负载)。
  • 是的,老实说,这就是他们的文档听起来的样子,但是 css 不知何故进入了我的页面。
  • writeHead 只是写 HTTP 头信息(状态、内容设置),而 write 实际上是在你的网页上写你想要的内容。看起来您正在下载一个 HTML 页面,并返回整个 HTML 页面,其中包括 <head> 标记(这可能是 css 所在的位置)。

标签: javascript jquery html node.js


【解决方案1】:

没有。 writeHead 将 HTTP 标头写入底层 TCP 流。它与 HTML 完全无关。

您遇到了问题,因为您的服务器返回了所请求 URL 的批发 HTML 内容。然后将此字符串传递给 jQuery,这显然是将包含的 CSS 样式添加到 your 文档中。

通常,从用户提供的 URL 中获取随机代码并在您的页面上下文中运行是一个糟糕的主意。它会让你发现巨大的安全漏洞——你看到的 CSS 工件就是一个例子。

坦率地说,您的代码有很多问题,请耐心等待我指出一些问题。

app.get('/htmlTest', function (req, res) {
    res.writeHead(200, { 'content-type': 'text/html' });

在这里,您以成功状态 (200) 响应浏览器 beore 您的服务器实际上做了任何事情。这是不正确的:只有在知道请求是成功还是失败之后,您才应该使用成功或错误代码进行响应。

        request(req.query.html, function (error, response, body) {
            if (error) {
                res.write(error.toString());
                res.end('\n');
            }

这里是响应错误代码的好地方,因为我们知道请求确实失败了。 res.send(500, error) 可以解决问题。

            else if (response.statusCode == 200) {
                res.write(body);
                res.end('\n');
            }

这里是我们可以用成功代码响应的地方。不要使用writeHead,而是使用Express 的setsend 方法——Content-Length 之类的东西将被正确设置:

res.set('Content-Type', 'text/html');
res.send(body);

现在如果response.statusCode != 200 会发生什么?你不处理那个案子。 error 仅在网络错误(如无法连接到目标服务器)的情况下设置。目标服务器仍然可以以非 200 状态响应,并且您的节点服务器永远不会响应浏览器。事实上,连接会一直保持打开状态,直到用户将其终止。这可以通过简单的else res.end() 来解决。


即使解决了这些问题,我们仍然没有解决在浏览器中尝试解析任意 HTML 不是一个好主意的事实。

如果我是你,我会在服务器上使用将 HTML 解析为 DOM 的东西,然后我只会将必要的信息作为 JSON 返回给浏览器。 cheerio 是您可能想要使用的模块——它看起来就像 jQuery,只是它在服务器上运行。

我会这样做:

var cheerio = require('cheerio'), url = require('url'), request = require('request');

app.get('/htmlTest', function(req, res) {
    request(req.query.url, function(err, response, body) {
        if (err) res.send(500, err); // network error, send a 500
        else if (response.status != 200) res.send(500, { httpStatus: response.status }); // server returned a non-200, send a 500
        else {
            // WARNING!  We should probably check that the response content-type is html
            var $ = cheerio.load(body); // load the returned HTML into cheerio
            var images = [];
            $('img').each(function() {
                // Image srcs can be relative.
                // You probably need the absolute URL of the image, so we should resolve the src.
                images.push(url.resolve(req.query.url, this.src));
            });

            res.send({ title: $('title').text(), images: images }); // send back JSON with the image URLs
        }
    });
});

然后从浏览器:

$.ajax({
    url: '/htmlTest',
    data: { url: url },
    dataType: 'json',
    success: function(data) {
        // data.images has your image URLs
    },
    error: function() {
        // something went wrong
    }
});

【讨论】:

  • 谢谢!我有点自学成才,所以这个答案是一个巨大的帮助。一个小的编辑: (response.status != 200) 应该是 (response.statusCode != 200)
猜你喜欢
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-02
相关资源
最近更新 更多