上一章介绍了如何在nodejs中构造httpserver以及在nodejs中如何构造httpclient来访问httpserver,接下来说一下nodejs在http交互中是如何处理请求的。首先我们回顾一下上一章最后的例子:
server代码(server把请求头信息处理后作为响应消息返回给client):
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
//response.end('Hello World\n');
response.end(util.inspect(url.parse(request.url, true)));
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
把server代码保存在在test8.js中,然后通过node test8.js命令来启动httpserver(如果之前已经启动,则需要停止以后再启动,截图略)。
client代码:
var http = require('http');
// 用于请求的选项
var options = {
host: 'localhost',
port: '8888',
path: '/test?params1="123"¶ms2=456'
};
// 处理响应的回调函数
var callback = function(response){
// 不断更新数据
var body = '';
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
// 数据接收完成
console.log(body);
});
}
// 向服务端发送请求
var req = http.request(options, callback);
req.end();
把client代码保存在在test9.js中,然后另开一个命令行窗口通过node test9.js命令来启动httpclient并访问httpserver(如果之前已经启动,则需要停止以后再启动):
client代码并没有显式地表达自己发送的是get请求还是post请求,但是通常情况下应该是默认发送get请求,下面我们来看一下http.request函数的参数描述:
可以看到在参数options里有一个method属性,默认值为get,这个属性确定了client发送的是get请求还是post请求。OK,目前我们可以确认client发送的get请求,再检查一下server代码是怎么处理client的请求信息:
上一章的例子里变更了client的请求路径(options里的path),server一样可以正常响应,下面来尝试变更client的请求方式,来验证server是否同样不感知,以下是client代码:
var http = require('http');
// 用于请求的选项
var options = {
host: 'localhost',
port: '8888',
path: '/test?params1="123"¶ms2=456' ,
method: 'POST'
};
// 处理响应的回调函数
var callback = function(response){
// 不断更新数据
var body = '';
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
// 数据接收完成
console.log(body);
});
}
// 向服务端发送请求
var req = http.request(options, callback);
//构造post消息体
data = {user:"hello",password:"world"};
req.write(require('querystring').stringify(data));
req.end();
以下为变更说明:
把变更后的client代码保存在在test9.js中,然后另开一个命令行窗口通过node test9.js命令来启动httpclient并访问httpserver(如果之前已经启动,则需要停止以后再启动):
可以看到请求依然正常得到了响应,这也证明了上例的server并不感知任何client发送的信息(不论是post消息体、http头还是url)。但是在实际的项目开发中,一个不能感知请求详情的server并没有什么卵用,接下来给出一个说明server如何读取client发送信息的例子:
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function (request, response) {
console.log(request.method);
if(request.method == "GET"){
console.log("enter GET");
}else{
var postdata = "";
request.on("data",function(postchunk){
postdata += postchunk;
});
request.on("end",function(){
console.log(postdata);
});
}
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
//response.end('Hello World\n');
response.end(util.inspect(url.parse(request.url, true)));
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
以下为变更说明:
把变更的server代码保存在在test8.js中,然后通过node test8.js命令来启动httpserver(如果之前已经启动,则需要停止以后再启动),再另开一个命令行窗口通过node test9.js命令来启动httpclient并访问httpserver(如果之前已经启动,则需要停止以后再启动),下面看一下server的打印信息:
可以看到server正常打印了请求类型以及post请求的消息体(由于client未声明post消息体数据类型,默认是按字符串处理,所以虽然在client侧消息体是一个json,但在server侧打印的接收到的post消息体是一个字符串)。
实际上只要能够明确请求类型和请求url(对应url对象的path,即请求路径),即可确定一个server端提供的接口(通常接口文档都是依据这两个信息来区分不同的接口),而请求信息的获取和操作则属于业务行为。post消息体的获取和使用属于纯业务操作(与接口无关,接口定义不care数据该如何获取和获取到的数据该如何使用),而http头的获取和使用则涉及安全(如sessionid、tls安全协议等等)。