原文:https://github.com/chyingp/nodejs-learning-guide

自己敲代码:

概览

http模块四剑客之一的res,应该都不陌生了。一个web服务程序,接受到来自客户端的http请求后,向客户端返回正确的响应内容,这就是res的职责。

返回的内容包括:状态代码/状态描述信息、响应头部、响应主体。下文会举几个简单的例子。

var http = require('http');
var server = http.createServer(function(req, res){
res.send('ok');
});
server.listen(3000);

例子

在下面的例子中,我们同时设置了 状态代码/状态描述信息、响应头部、响应主体,就是这么简单。

var http = require('http');

// 设置状态码、状态描述信息、响应主体
var server = http.createServer(function(req, res){
res.writeHead(200, 'ok', {
'Content-Type': 'text/plain'
});
res.end('hello');
}); server.listen(3000);

设置状态代码、状态描述信息

res提供了 res.writeHead()、res.statusCode/res.statusMessage 来实现这个目的。

举例,如果想要设置 200/ok ,可以

res.writeHead(200, 'ok');

也可以

res.statusCode = 200;
res.statusMessage = 'ok';

两者差不多,差异点在于

  1. res.writeHead() 可以提供额外的功能,比如设置响应头部。
  2. 当响应头部发送出去后,res.statusCode/res.statusMessage 会被设置成已发送出去的 状态代码/状态描述信息。

设置响应头部

res提供了 res.writeHead()、response.setHeader() 来实现响应头部的设置。

举例,比如想把 Content-Type 设置为 text-plain,那么可以

// 方法一
res.writeHead(200, 'ok', {
'Content-Type': 'text-plain'
}); // 方法二
res.setHeader('Content-Type', 'text-plain');

两者的差异点在哪里呢?

  1. res.writeHead() 不单单是设置header。
  2. 已经通过 res.setHeader() 设置了header,当通过 res.writeHead() 设置同名header,res.writeHead() 的设置会覆盖之前的设置。

关于第2点差异,这里举个例子。下面代码,最终的 Content-Type 为 text/plain。

var http = require('http');

var server = http.createServer(function(req, res){
res.setHeader('Content-Type', 'text/html');
res.writeHead(200, 'ok', {
'Content-Type': 'text/plain'
});
res.end('hello');
}); server.listen(3000);

而下面的例子,则直接报错。报错信息为 Error: Can't set headers after they are sent.。

var http = require('http');

var server = http.createServer(function(req, res){
res.writeHead(200, 'ok', {
'Content-Type': 'text/plain'
});
res.setHeader('Content-Type', 'text/html');
res.end('hello');
}); server.listen(3000);

其他响应头部操作

增、删、改、查 是配套的。下面分别举例说明下,例子太简单就直接上代码了。

// 增
res.setHeader('Content-Type', 'text/plain'); // 删
res.removeHeader('Content-Type'); // 改
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Type', 'text/html'); // 覆盖 // 查
res.getHeader('content-type');

其中略显不同的是 res.getHeader(name),name 用的是小写,返回值没做特殊处理。

res.setHeader('Content-Type', 'TEXT/HTML');
console.log( res.getHeader('content-type') ); // TEXT/HTML res.setHeader('Content-Type', 'text/plain');
console.log( res.getHeader('content-type') ); // text/plain

此外,还有不那么常用的:

  • res.headersSent:header是否已经发送;
  • res.sendDate:默认为true。但为true时,会在response header里自动设置Date首部。

设置响应主体

主要用到 res.write() 以及 res.end() 两个方法。

res.write() API的信息量略大,建议看下官方文档。

response.write(chunk[, encoding][, callback])

  • chunk:响应主体的内容,可以是string,也可以是buffer。当为string时,encoding参数用来指明编码方式。(默认是utf8)
  • encoding:编码方式,默认是 utf8。
  • callback:当响应体flushed时触发。(TODO 这里想下更好的解释。。。)

