HTTP 状态代码 200 但页面未加载 Node.js Socket.io -- 使用 Socket.io 的 Node.js 教程,Daniel Nill,fs.readFile(),socket

     2023-04-18     154

关键词:

【中文标题】HTTP 状态代码 200 但页面未加载 Node.js Socket.io -- 使用 Socket.io 的 Node.js 教程,Daniel Nill,fs.readFile(),socket.html【英文标题】:HTTP Status Code 200 but page does not load Node.js Socket.io -- Node.js Tutorial With Socket.io, Daniel Nill, fs.readFile(), socket.html 【发布时间】:2013-12-20 05:54:15 【问题描述】:

了解 node.js 和 socket.io 并通过 this tutorial by Daniel Nill 工作。服务器启动没有问题。但是,当我导航到 localhost:8001/socket.html 时,我收到默认错误消息。所以我将 switch 语句更改为“/socket.html”而不是“socket.html”。该页面现在加载状态代码 200,但没有任何内容呈现到屏幕上。屏幕应该显示“这是我们的 socket.html 文件”。什么给了?

服务端js代码是

var http = require("http");
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(request, response) 
    console.log('Connection');
    var path = url.parse(request.url).pathname;

    switch(path)
        case '/':
            response.writeHead(200, 'Content-Type': 'text/html'); 
            response.write('hello world');
            break;
        case 'socket.html':
            fs.readFile(__dirname + path, function(error, data)
                if (error)
                    response.writeHead(404);
                    response.write("opps this doesn't exist - 404");
                
                else
                    response.writeHead(200, "Content-Type": "text/html");
                    response.write(data, "utf8");
                
            );
            break;
        default:
            response.writeHead(404);
            response.write("opps this doesn't exist - 404");
            break;
    
    response.end(); 
); 

server.listen(8001); 

与 server.js 位于同一目录的 Socket.html 包含此

<html>
  <head></head>
  <body>This is our socket.html file</body>
</html>

好吧,我放弃了,转而使用 this example,它开箱即用!

【问题讨论】:

【参考方案1】:

这里是初学者。据我所知,Daniel Nill 为教程编写了一堆代码,但从未奏效。结果,他只是增加了初学者的困惑——他声称他试图缓解这一点。

所以我将 switch 语句更改为“/socket.html”而不是“socket.html”。

这是一个明显的错误——很好。

页面现在加载状态码 200,但没有呈现任何内容 屏幕。屏幕应该显示“这是我们的 socket.html 文件”。什么 给?

或者,就像我看到的那样,如果 socket.html 文件不存在,我得到的不是 404 错误,而是状态代码 200(OK)和一个空网页。

教程中的代码不起作用的原因是丹尼尔尼尔认为他会很聪明,不会在每个response.write()之后写response.end()。他认为他可以在所有代码的末尾写一个response.end()

在我看来,Daniel Nill 误解了 nodejs 的工作原理。也就是说,nodejs 不会执行一个函数,然后等待作为参数传递的处理函数完成执行,然后再执行下一行代码。如果 nodejs 确实这样做了,那么我们就不需要将代码放在处理函数中。相反,nodejs 将一个处理函数添加到将在未来某个时间执行的处理函数列表中。

看看这段代码中的 fs.readFile() 函数:

switch(path)
    case '/':
        response.writeHead(200, 'Content-Type': 'text/html'); 
        response.write('hello world');
        break;
    case 'socket.html':
        fs.readFile(__dirname + path, function(error, data)
            if (error)
                response.writeHead(404);
                response.write("opps this doesn't exist - 404");
            
            else
                response.writeHead(200, "Content-Type": "text/html");
                response.write(data, "utf8");
            
        );
        break;
    default:
        response.writeHead(404);
        response.write("opps this doesn't exist - 404");
        break;

response.end(); 

fs.readFile() 的处理函数是这部分:

        function(error, data)
            if (error)
                response.writeHead(404);
                response.write("opps this doesn't exist - 404");
            
            else
                response.writeHead(200, "Content-Type": "text/html");
                response.write(data, "utf8");
            
        );

当浏览器请求/socket.html时,nodejs执行fs.readFile(),然后nodejs将其处理函数添加到等待执行的处理函数列表中,然后nodejs继续。将执行的下一行代码是这里的response.end()

    default:
        response.writeHead(404);
        response.write("opps this doesn't exist - 404");
        break;


response.end();   //<====HERE ******

对我来说很明显,在 fs.readFile() 的处理函数有机会执行之前,nodejs 会执行 response.end()

根据response.end() 的文档:

response.end([数据], [编码]) 此方法向服务器发出信号 已发送所有响应标头和正文;那台服务器 应该认为这个消息是完整的。方法,response.end(), 必须在每次响应时调用。

