NodeJS学习笔记 (6)网络服务-http-res(ok)
原文: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';
两者差不多,差异点在于
- res.writeHead() 可以提供额外的功能,比如设置响应头部。
- 当响应头部发送出去后,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');
两者的差异点在哪里呢?
- res.writeHead() 不单单是设置header。
- 已经通过 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 这里想下更好的解释。。。)
使用上没什么难度,只是有些注意事项:
- 如果 res.write() 被调用时, res.writeHead() 还没被调用过,那么,就会把header flush出去。
- res.write() 可以被调用多次。
- 当 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)的更多相关文章
- NodeJS学习笔记 (9)网络服务-https(ok)
模块概览 这个模块的重要性,基本不用强调了.在网络安全问题日益严峻的今天,网站采用HTTPS是个必然的趋势. 在nodejs中,提供了 https 这个模块来完成 HTTPS 相关功能.从官方文档来看 ...
- NodeJS学习笔记 (8)网络服务-http-server(ok)
http服务端概览 创建server 几行代码搞定 var http = require('http'); var requestListener = function(req, res){ res. ...
- NodeJS学习笔记 (5)网络服务-http-req(ok)
原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: 概览 本文的重点会放在req这个对象上.前面已经提到,它其实是http.Incom ...
- NodeJS学习笔记 (7)网络服务-http-client(ok)
原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: ClientRequest概览 当你调用 http.request(options ...
- NodeJS学习笔记 (4)网络服务-http(ok)
原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: http模块概览 大多数nodejs开发者都是冲着开发web server的目的选 ...
- nodejs学习笔记之网络编程
了解一下OSI七层模型 OSI层 功能 TCP/IP协议 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层 数据格式化 ...
- NodeJS学习笔记 (10)网络TCP-net(ok)
模块概览 net模块是同样是nodejs的核心模块.在http模块概览里提到,http.Server继承了net.Server,此外,http客户端与http服务端的通信均依赖于socket(net. ...
- NodeJS学习笔记 (12)网络地址解析-url(ok)
模块概述 nodejs中,提供了url这个非常实用的模块,用来做URL的解析.在做node服务端的开发时会经常用到.使用很简单,总共只有3个方法. 正式讲解前,各位同学先把下面这个图记在心上(来自no ...
- NodeJS学习笔记 (11)网络UDP-dgram(ok)
模块概览 dgram模块是对UDP socket的一层封装,相对net模块简单很多,下面看例子. UPD客户端 vs UDP服务端 首先,启动UDP server,监听来自端口33333的请求. se ...
随机推荐
- svn: E155017: Checksum mismatch while updating 校验错误的解决方法
[10.3.53.53:/EMRCV5]# svn up svn: E155004: Working copy '/EMRCV5' locked. svn: E155004: '/EMRCV5' is ...
- Day73-CMDB(资产管理采集)的三种实现方式
# 采集数据 import subprocess import requests ret = subprocess.getoutput('ipconfig') # print(ret) # 正则处理获 ...
- SQLserver 导入超大CSV(100G以上)方法
1.似乎SQLSERVER2008对UTF8不兼容,采用SQLSERVER20052.采用SQLSERVER2005,还是出现UTF8诸如此类的问题,修改表结构,varchar改成 nvarchar3 ...
- jquery获得url的get参数
只是用了第一种方法,简单好用直接传入想要获取的参数名,即可返回参数值 function GetQueryString(name) { var reg = new RegExp("( ...
- nignx 502错误不能使用/的路径方式 即pathinfo
在server中加入 include enable-php-pathinfo.conf; 引入nginx.conf下的这个文件即可. 如果是tp框架,主要隐藏index.php的入口文件,再加入下面这 ...
- Error: Password file read access must be restricted: /etc/cassandra/jmxremote.password
在配置JMX远程访问的时候,设置jmxremote.password文件权限,修改该文件时添加写权限,chmod +w jmxremote.password ,放开角色信息那俩行的注释,保存,再使用c ...
- 【原创】PHP扩展开发进阶
PHP扩展开发进阶 作者:wf (360电商技术) 在第一期PHP扩展开发入门中,简单的介绍了PHP的总体架构和执行机制,并具体说明了怎样开发和编译一个主要的PHP扩展,最后在PHP 5.3的环境下 ...
- [CSS3] Create Dynamic Styles with CSS Variables
In this lesson we are going to use CSS variables to keep our application's colors consistent. This i ...
- iOS 图像处理-调整图像亮度
- (UIImage*) getBrighterImage:(UIImage *)originalImage { UIImage *brighterImage; CIContext *context ...
- nyoj--301--递推求值(经典矩阵运算)
递推求值 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给你一个递推公式: f(x)=a*f(x-2)+b*f(x-1)+c 并给你f(1),f(2)的值,请求出f(n ...