zoukankan      html  css  js  c++  java
  • nodejs的某些api~(五) HTTP模块

    HTTP的模块是nodejs最重要的模块(应该是),最近在看HTTP权威指南,重新过了一遍http协议和web客户端。再来看这个http。

    HTTP构建于TCP之上,属于应用层协议,继承自tcp服务器(net模块),它能与多个客户端保持连接,由于基于事件驱动,并不为每个连接创建额外的进程或线程,所以能实现高并发;HTTP服务器与TCP服务器有区别的地方在于,在开启keepalive后,一个tcp会话可以用于多次请求和响应。TCP服务是以connection为单位进行服务,HTTP是以request为单位进行服务,HTTP模块就是将connection到request的过程进行了封装。

    http模块将连接所用的套接字的读写抽象为serverRequest和serverResponse对象,他们分别对应请求和响应。在请求产生过程中,http模块拿到连接中的数据,调用二进制模块http_parser进行解析,解析玩报文的报头后,触发request事件,调用用户的业务逻辑。

    HTTP的消息头通过对象表示
    { 'content-length': '123',
    'content-type': 'text/plain',
    'connection': 'keep-alive',
    'host': 'mysite.com',
    'accept': '*/*' }

    http.STATUS_CODES//例如http.STATUS_CODES[404]==='Not Found';
    http.createServer([requestListener]);//返回一个新的web服务器对象;

    类http.Server这是一个包含下列事件的EventEmitter
    事件'request'function(request,response){}
    //每次收到一个请求时触发,每个链接又可能有多个请求;
    //request是http.IncomingMessage的一个实例.response是http.ServerResponse的一个实例;
    事件'connection' function(socket){}
    //新的TCP流建立时触发。socket是一个net.Socket对象。通常用户无需处理改时间
    事件'close'
    事件'checkContinue'//每次收到Expect:100-continue的http请求时触发。如果未监听该事件,服务器会酌情发送100Continue响应
    事件'connect' function(request,socket,head){}//每次客户端发起CONNECT请求时触发。如果未监听该事件,客户端发起CONNECT请求时连接会被关闭
    //request是该http请求的参数;head是一个Buffer实例,隧道流的第一个包,可能为空
    //这个世界被分发后,请求的套接字将不会有data事件监听器,你需要绑定一个监听器到data事件,处理套接字被发送到服务器的数据
    事件'upgrade' function(request,socket,head){}//每当一个客户端请求http升级时触发;需要绑定data监听器
    事件'clientError'function(exception,socket){}//客户端触发一个error事件,被转发到此;
    server.listen(port,[hostname],[cb],[backlog],[callback])//开始在指定的主机名和端口接收连接
    //积压量backlog为连接等待队列的的最大长度。
    server.listen(path,[cb]);//启动一个unix套接字在所给路径path上监听连接;
    server.close([cb])//仅在服务端接收新连接
    server.maxHeadersCount//最大请求头目现在,默认1000个
    server.setTimeout(msecs,cb);//设置超时值,若超时,分发’timeout‘事件,同时将套接字做参传入;
    server.timeout//一个套接字被判为超时之时闲置的毫秒数;
    类http.ServerResponse//这是一个由HTTP服务器内部创建的对象,他将做为2参传递到'request'事件中;实现了weitable Stream接口,是一个包含下列事件的EventEmitter
    事件'close' function(){}//底层连接在response.end()或被调用或可以冲洗掉之前就被终结了。;
    response.writeContinue()//发送一个HTTP/1.1 100 Continue消息至客户端,表明请求体可被发送;
    response.writeHead(statusCode,[reasonPhrase],[headers])//向请求恢复响应头,statusCode是一个3位HTTP状态码;
    //headers是响应头的内容。把人类可读的‘原因短句’作为第二个参数;
    response.setTimeout(msecs,cb);
    response.statusCode//使用默认headers时,这个属性决定headers更新时被传回客户端的http状态码;
    response.setHeader(name,value)//为默认或已存在的头设置一条单独的头内容,如果已存在于将被送出的头重,将会覆盖其如果想设置更多的头,就会使用一个相同名字的字符串数组。
    ·response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
    ·response.setHeader("Content-Type","text/html");
    response.headersSent//如果headers发送完毕为true,反正为false;
    response.sendData//若为true,则当headers里没有Date值时自动生成Date并发送,默认true;
    response.getHeader(name)//读取一个在队列中但还没有被发送只客户端的header
    response.removeHeader(name)//取消一个在队列内等待发送的header
    response.write(chunk,[encoding])//发送一个响应体的数据块,可能被调用多次以防继承部分响应体;
    //chunk可以是字符串或缓存,若为字符串,2参表明如何将一个字符串编码为一个比特流。
    response.addTrailers(headers)//这个方法添加HTTP尾随headers给响应;
    //只有当数据块编码被用于响应时尾随才会被触发,如果不是,会被自动丢弃;
    //如果触发尾随消息,HTTP要求一个报文头场列表和Trailer报头一起发送;
    response.writeHead(200, { 'Content-Type': 'text/plain',
    'Trailer': 'Content-MD5' });
    response.write(fileData);
    response.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"});
    response.end();
    response.end([data],[encoding]);//当所有响应报头和报文被发送完成时,这个方法将信号发送给服务器,服务器会认为消息完成了,每次响应完成必须调用此;
    http.request(options,cb);
    //node维护几个连接每个服务器的HTTP请求,这个函数允许后台发布请求。
    //options可以是一个对象或一个字符串。如果options是一个字符串,它将自动使用url.parse()解析;
    host:请求发送到的服务器的域名或IP地址。默认为'localhost'。
    hostname:用于支持url.parse()。hostname比host更好一些
    port:远程服务器的端口。默认值为80。
    localAddress:用于绑定网络连接的本地接口。
    socketPath:Unix域套接字(使用host:port或socketPath)
    method:指定HTTP请求方法的字符串。默认为'GET'。
    path:请求路径。默认为'/'。如果有查询字符串,则需要包含。例如'/index.html?page=12'。请求路径包含非法字符时抛出异常。目前,只否决空格,不过在未来可能改变。
    headers:包含请求头的对象。
    auth:用于计算认证头的基本认证,即'user:password'
    agent:控制Agent的行为。当使用了一个Agent的时候,请求将默认为Connection: keep-alive。可能的值为:
    undefined(默认):在这个主机和端口上使用[全局Agent][]。

    此例构造了一个http客户端,node模拟的客户端请求。

    var options={
        hostname:‘127.0.0.1’,
        port:1334,
        path:'/',
        method:'GET'
    }
    var req=http.request(options,function(res){
       console.log('STAUS: '+res.statusCode);
       console.log('HRADERS: '+JSON.stringify(res.headers));
       res.setEncoding(utf8);
       res.on('data',function(chunk){
           console.log(chunk);
       })   
    })
    req.end()

    Agent对象:在Agent中显式使用passed。
    false:在对Agent进行资源池的时候,选择停用连接,默认请求为:Connection: close。
    keepAlive:{Boolean} 保持资源池周围的套接字在未来被用于其它请求。默认值为false
    keepAliveMsecs:{Integer} 当使用HTTP KeepAlive的时候,通过正在保持活动的套接字发送TCP KeepAlive包的频繁程度。默认值为1000。仅当keepAlive被设置为true时才相关。
    //http.request()返回一个http.ClientRequest类的实例。ClientRequest实例是一个可写流对象,如果需要用post请求上传一个文件的话,将其写入到ClientRequest对象;
    http.get(options,cb)//与http.request()唯一区别是它设置的是get方法并自动调用req.end();

    http.get("http://www.google.com/index.html", function(res) {
      console.log("响应:" + res.statusCode);
    }).on('error', function(e) {
      console.log("错误:" + e.message);
    });

    类http.Agent

    //用于把套接字做成资源池,用于http客户端请求;

    http服务器默认的客户端代理对象http.globalAgent,它对每个服务器端创建的连接进行管理,默认情况下,对同一个服务器端发起的http请求最多创建5个链接,它的实质是一个连接池。

    我们可以自行构造代理对象。

    var agent=new http.Agent({
       maxSockets:10 
    })
    var options={
        hostname:"127.0.0.1",
        post:1334,
        path:"/",
        method:"GET",
        agent:agent
    };

    也可以设置agent为false,就脱离连接池的管理,使请求不受并发的限制。

    http Agent把客户端请求默认使用Connection:keep-alive。如果没有http请求在等待成为空闲的套接字,那么套接字将关闭。

    当套接字触发了close事件或特殊的agentRemove事件的时候,套接字从agent资源池中移出。

    如果你打算保持一个http请求长时间开启,并不希望它保持在资源池中,那么你可以按照下列代码:

    http.get(options,function(res){
        //..dosomething
    }).on('socket',function(socket){
        socket.emit('agentremove')
    })
    可用agent:false选择完全停用资源池;
    http.get({
        hostname:'localhost',
        port:80,path:'/',agent:false,
    },function(res){//..})

    类http.ClientRequest

    //该对象在内部创建,并由http.request()返回。他表示着一个正在处理的请求,其头部已经进入请求队列。

    //该头部仍可以通过setHeader(name,value),getHeader(name),removeHeader(name)等api修改;

    //为了获取响应对象,给请求对象添加一个'response'监听器。当接收到响应头时,请求对象会触发'response',该事件执行时有一个参数,参数为http.IncomingMessage的一个实例

    在'response'事件期间,可以为响应对象添加监听器,尤其是'data事件'。

    Event 'response'

    function(res){}//当接收到请求的响应时触发,只被触发一次。response参数是http.http.IncomingMessage的一个实例;

    事件'socket'//触发于一个套接字被赋予为这个请求的时候

    事件'connect'//每次服务器使用connect方法响应一个请求时被触发。如果该事件未被监听,接收connect方法的客户端将关闭它们的连接;

    socket.write('GET /HTTP/1.1
    '+'Host:www.google.com:80
    '+'Connection:close
    '+'
    ');
    socket.on('data',function(chunk){
        console.log(chunk.toString());
    })
    socket.on('end',function(){
        proxy.close();
    })

    事件'upgrade' function(response,socket,head){}

    //每次服务器返回upgrade响应时触发。如果事件为被监听,客户端收到upgrade后将关闭连接

    req.on('upgrade',function(res,socket,upgradeHead){
        console.log('got upgrade!');
        socket.end();
        process.exit(0);
    })

    事件'continue' 

    //当服务器发送100 continue响应时触发,通常是因为请求保护Expect:100-contine,该指令表示客户端应发送请求体。

    request.write(chunk,[encoding])

    //发送一块请求体。调用多次。用户可以流式发送请求体至服务器--在这种情况下,创建请求时建议使用['Transfer-Encoding','chunked']当所有响应报头和报文被发送完成时,这个方法将信号发送给服务器,服务器会认为消息完成了,每次响应完成必须调用此;

    request.end([data],[encoding])

    //结束发送请求。

    request.abort()//终止一个请求;

    request.setTimeout(timeout,[cb])//一旦一个套接字被分配给该请求并且完成连接,socket.setTimeout()将被调用

    request.setNoDelay([noDelay])//一旦一个套接字被分配到一个请求  同上

    http.http.IncomingMessage; 一个IncomingMessage对象由http.server或者http.http.ClientRequest创建的。并作为第一参数分别传递给'request'和'response'事件。它也可以被用来访问应答的状态,头文件和数据。’

    事件'close'表示在response.end()被掉用或强制刷新之前,底层的连接已经被终止了。

  • 相关阅读:
    Beta版本冲刺第二天 12.6
    Beta版本冲刺第一天 12.5
    Linux学习(2)—— 图形化界面
    Linux学习(1)—— 虚拟机安装Linux系统
    IntelliJ IDEA使用
    spring+springmvc+hibernate 整合
    新的篇章
    软件工程实践总结作业——个人作业
    Beta版本冲刺———第七天
    Beta版本冲刺———第六天
  • 原文地址:https://www.cnblogs.com/dh-dh/p/5090356.html
Copyright © 2011-2022 走看看