我测试过,如果你不做任何response.write(),而只是调用response.end(),nodejs 会创建一个空响应,状态码为200,例如:

  switch(path) 
    case '/':
      //resp.writeHead(200, 'Content-Type': 'text/html' );
      //resp.write('<h3>Root page</h3>');
      resp.end();
      break;

我认为从 Daniel Nill 的错误中吸取的教训是,在你给 nodejs 一个处理函数之后,你就无法控制 处理函数 执行后执行的位置。事实上,在处理函数结束之后编写的代码可以在处理函数执行之前执行。因此,处理函数需要自己完成所有需要完成的事情。

以下是使教程中的示例正常工作所需的修改:

var http = require('http');
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(requ, resp) 
  //requ.url => everything after the host--including the query string
  //url.parse(requ.url).pathname => the portion of requ.url before the query string
  var path = url.parse(requ.url).pathname;

  //The following is so that the automatic request that all browsers make
  //for favicon.ico (which for some reason is not logged by any developer
  //tools) will not display a 'connection' message:

  if (path == '/favicon.ico') 
    resp.writeHead(200, 'Content-Type': 'image/x-icon' );
    resp.end();
    return;   //Terminate execution of this function, skipping the code below.
  

  //Router:
  switch(path) 
    case '/':
      resp.writeHead(200, 'Content-Type': 'text/html' );
      resp.write('<h3>Root page</h3>');
      resp.end();
      break;
    case '/socket.html':
      fs.readFile(__dirname + path, function(error, data) 
        if (error) 
          console.log('file error');
          resp.writeHead(404);
          resp.write("oops, this doesn't exist - 404");
          resp.end();
        
        else 
          console.log('no file error');
          resp.writeHead(200, 'Content-Type': 'text/html' );
          resp.write(data, 'utf8');
          resp.end();
        
      );
      break;
    default:
      resp.writeHead(404);
      resp.write("oops, this doesn't exist - 404");
      resp.end();
      break;
  

  console.log('Connection');
);

port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);

为了尽量减少您必须致电response.end() 的次数,您可以这样做:

var http = require('http');
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(requ, resp) 
  //console.log('request url: ' + requ.url);

  //requ.url => everything after the host--including the query string
  //url.parse(requ.url).pathname => the portion of requ.url before the query string
  var path = url.parse(requ.url).pathname;

  //The following is so that the automatic request that all browsers make
  //for favicon.ico (which for some reason is not logged by any developer
  //tools) will not cause a 'connection' message:

  if (path == '/favicon.ico') 
    resp.writeHead(200, 'Content-Type': 'image/x-icon' );
    resp.end();
    return;
  

  //Router:
  switch(path) 
    case '/':
      resp.writeHead(200, 'Content-Type': 'text/html' );
      resp.write('<h3>Root page</h3>');
      resp.end();
      break;
    case '/socket.html':
      fs.readFile(__dirname + path, function(error, data) 
        if (error) 
          console.log('file error');
          resp.writeHead(404);
          resp.write("oops, this doesn't exist - 404");
          //resp.end();
        
        else 
          console.log('no file error');
          resp.writeHead(200, 'Content-Type': 'text/html' );
          resp.write(data, 'utf8');
          //resp.end();
        
        resp.end();
      );
      break;
    default:
      resp.writeHead(404);
      resp.write("oops, this doesn't exist - 404");
      resp.end();
      break;
  
  //resp.end();
  console.log('Connection');
);



port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);

但是您不能像 Daniel Nill 那样将 response.end() 完全重构出处理函数;并且您不能在 switch 语句之后放置response.end(),因为response.end() 将在传递给 fs.readFile() 的处理函数有机会执行之前执行,这将导致状态码为 200 的空请求发送到浏览器。

此外,我在一个请求中收到了两条“连接”消息。当我输入如下网址时,我的开发人员工具仅显示浏览器发送了一个请求:

http://localhost:8888/

...但是所有浏览器都会发送一个额外的请求来检索/favicon.ico。您可以通过编写以下内容来证明是这样的:

var server = http.createServer(function(requ, resp) 
  console.log('request url: ' + requ.url);

为了解决双重请求问题,我添加了if语句:

if (path == '/favicon.ico') ...

...这里描述:

http://tinyurl.com/odhs5le

=====

在教程的下一部分中,为了在使用 socket.io 时看到命令行输出,您必须使用如下命令启动服务器:

 $ DEBUG=socket.io:* node server.js

在此处查看 nodejs 文档“从 0.9 升级”,Log differences 部分:

http://socket.io/docs/migrating-from-0-9/

=====

为了让 socket.io 部分代码正常工作,我在server.js 中加入了以下内容:

var http = require('http');
var url = require('url');
var fs = require('fs');
var io = require('socket.io'); //New code

var server = http.createServer(function(requ, resp) 
  ...
  ...
  ...
);

port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);