使用上没什么难度,只是有些注意事项:

  1. 如果 res.write() 被调用时, res.writeHead() 还没被调用过,那么,就会把header flush出去。
  2. res.write() 可以被调用多次。
  3. 当 res.write(chunk) 第一次被调用时,node 会将 header 信息 以及 chunk 发送到客户端。第二次调用 res.write(chunk) ,node 会认为你是要streaming data(WTF,该怎么翻译)。。。

Returns true if the entire data was flushed successfully to the kernel buffer. Returns false if all or part of the data was queued in user memory. 'drain' will be emitted when the buffer is free again.

response.end([data][, encoding][, callback])

掌握了 res.write() 的话,res.end() 就很简单了。res.end() 的用处是告诉nodejs,header、body都给你了,这次响应就到这里吧。

有点像个语法糖,可以看成下面两个调用的组合。至于callback,当响应传递结束后触发。

res.write(data, encoding);
res.end()

chunk数据

参考这里:http://stackoverflow.com/questions/6258210/how-can-i-output-data-before-i-end-the-response

也就是说,除了nodejs的特性,还需要了解 HTTP协议、浏览器的具体实现。(细思极恐)

如果是 text/html

var http = require('http');

http.createServer(function(req, res) {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.write('hello'); setTimeout(function() {
res.write(' world!');
res.end();
}, 2000); }).listen(3000);

如果是 text/plain

var http = require('http');

http.createServer(function (req, res) {
res.writeHead(200, {
'Content-Type': 'text/plain; charset=utf-8',
'X-Content-Type-Options': 'nosniff'
});
res.write('hello'); setTimeout(function(){
res.write('world');
res.end()
}, 2000); }).listen(3000);

失败例子

var http = require('http');

var server = http.createServer(function(req, res){
res.writeHead(200, 'ok', {
'Content-Type': 'text/html'
});
res.write('hello'); setTimeout(function(){
res.write('world');
res.end();
}, 2000);
}); server.listen(3000);

超时处理

接口:response.setTimeout(msecs, callback)

关于 timeout 事件的说明,同样是言简意赅(WTF),话少信息量大,最好来个demo TODO

If no 'timeout' listener is added to the request, the response, or the server, then sockets are destroyed when they time out. If you assign a handler on the request, the response, or the server's 'timeout' events, then it is your responsibility to handle timed out sockets.

事件 close/finish

  • close:response.end() 被调用前,连接就断开了。此时会触发这个事件。
  • finish:响应header、body都已经发送出去(交给操作系统,排队等候传输),但客户端是否实际收到数据为止。(这个事件后,res 上就不会再有其他事件触发)

其他不常用属性/方法

  • response.finished:一开始是false,响应结束后,设置为true。
  • response.sendDate:默认是true。是否自动设置Date头部。(按HTTP协议是必须要的,除非是调试用,不然不要设置为false)
  • response.headersSent:只读属性。响应头部是否已发送。
  • response.writeContinue():发送 HTTP/1.1 100 Continue 消息给客户端,提示说服务端愿意接受客户端的请求,请继续发送请求正文(body)。(TODO 做个demo啥的是大大的好)

相关链接

How can I output data before I end the response? http://stackoverflow.com/questions/6258210/how-can-i-output-data-before-i-end-the-response

8.2.3 Use of the 100 (Continue) Status http://greenbytes.de/tech/webdav/rfc2616.html#use.of.the.100.status

