node.js中提供了http和https模块,专用于创建HTTPS服务器、HTTP客户端,以及HTTPS服务器及HTTPS客户端,同时实现这些服务器与客户端之间所需进行的处理

  • 创建HTTP服务器
  • 使用HTTP服务器接收客户端请求数据
  • 使用HTTP服务器向客户端返回响应数据
  • 使用node.js制作HTTP客户端
  • 使用node.js制作代理服务器
  • 创建HTTPS服务器
  • 创建HTTPS客户端

1 HTTP服务器

只需要调用http模块中的create Server方法就可创建一个HTTP服务器

var server = http.createServer([requestListener])
  • 使用一个可选参数,参数值为一个回调函数,用于指定当前接收客户端请求时所需要执行的处理,该回调函数的指定方法如下:

      function (request, response) {
          // 回调函数代码
      }
    
    • 第一个参数: http.IncomingMessage对象,代表一个客户端请求
    • 第二个参数: http.ServerResponse对象,代表一个服务器端响应对象
  • 在listeng方法中指定服务器端开始监听时调用的回调函数

var http = require('http');
var server = http.createServer(function (req, res) {
    // 暂时不指定接收到客户端请求时的处理
}).listen(1337, "127.0.0.1", function() {
    console.log('服务器端开始监听');
});

1.2 获取客户端请求信息

HTTP服务器端请求时调用的回调函数中的第一个参数值为一个http.IncomingMessage对象,该对象用于读取客户端请求流中数据 当从客户端请求流中读取到新的数据时触发data事件,当读取完客户端请求流中的数据时触发end事件。 当该对象被用于读取客户端请求流中的数据时,该对象拥有以下属性:

  • method: 属性值为一个字符串,字符串值为客户端向服务端发送请求时使用的方法,GET、POST、PUT、DELETE

  • url: 该属性值为客户端发送请求使用的URL参数字符串

  • headers: 属性值为客户端发送的请求头对象,其中存放了客户端发送的所有请求头信息,包括各种cookie信息以及浏览器的各种信息

  • httpVersion:该属性值为一个字符串,字符串值为客户端发送的HTTP版本

  • trailers:该属性值为客户端发送的trailer对象。该对象中存放了客户端附加的一些HTTP头信息,该对象被包含在客户端发送的请求数据之后,因此只有当http.IncomingMessage对象的end事件触发之后才能读取到的trailer对象中的信息

  • socket: 该属性值为服务器端用于监听客户端请求的socket对象

  • 在文件中保存客户端情求信息

var http = require('http');
var fs = require('fs');
var server=http.createServer(function (req, res) {    if(req.url!=="/favicon.ico"){        var out=fs.createWriteStream('./request.log');        out.write('客户端请求所用方法为:'+req.method+'\r\n');        out.write('客户端请求所用url字符串为:'+req.url+'\r\n');        out.write('客户端请求头对象为:'+JSON.stringify(req.headers)+'\r\n');        out.end('客户端请求所用HTTP版本为:'+req.httpVersion);    }    res.end();}).listen(1337, "127.0.0.1");
  • 一个实例
<!--用于测试data事件与end事件回调函数的HTML页面代码-->
<!DOCTYPE html>
<html>
    <head>
        <title> Node.js的事件与end事件的回调函数测试页面</title>
    </head>
    <body>
        <form id="form1" action="http:// localhost:1337/" method="post">
            姓名:<input type="text" name="name" value="牛展">
            <br />
            年龄:<input type="text" name="age" value="40">
            <input type="submit" value="提交"/>
        </form>
    </body>
</html> 
// 该实例后端接口
var http = require('http');
var fs = require('fs');
var server = http.createServer(function (req, res) {
    if (req.url !== "/favicon.ico") {
        req.on('data', function(data) {
            console.log('服务器端接收到数据: ', decodeURLComponent(data));
        })
        req.on('end', function () {
            console.log('客户端请求数据已去拿不接收完毕');
        });
    }
    res.end();
}).listen(1337, "127.0.0.1");

1.3 转换URL字符串与查询字符串

在Node.js中,提供了一个url模块与一个Query String模块,分别用来转换完整URL字符串与URL中的查询字符串

  • 一个完整的URL字符串从?字符之后到#字符之前,称为查询字符串

  • 可以使用Query String模块中的parse方法将该字符串转换为一个对象

    • querystring.parse(str, [sep], [ep], [optiona])
  • parse()解析:

    • str: 指定参数,(用于指定被转换的查询字符串)
    • sep、eq、options参数为可选参数
    • sep: 用于指定该查询字符串中的分割字符,默认为:“&”
    • eq: 用于指定该查询字符串中的分配字符,默认参数值为“=”
    • options参数:一个对象,可以在该对象中使用一个整数值类型的maxKeys属性来指定转换后的对象中的属性个数,如果将maxKeys属性值设定为0,其效果等于不使用maxKeys属性值。
querystring.parse('username=Luling&age=40&sex=male');
// 输出
{
    username: 'Luling',
    age: '40',
    sex: 'male',
}

querystring.parse('username=Luling&age=40&sex=male', '!')
//输出
{
    username:'Lulingniu&age=40&sex=male'
}

querystring.prase('username=Luling&age=40&sex=male', '&')
//输出
{
    username: 'Luling',
    age: '40',
    sex: 'male',
}

querystring.parse('userName=Lulingniu!age=40!sex=male','!');
{ username:'Lulingniu',    age:'40',    sex:'male'}