//New code:
var websockets_listener = io.listen(server);
websockets_listener.sockets.on('connection', function(socket)
    socket.emit('server message', "message": "hello world");
);

然后在socket.html,我有这个:

<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
  </head>
  <body>

    <div>This is our socket.html file</div>
    <div id="message"></div>

    <script>
      var socket = io.connect();
      //More recent versions of socket.io allow you to simply write:
      //var socket = io();
      //which both creates the socket and by default connects to 
      //the same host that served this page.
      //See: http://socket.io/get-started/chat/, section Integrating Socket.IO

      socket.on('server message', function(data) 
        document.getElementById('message').innerHTML = data.message;
      );
    </script>
  </body>
</html>

你可以这样做:

     socket.on('server message', function(data) 
        console.log(data.message);
      );

...但是您必须记住,在 nodejs 中,console.log() 输出会转到服务器窗口,但是当 javascript 在网页上执行时,例如 socket.html,console.log() 输出会转到到 Web 浏览器的控制台(显示您的 Web 浏览器的开发工具以查看控制台)--所以不要在服务器窗口中查找输出。

===

在教程的下一部分中,要仅流式传输时间,消除日期、毫秒、utc 偏移量等,这只会使一切变得混乱,您可以在server.js 中执行此操作:

var websockets_listener = io.listen(server);
websockets_listener.sockets.on('connection', function(socket)

  setInterval(function() 
    var now = new Date();
    socket.emit('time', local_time: now.toLocaleTimeString())
  , 1000);

);

socket.html:

<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
  </head>
  <body>
    <div>This is our socket.html file</div>
    <div id="message"></div>

    <script>
      var socket = io.connect();

      socket.on('time', function(data) 
        document.getElementById('message').innerHTML = data.local_time;
      );
    </script>
  </body>
</html>

===

在教程的下一部分中,要将数据从客户端流式传输到服务器,您可以这样做(注意对 jquery 的更正,这不符合标准):

socket.html:

<html>
  <head>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
  </head>
  <body>
    <div>This is our socket.html file</div>
    <div id="time"></div>
    <textarea id="text"></textarea>


    <script>
      var socket = io.connect();           

      socket.on('time', function(data) 
        $('#time').html(data.local_time);
      );

      //Because the html above has already been parsed by the time this
      //js executes, there is no need for document.ready():

      $('#text').on('keypress', function(event) 
        var keycode = event.which;
        socket.emit('client data', letter: String.fromCharCode(keycode) ); 
      );
    </script>     
  </body>
</html>

server.js

var http = require('http');
var url = require('url');
var fs = require('fs');
var io = require('socket.io');

var server = http.createServer(function(requ, resp) 
  ...
  ...
  ...
);

port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);

var websockets_listener = io.listen(server);

//websockets_listener.set('log level', 1); 
//Rather than writing the previous line(which doesn't work anymore)
//just stop the server and restart it using this command:
//$ node server.js
//...instead of:
//$ DEBUG=socket.io:* node server.js

websockets_listener.sockets.on('connection', function(socket)

  setInterval(function() 
    var now = new Date();
    socket.emit('time', local_time: now.toLocaleTimeString())
  , 1000);

  socket.on('client data', function(data) 
    process.stdout.write(data.letter);
  );

);

【讨论】:

【参考方案2】:

使用response.sendfile 而不是手动读取文件。这让 express 为您处理内容类型。

【讨论】:

教程与express无关。

状态码

常见状态码200成功300多种选择400错误请求404未找到405方法禁用500服务器内部错误(1)1开头的http状态码100继续101切换协议(2)2开头的http状态码200成功201请求成功并服务器创建了新的资源202接受请求但没创建资源203返回另一资源... 查看详情

HTTP 状态代码 200 但访问被拒绝。 WebAPI ASP.NET MVC

