Node.js学习笔记之HTTP 服务器与客户端

http.Server
http.Server 是一个基于事件的 HTTP 服务器,所有的请求都被封装为独立的事件, 开发者只需要对它的事件编写响应函数即可实现 HTTP 服务器的所有功能。它继承自 EventEmitter,提供了以下几个事件。

request:当客户端请求到来时,该事件被触发,提供两个参数 req 和res,分别是 http.ServerRequest 和 http.ServerResponse 的实例,表示请求和响应信息。
connection:当 TCP 连接建立时,该事件被触发,提供一个参数 socket,为 net.Socket 的实例。connection 事件的粒度要大于 request,因为客户端在 Keep-Alive 模式下可能会在同一个连接内发送多次请求。
close :当服务器关闭时,该事件被触发。注意不是在用户连接断开时。
在这些事件中,最常用的就是 request 了,因此 http 提供了一个捷径: http.createServer([requestListener]),功能是创建一个 HTTP 服务器并将 requestListener 作为 request 事件的监听函数

//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.ServerRequest
一般由 http.Server 的 request 事件发送,作为第一个参数传递,通常简称 request 或 req。


 获取 GET 请求内容
 由于 GET 请求直接被嵌入在路径 中,URL是完整的请求路径,包括了 ? 后面的部分,因此可以手动解析后面的内容作为 GET 请求的参数。Node.js 的 url 模块中的 parse 函数提供了这个功能
//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,我们可以看到浏览器返回的结果:

{ search: '?name=byvoid&email=byvoid@byvoid.com', 
  query: { 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 被解析为一个对象,其中 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 是返回给客户端的信息,决定了用户最终能看到的结果。
它也是由 http.Server 的 request 事件发送的,作为第二个参数传递,一般简称为 response 或 res。
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 是请求的回调函数。
option 常用的参数如下。

  • host :请求网站的域名或 IP 地址。
  • port :请求网站的端口,默认 80。
  • method :请求方法,默认是 GET。
  • path :请求的相对于根的路径,默认是“/”。QueryString 应该包含在其中。 例如 /search?query=byvoid。
  • headers :一个关联数组对象,为请求头的内容。

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(); 

运行后结果如下:

array(3) { 
  ["name"]=> 
  string(6) "byvoid" 
  ["email"]=> 
  string(17) "byvoid@byvoid.com" 
  ["address"]=> 
  string(30) "Zijing 2#, Tsinghua University" 
} 

http.get(options, callback) http 模块还提供了一个更加简便的方法用于处 理GET请求:http.get。它是 http.request 的简化版,唯一的区别在于http.get 自动将请求方法设为了 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); 
  }); 
}); 

http.ClientRequest
http.ClientRequest 是由 http.request 或 http.get 返回产生的对象,表示一 个已经产生而且正在进行中的 HTTP 请求。它提供一个 response 事件,即 http.request 或 http.get 第二个参数指定的回调函数的绑定对象。也可以显式地绑定这个事件的 监听函数:

//httpresponse.js  

var http = require('http');  

var req = http.get({host: 'www.byvoid.com'});  

req.on('response', function(res) { 
  res.setEncoding('utf8'); 
  res.on('data', function (data) { 
    console.log(data); 
  }); 
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值