NodeJS学习笔记 (6)网络服务-http-res(ok)的更多相关文章

  1. NodeJS学习笔记 (9)网络服务-https(ok)

    模块概览 这个模块的重要性,基本不用强调了.在网络安全问题日益严峻的今天,网站采用HTTPS是个必然的趋势. 在nodejs中,提供了 https 这个模块来完成 HTTPS 相关功能.从官方文档来看 ...

  2. NodeJS学习笔记 (8)网络服务-http-server(ok)

    http服务端概览 创建server 几行代码搞定 var http = require('http'); var requestListener = function(req, res){ res. ...

  3. NodeJS学习笔记 (5)网络服务-http-req(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: 概览 本文的重点会放在req这个对象上.前面已经提到,它其实是http.Incom ...

  4. NodeJS学习笔记 (7)网络服务-http-client(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: ClientRequest概览 当你调用 http.request(options ...

  5. NodeJS学习笔记 (4)网络服务-http(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: http模块概览 大多数nodejs开发者都是冲着开发web server的目的选 ...

  6. nodejs学习笔记之网络编程

    了解一下OSI七层模型   OSI层 功能 TCP/IP协议 应用层 文件传输,电子邮件,文件服务,虚拟终端  TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层 数据格式化 ...

  7. NodeJS学习笔记 (10)网络TCP-net(ok)

    模块概览 net模块是同样是nodejs的核心模块.在http模块概览里提到,http.Server继承了net.Server,此外,http客户端与http服务端的通信均依赖于socket(net. ...

  8. NodeJS学习笔记 (12)网络地址解析-url(ok)

    模块概述 nodejs中,提供了url这个非常实用的模块,用来做URL的解析.在做node服务端的开发时会经常用到.使用很简单,总共只有3个方法. 正式讲解前,各位同学先把下面这个图记在心上(来自no ...

  9. NodeJS学习笔记 (11)网络UDP-dgram(ok)

    模块概览 dgram模块是对UDP socket的一层封装,相对net模块简单很多,下面看例子. UPD客户端 vs UDP服务端 首先,启动UDP server,监听来自端口33333的请求. se ...

随机推荐

  1. 一个关于传参数js数组的封装方法(寄生模式)

    function createArr(){ var arr = new Array(); arr.push.apply(arr,arguments); arr.toJoin = function(){ ...

  2. CorelDRAW X6最新注册激活机制

    最近购买CorelDRAW X6的小伙伴可能对如何注册激活软件存在疑惑,下面小编一步步教您如何快速激活CorelDRAW X6. CorelDRAW X6最新注册机制如下: 1.关注“Corel服务中 ...

  3. Pyhton二级操作题练习

    # 1.编写一个python程序,输入两个数,比较它们的大小并输出其中较大者. num1 = input('请输入数字X:') num2 = input('请输入数字Y:') if num1.isde ...

  4. VUE:模板语法(小白自学)

    VUE:模板语法 一:何为声明式 安装规定的语法,去实现一些效果(不需要管流程). 二:模板语法 <!DOCTYPE html> <html> <head> < ...

  5. CodeForces 362E Petya and Pipes

    Petya and Pipes Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

  6. POJ——T 3159 Candies

    http://poj.org/problem?id=3159 Time Limit: 1500MS   Memory Limit: 131072K Total Submissions: 33328   ...

  7. Qt之二维码扫描

    简述 二维码(QR Code)是用某种特定的几何图形按一定规律在平面(二维方向)分布的黑白相间的图形记录数据符号信息的.是所有信息数据的一把钥匙.应用十分广泛,如:产品防伪/溯源.广告推送.网站链接. ...

  8. 【Bootstrap】一个PC、平板、手机同一时候使用并且美观的登陆页面

    Bootstrap如同前台框架,它已经布置好不少的CSS.前端开发的使用须要则直接调用就可以.其站点的网址就是http://www.bootcss.com.使用Bootstrap能降低前端开发时候在C ...

  9. simple_strtoul()分析

    此函数有以下几点值得注意:1.第一个参数中的const.一般在函数的形参中,如果我们只是希望调用者使用该参数,而不会去改变该参数内容(一般是指针指向的内容),则可以声明为const.2.第二个参数.C ...

  10. iOS中respondsToSelector与conformsToProtocol的相关理解和使用

    respondsToSelector相关的方法 : -(BOOL) isKindOfClass: classObj 用来判断是否是某个类或其子类的实例 -(BOOL) isMemberOfClass: ...