】HTTP状态代码200但访问被拒绝。WebAPIASP.NETMVC【英文标题】:HTTPstatuscode200butaccessdenied.WebAPIASP.NETMVC【发布时间】:2018-05-0306:20:08【问题描述】:我正在调用这样的WebAPI方法:$.post("/api/attendances",gigId:button.attr("data-gig-id")).done(functio... 查看详情

已验证但未授权的 HTTP 状态代码?

】已验证但未授权的HTTP状态代码?【英文标题】:HTTPStatusCodeforAuthenticatedbutUnauthorized?【发布时间】:2017-01-0212:40:54【问题描述】:如果请求已通过身份验证(根据TheOAuth2.0AuthorizationFramework:BearerTokenUsage:AuthorizationRequestHeaderField)... 查看详情

Nuxtjs 登陆页面未加载,但其余工作正常

】Nuxtjs登陆页面未加载,但其余工作正常【英文标题】:Nuxtjslandingpagedoes\'tloadbuttherestworkfine【发布时间】:2021-06-2816:26:19【问题描述】:我用Nuxtjs开发了一个博客,在开发模式下一切正常,但是在我将应用程序部署到我的cpanel... 查看详情

什么是“未找到项目”错误页面最合适的 HTTP 状态代码

】什么是“未找到项目”错误页面最合适的HTTP状态代码【英文标题】:What\'sthemostappropriateHTTPstatuscodeforan"itemnotfound"errorpage【发布时间】:2021-04-0708:06:54【问题描述】:我很好奇什么是“项目不存在”页面最合适的HTTP状... 查看详情

http状态代码

1XX临时/信息相应2XX成功3XX重定向4XX客户端/请求错误5XX服务器错误200(成功)服务器成功处理了请求301(永久移动)302(临时移动)400(错误请求)服务器不理解请求语法403(禁止)服务器拒绝请求404(未找到)服务器找不到请... 查看详情

javascript 未加载到 HTML 文件中 - nodejs + http

...答案。我在Windows上使用node.js,通过http模块生成一个静态页面,其内容从js文件生成。服务器文件(server.js):va 查看详情

未找到搜索结果的正确 HTTP 状态代码是啥?

】未找到搜索结果的正确HTTP状态代码是啥?【英文标题】:WhatisthecorrectHTTPstatuscodeforsearchresultsnotfound?未找到搜索结果的正确HTTP状态代码是什么?【发布时间】:2019-05-0118:55:06【问题描述】:我们正在用Java实现RESTAPI。对于GETREST... 查看详情

我想在 url / 之后加载另一个视图文件,但收到一个错误提示页面未找到

...想在url/之后加载另一个视图文件,但收到一个错误提示页面未找到【英文标题】:Iwanttoloadanotherviewfileaftertheurl/butreceivinganerrorsayingpagenotfound【发布时间】:2021-01-3116:31:51【问题描述】:错误信息:找不到页面(404)请求方法:GET请... 查看详情

http常见响应状态码(代码片段)

HTTP响应状态码:1xx:信息100Continue服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。101SwitchingProtocols服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。2xx:成功200OK请... 查看详情

##node从helloworld开始(代码片段)

创建文件server.js//es5varhttp=require(‘http‘);http.createServer(function(request,response)//发送HTTP头部//HTTP状态值:200:OK//内容类型:text/plainresponse.writeHead(200,‘Content-Type‘:‘text/plain‘);//发送响应数据"HelloWo 查看详情

Chrome etag 总是显示 200 ok 但 curl 得到 304 未修改

...片,第一张是在浏览器中发送请求,etag值始终相同,http状态始终为200ok,基于httpetagstretegy,我会得到此请求中未修改的304。然后让我怀疑的是,当我将请求复制 查看详情

使用 Node 在 res.render() 中发送请求后页面内容未加载/显示

】使用Node在res.render()中发送请求后页面内容未加载/显示【英文标题】:Pagecontentnotloading/displayedaftersendrequestinres.render()usingNode【发布时间】:2018-03-2008:19:32【问题描述】:我有服务器文件,即node_app.js、客户端文件login.php、group.p... 查看详情

node学习笔记——http与url模块(代码片段)

...erver((req,res)=>console.log(req.url);//获取url//设置响应头//状态码是200,文件类型是html,字符集是utf8res.writeHead(200,"Content-type":"text/html;charset=utf-8 查看详情

http状态码

...务器内部错误)服务器遇到错误,无法完成请求。 HTTP状态码(HTTPStatusCode)状态码并不是每个都有,为了后期扩展。【update20170505】一些常见的状态码为:一、1开头1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代... 查看详情

ctf_writeup_http——302临时重定向问题(代码片段)

...中找出flag;相关知识什么是HTTP302跳转?首先我们要知道状态码,状态码是HTTP请求过程结果的描述,由三位数字组成。这三位数字描述了请求过程中所发生的情况。状态码位于响应的起始行中,如在HTTP/1.0200OK中,状态码就是200... 查看详情

HTTP - PUT 方法返回状态 200 但没有数据放入数据库

】HTTP-PUT方法返回状态200但没有数据放入数据库【英文标题】:HTTP-PUTmethodreturnsstatus200butnodatabeingputintothedatabase【发布时间】:2022-01-0809:34:34【问题描述】:我是新手,不知道为什么我的PUT请求没有将数据插入数据库。constorderId=J... 查看详情

http代码(代码片段)

HTTP响应状态码参考:1xx:信息100Continue服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。101SwitchingProtocols服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。2xx:成功200O... 查看详情