querystring.parse('username=Luling&age=40&sex=male', '&', ':');
//输出
{ 'userName=Lulingniu':'',    'age=40':'',    'sex=male':''}


querystring.parse('username=Liling&age=40&sex=male', '&', '=');
//输出
{
    username: 'Luling',
    age: '40',
    sex: 'male',
}

// ...
  • 可以使用Query String模块中的stringify()将对象转换为一个查询字符串,stringify()的使用:
querystring.stringify(obj, [seq], [ep])
  • 参数解析:
    • obj: 指定参数
    • sep: 分割字符。默认数值为&
    • eq: 指定查询字符串中使用的分配字符,默认为=
querystring.stringify({username:'赵云龙', age:'40', sex: 'male'})
// 输出
'userName=Lulingniu&age=40&sex=male'
  • url模块

    • 在url模块中,可以使用parse方法将URL字符串转换为一个对象,根据URL字符串中的不同内容,该对象中可能具有的属性及其含义不同。
      • href: 被转换的原URL字符串
      • protocol:客户端发出请求时使用的协议
      • slashes:在协议与路径中间是否使用“//”分隔符
      • host:URL字符串中的完整地址及端口号,可以是IP地址也可以是一个主机名
      • auth:URL字符串中的认证信息部分
      • hostname:URL字符串中完整地址,该地址可能为一个IP地址或主机名
      • port:URL字符串中的端口号
      • pathname: URL字符串中的路径,不包含查询字符串
      • search:URL字符串中的查询字符串,包含起始字符“?”
      • path:URL字符串中的路径,包含查询字符串
      • query:URL字符串中的查询字符串,不包含起始字符“?”, 或根据该查询字符串而转换的对象(根据parse()所用参数而决定query属性值)
      • hash:URL字符串中的散列字符串,包含起始字符“#”
  • parse()方法的使用方式如下

      url.parse(urlStr, [parseQueryString])
    
    • 在parse方法中,使用两个参数,其中urlStr参数为必须输入参数,parseQueryString参数为可选参数。urlStr参数用于指定需要转换的URL字符串;parseQueryString参数为一个布尔类型的参数,当参数值为true时,内部使用Query String模块将查询字符串转换为一个对象,参数值为false时不执行该转换操作,默认参数值为false.
url.parse('http://user:pass@host.com:8080/users/user.php?userName=Luling&age=40&sex=male#name1');
// 输出
{
    protocol: 'http',
    slashes: true,
    auth: 'user:pass',
    host: 'host.com:8080',
    port: '8080',
    hostname: 'host.com',
    hash: '#name1',
    search: '?userName=Lulingniu&age=40&sex=male',
    query: 'userName=Lulingniu&age=40&sex=male',
    pathname: '/users/user.php',
    path: 'users/user.php?userName=Lulingniu&age=40&sex=male',
    href: 'http://user:pass@host.com:8080/users/user.php?userName=Luling&age=40&sex=male#name1'
}

url.parse('http://user:pass@host.com:8080/users/user.php?userName=Luling&age=40&sex=male#name1', true);
// 输出
{
    protocol: 'http',
    slashes: true,
    auth: 'user:pass',
    host: 'host.com:8080',
    port: '8080',
    hostname: 'host.com',
    hash: '#name1',
    search: '?userName=Lulingniu&age=40&sex=male',
    query: {
        userName: 'Luling',
        age: '40',
        sex: 'male'
    },
    pathname: '/users/user.php',
    path: 'users/user.php?userName=Lulingniu&age=40&sex=male',
    href: 'http://user:pass@host.com:8080/users/user.php?userName=Luling&age=40&sex=male#name1'
}

  • 使用url模块中的format()将URL字符串经过转换后的对象还原为一个URL字符串

    • url.format(urlObj)
  • 使用parse()解析url地址字符串

var http = require('http'), url = require('url');
var server = http.createServer().listen(1337, 'localhost');
sever.on('request', function (req, res) {
    if (req.url !== '/favicon.ico') {
        res.write('<html><head><meta charset="utf-8"/></head>');
        var url_parts = url.parse(req.url);
        switch(url_parts.pathname) {
            case: '/':
            case: '/index.html':
            res.write('<body>您当前正在访问网站首页。</body></html>');                
            break;
            default: res.write('<body>您当前正在访问的页面为'+url_parts.pathname+'。</body></html>');
        }
    }
    res.end();
});

1.4 发送服务端响应流

在createServer()的参数值回调函数或服务器对象的request事件函数中的第二个参数值为一个http.ServerResponse对象,可以利用该对象发送服务器端响应流

  • 利用http.ServerResponse对象的writeHead()方法来发送响应头信息

      response.writeHead(statusCode, [reasonPhrase], [headers])
    
    • 参数解析
      • statusCode: 必须输入参数
      • reasonPhrase: 指定一个三位数的HTTP状态码,如404
      • reasonPhrase: 指定对于该状态码的描述信息,是一个对象,用于指定服务器创建的响应头对象
  • 在响应头中常用的字段

    • content-type: 用于指定内容类型
    • location: 用于将客户端重定向到另一个URL地址
    • content-disposition: 用于指定一个被下载的文件对象
    • content-length: 用于指定服务器响应内容的字节数
    • set-cookie: 用于在客户端创建一个cookie
    • content-encoding: 用于指定服务器端响应内容的编码方式
    • Cache-Control: 是否开启缓存机制
    • Expires: 指定缓存过期时间
    • Etag:指定当服务器端响应内容没有变化时,不重新下载数据

2 HTTP客户端

P436