开启Nodejs之旅9--HTTP 服务器与客户端

210 阅读5分钟
http.Server 是一个基于事件HTTP 服务器
http.request 则是一个HTTP 客户端工具,用于向 HTTP 服务器发起请求,例如实现Pingback或者内容抓取

http.createServer 创建了一个 http.Server 的实例

//app.js 
var http = require('http'); 
http.createServer(function(req, res) { 
 res.writeHead(200, {'Content-Type': 'text/html'}); 
 res.write('<h1>Node.js</h1>'); 
 res.end('<p>Hello World</p>'); 
}).listen(3000); 
console.log("HTTP server is listening at port 3000.");

分别是请求对象( req )和响应对象( res )。
在函数体内,res 显式地写回了响应代码 200 (表示请求成功),
指定响应头为'Content-Type': 'text/html',
然后写入响应体 '<h1>Node.js</h1>',
通过 res.end结束并发送。
最后该实例还调用了 listen 函数,启动服务器并监听 3000 端口。

 http下的api除了createServer还有server,request等,

用http.server和http.createServer的效果差不多

//httpserver.js 
var http = require('http'); 
var server = new http.Server(); 
server.on('request', function(req, res) { 
 res.writeHead(200, {'Content-Type': 'text/html'}); 
 res.write('<h1>Node.js</h1>'); 
 res.end('<p>Hello World</p>'); 
}); 
server.listen(3000); 
console.log("HTTP server is listening at port 3000."); 

http.Server 的事件它继承自EventEmitter,并提供以下事件

  • request:当客户端请求到来时,该事件被触发,提供两个参数 req 和res,分别是
http.ServerRequest 和 http.ServerResponse 的实例,表示请求和响应信息。
  • connection:当 TCP 连接建立时,该事件被触发,提供一个参数 socket,为
net.Socket 的实例。connection 事件的粒度要大于 request,因为客户端在Keep-Alive 模式下可能会在同一个连接内发送多次请求
  • close :当服务器关闭时,该事件被触发。注意不是在用户连接断开时。


http.ServerRequest

HTTP 请求一般可以分为两部分:请求头(Request Header)和请求体(Requset Body)

http.ServerRequest主要是控制请求体  ,以下三个事件均用来控制请求体的内容

data:当请求体数据到来时,该事件被触发。该事件提供一个参数 chunk,表示接

收到的数据。如果该事件没有被监听,那么请求体将会被抛弃。该事件可能会被调
用多次。
 end :当请求体数据传输完成时,该事件被触发,此后将不会再有数据到来。
 close: 用户当前请求结束时,该事件被触发。不同于 end,如果用户强制终止了
传输,也还是调用close。



 获取 GET 请求内容

//httpserverrequestget.js 
var http = require('http'); 
var url = require('url'); 
var util = require('util'); 
http.createServer(function(req, res) { 
 res.writeHead(200, {'Content-Type': 'text/plain'}); 
 res.end(util.inspect(url.parse(req.url, true))); 
}).listen(3000);

在浏览器中输入http://127.0.0.1:3000/user?name=byvoid&email=byvoid@byvoid.com

Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?name=byvoid&email=byvoid@byvoid.com',
  query:
   [Object: null prototype] { name: 'byvoid', email: 'byvoid@byvoid.com' },
  pathname: '/user',
  path: '/user?name=byvoid&email=byvoid@byvoid.com',
  href: '/user?name=byvoid&email=byvoid@byvoid.com' 
}

  url.parse,原始的 path 被解析为一个对象,util.inspect是一个将任意对象转换为字符串,query 就是我们所谓的 GET请求的内容,而路径则是 pathname。

获取 POST 请求内容

POST 请求的内容全部都在请求体中。
http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是
一件耗时的工作,譬如上传文件。而很多时候我们可能并不需要理会请求体的内容,恶意的 POST请求会大大消耗服务器的资源。所以 Node.js 默认是不会解析请求体的,当你需要的时候,需要手动来做.

//httpserverrequestpost.js 
var http = require('http'); 
var querystring = require('querystring'); 
var util = require('util'); 
http.createServer(function(req, res) { 
 var post = ''; 
 req.on('data', function(chunk) { 
 post += chunk; 
 }); 
 req.on('end', function() { 
 post = querystring.parse(post); 
 res.end(util.inspect(post)); 
 }); 
}).listen(3000); 

上面代码并没有在请求响应函数中向客户端返回信息,而是定义了一个 post 变量,用
于在闭包中暂存请求体的信息。通过 req 的 data 事件监听函数,每当接受到请求体的数据,
累加到 post 变量中。在 end 事件触发后,通过 querystring.parse 将 post 解析为
真正的 POST 请求格式,然后向客户端返回。


 http.ServerResponse

http.ServerResponse 有三个重要的成员函数,用于返回响应头、响应内容以及结束请求
response.writeHead(statusCode, [headers]):向请求的客户端发送响应头。
statusCode 是 HTTP 状态码,如 200 (请求成功)、404 (未找到)等。headers 
是一个类似关联数组的对象,表示响应头的每个属性。
该函数在一个请求内最多只能调用一次,如果不调用,则会自动生成一个响应头

response.write(data, [encoding]):向请求的客户端发送响应内容。
data 是一个 Buffer 或字符串,表示要发送的内容。
如果 data 是字符串,那么需要指定encoding 来说明它的编码方式,默认是 utf-8。
在 response.end 调用之前,response.write 可以被多次调用。

response.end([data], [encoding]):结束响应,告知客户端所有发送已经完
成。当所有要返回的内容发送完毕的时候,该函数 必须 被调用一次。它接受两个可
选参数,意义和 response.write 相同。如果不调用该函数,客户端将永远处于
等待状态。


HTTP 客户端

http 模块提供了两个函数 http.request 和 http.get,功能是作为客户端向 HTTP服务器发起求
http.request(options, callback)发起 HTTP 请求。接受两个参数,option 是一个类似关联数组的对象,表示请求的参数,callback 是请求的回调函数。
callback 传递一个参数,为 http.ClientResponse 的实例
http.request 返回一个 http.ClientRequest 的实例

//httprequest.js 
var http = require('http'); 
var querystring = require('querystring'); 
var contents = querystring.stringify({ 
 name: 'byvoid', 
 email: 'byvoid@byvoid.com', 
 address: 'Zijing 2#, Tsinghua University', 
}); 
var options = { 
 host: 'www.byvoid.com', 
 path: '/application/node/post.php', 
 method: 'POST', 
 headers: { 
 'Content-Type': 'application/x-www-form-urlencoded', 
 'Content-Length' : contents.length 
 } 
}; 
var req = http.request(options, function(res) { 
 res.setEncoding('utf8'); 
 res.on('data', function (data) { 
 console.log(data); 
 }); 
}); 
req.write(contents); 
req.end(); 
http.get(options, callback) 于自动将请求方法设为了 GET 请求,同时不需要手动调用 req.end()。

//httpget.js 
var http = require('http'); 
http.get({host: 'www.byvoid.com'}, function(res) { 
 res.setEncoding('utf8'); 
 res.on('data', function (data) { 
 console.log(data); 
 }); 
});