HTTP入门(三):使用Nodo.js脚本实现简易服务器

  • 本文通过简单的Node.js脚本模拟服务器请求与响应原理
  • 本文主要目的是对学习内容进行总结以及方便日后查阅。
  • 本文所引用的图片和文字版权归原作者所有,侵权删。
  • 如有错误请在下方评论区指出,欢迎积极讨论。

前言


  • 硬件服务器:我们的电脑就是一个服务器。和普通的服务器的区别是:真正的服务器CPU可能有128G核,32、64、128G内存。没有GUI,没有显示器,用ssh远程登录,本质还是电脑
  • 软件服务器:服务器上的软件。

服务器你已经有了,你使用的电脑就是服务器。但是你还没有提供 HTTP 服务的「程序」
脚本就可以提供 HTTP 服务,不管是 Bash 脚本还是 Node.js 脚本都可以。这篇文章先用 Node.js 脚本试试水。

接收请求


我们的脚本只需要一个文件就可以搞定:

  • 新建一个安全的目录

     
         cd ~/Desktop
         mkdir node-demo
         cd node-demo
    
  • touch server.js
  • 编辑 server.js,内容已上传到GitHub,所以用命令

    curl https://raw.githubusercontent.com/mtt3366/nodeserver/master/NodeServer.js > ./server.js

    拷贝代码到server.js
    示例

  • cat server.js查看内容是否已经拷贝。
    查看
  • node server.js 8888 监听8888本地端口,这里端口参数不建议写0-1023,因为小于1024已经被规定使用,需要管理员权限才可以访问。
  • 成功之后,这个 server 会保持运行,无法退出。
  • 如果你想「中断」这个 server,按 Ctrl + C 即可(C 就是 Cancel 的意思),中断后你才能输入其他命令。
  • 把这个 server 放在那里别动,新开一个 Bash 窗口,完成下面的测试

好了服务器完成。只不过

  1. 这个服务器目前只有一个功能,那就是打印出路径查询字符串
  2. 还缺少一个重要的功能,那就是发出 HTTP 响应,目前我们先不发出响应

接下来要发起一个请求到这个服务器。这听起来有点怪异,「我向自己发起请求」,目前是的,因为我们的电脑既是客户端,又是服务器,还是会经历HTTP协议,还是会走一遍TCP/IP协议,所以用本机来学习服务器原理可行。接下来

  • 在新的 Bash 窗口运行 curl http://localhost:8888/xxx 或者 curl http://127.0.0.1:8888/xxx

你会马上发现 server 打印出了路径:

MTT说:得到 HTTP 路径
/xxx
MTT说:查询字符串为

MTT说:不含查询字符串的路径为
/xxx

这说明:

  1. 我们的 server 收到了我们用 curl 发出的请求
  2. 由于 server 迟迟没有发出响应,所以 curl 就一直等在那里,无法退出(用 Ctrl + C 中断这个傻 curl)
  3. 运行curl "http://127.0.0.1:8888/xxx?name=ff"
    打印结果:

    MTT说:得到 HTTP 路径
    /xxx?name=ff
    MTT说:查询字符串为
    ?name=ff
    MTT说:不含查询字符串的路径为
    /xxx
    

这个服务器就一个功能,把路径和查询参数打印出来,不发出响应

发出响应


接下来我们让我们 server 发出响应,不在让客户端端一直等我们

  1. 编辑 server.js
  2. 在中间我标注的区域添加两行代码
  3. response.write('Hi')
  4. response.end() 如果没有这句话,客户端还会一直等
  5. 中断之前的 server,重新运行 node server 8888
  6. curl http://127.0.0.1:8888/xxx,结果如下:
  7. Hi%
    这个 % 不是我们的内容,% 表示结尾。如果你看 % 不爽,就把 'Hi' 换成 'Hi\n'
  8. 响应添加成功
  9. 使用 curl -s -v -- "http://localhost:8888/xxx" 可以查看完整的请求和响应示例

根据请求返回不同的响应


响应 /404

将中间的代码改为

if(path  ==  "/" ){
    response.write('Hi')
    response.end()
    }    else{
    response.statusCode = 404
    response.end()
    }

代码示例
代码示例

不同的请求返回内容的截图

响应404
1

响应/

响应 /index.html

代码修改

响应示例

强调:后缀是废话。文件内容是有 HTTP 头中的 Content-Type 保证的
响应真正的网页
  • 完整代码:
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var path = request.url 
  var query = ''
  if(path.indexOf('?') >= 0){ query = path.substring(path.indexOf('?')) }
  var pathNoQuery = parsedUrl.pathname
  var queryObject = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('HTTP 路径为\n' + path)
  if(path == '/style.js'){
    response.setHeader('Content-Type', 'text/css; charset=utf-8')
    response.write('body{background-color: #ddd;}h1{color: red;}')
    response.end()
  }else if(path == '/script.html'){
    response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
    response.write('alert("这是JS执行的")')
    response.end()
  }else if(path == '/index.css'){
    response.setHeader('Content-Type', 'text/html; charset=utf-8')
    response.write('<!DOCTYPE>\n<html>'  + 
      '<head><link rel="stylesheet" href="/style.js">' +
      '</head><body>'  +
      '<h1>你好</h1>' +
      '<script src="/script.html"></script>' +
      '</body></html>')
    response.end()
  }else{
    response.statusCode = 404
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)
  • 接下来 curl -s -v – "http://localhost:8888"

  • 因为响应中<link rel="stylesheet" href="/style.js"><script src="/script.html"></script>服务器会接着继续发出/script/style响应。
  • 包括图片路径,也会发出响应。
  • 模拟一下/script/style响应。
  • 为了证实我们的想法,打开network查看请求与响应。发现确实有三个响应。

风彻
1.5k 声望142 粉丝