协议 (protocol)
协议确定如何传输请求。我们主要是处理http 和https。其他常见的协议还有file 和ftp。
主机名(hostname)
主机名标识服务器。运行在本地计算机(localhost)和本地网络的服务器可以简单地表示,比如用一个单词,或一个数字IP
地址。在Internet 环境下,主机名通常以一个顶级域名(TLD)结尾,比如.com
或.net。另外,也许还会有子域名作为主机名的前缀。子域名可以是任何形式的,其中www 最为常见。子域名通常是可选的。端口(port)
每一台服务器都有一系列端口号。一些端口号比较“特殊”,如80 和443 端口。如果省略端口值,那么默认80
端口负责HTTP传输,443 端口负责HTTPS 传输。如果不使用80 和443
端口,就需要一个大于10231的端口号。通常使用容易记忆的端口号,如3000、8080 或8088。路径(path)
URL中影响应用程序的第一个组成部分通常是路径(在考虑协议、主机名和端口的基础上做决定很合理,但是不够好)。路径是应用中的页面或其他资源的唯一标识。查询字符串(querystring)
查询字符串是一种键值对集合,是可选的。它以问号(?)开头,键值对则以与号(&)分隔开。所有的名称和值都必须是URL编码的。对此,JavaScript
提供了一个嵌入式的函数encodeURIComponent来处理。例如,空格被加号(+)替换。其他特殊字符被数字型字符替换。- 信息片段(fragment)
信息片段(或散列)被严格限制在浏览器中使用,不会传递到服务器。用它控制单页应用或AJAX富应用越来越普遍。最初,信息片段只是用来让浏览器展现文档中通过锚点标记(<a
id="chapter06">)指定的部分。
6.2 HTTP请求方法
HTTP 协议确定了客户端与服务器通信的请求方法集合(通常称为HTTP verbs)。很显然,GET 和POST 最为常见。
GET 请求
大部分页面都响应GET 请求。服务器通过GET请求的路径和查询字符串来匹配对于的路由。
POST 请求
POST 请求通常用来提交信息到服务器后台(例如表单处理)
6.3 请求报头
一个请求中会附带一个请求包头,包含一些“隐形”信息。
语言、浏览器、操作系统和硬件设备。服务端可以根据这些信息再去生成有正对性的数据。
获取请求报头方式:
app.get('/headers', function(req,res){
res.set('Content-Type','text/plain');
var s = '';
for(var name in req.headers) s += name + ': ' + req.headers[name] + '\n';
res.send(s);
});
这些报头信息存储在req.headers对象上,便于访问。
6.4 响应报头
服务端也会将元数据和服务器信息以响应报头的形式返回给客户端。
浏览器所需要的信息:
内容类型头信息,压缩,编码形式,资源缓存等。
服务器信息:
服务器的类型、操作系统的详细信息等。
内容类型报头就是一种互联网媒体类型,由一个类型、一个子类型以及可选的参数组成。例如,text/html;charset=UTF-8 说明类型是text,子类型是html,字符编码是UTF-8。
6.6 请求体请求体起到承载数据的的作用。一般GET没有请求提,GET是用过url的形式发送简单的数据。
请求体一般用于POST中,常见的类型:
媒体类型:
application/x-www-form-urlendcoded:是键值对集合的简单编码,用& 分隔。
multipart/form-data:如果POST 请求需要支持文件上传时使用
application/json :用于AJAX请求
参数来源:
查询字符串、会话、请求体、路由参数
req.params
一个数组,包含命名过的路由参数。
req.param(name)
返回命名的路由参数,或者GET 请求或POST 请求参数。req.query
一个对象,包含以键值对存放的查询字符串参数(通常称为GET 请求参数)。
req.body
一个对象,包含POST 请求参数。这样命名是因为POST 请求参数在REQUEST
正文中传递,而不像查询字符串在URL中传递。要使req.body 可用,需要中间件能够解析请求正文内容类型。req.route
关于当前匹配路由的信息。主要用于路由调试。
req.cookies/req.singnedCookies
一个对象,包含从客户端传递过来的cookies 值。
req.headers
从客户端接收到的请求报头。
req.accepts([types])
一个简便的方法,用来确定客户端是否接受一个或一组指定的类型(可选类型可以是单个的MIME类型,如application/json、一个逗号分隔集合或是一个数组)。写公共API的人对该方法很感兴趣。假定浏览器默认始终接受HTML。req.ip
客户端的IP 地址。
req.path
请求路径(不包含协议、主机、端口或查询字符串)。
req.host
一个简便的方法,用来返回客户端所报告的主机名。这些信息可以伪造,所以不应该用于安全目的。
req.xhr
一个简便属性,如果请求由Ajax 发起将会返回true。
req.protocol
用于标识请求的协议(http 或https)。
req.secure
一个简便属性,如果连接是安全的,将返回true。等同于req.protocol==='https'。
- req.url/req.originalUrl
有点用词不当,这些属性返回了路径和查询字符串(它们不包含协议、主机或端口)。req.url若是出于内部路由目的,则可以重写,但是req.orginalUrl
旨在保留原始请求和查询字符串。
req.acceptedLanguages
一个简便方法,用来返回客户端首选的一组(人类的)语言。这些信息是从请求报头中解析而来的。
请求对象的方法分为:
- url解析:
req.params req.param(name)
req.query
req.route
req.path
req.host
req.protocol
req.secure
req.url/req.originalUrl - 报头信息:
req.headers
req.accepts([types])
req.ip - 请求数据:
req.cookies/req.singnedCookies
req.xhr
res.status(code)
设置HTTP 状态代码。Express> 默认为200(成功),所以你可以使用这个方法返回状态404(页面不存在)或500(服务器内部错误),或任何一个其他的状态码。对于重定向(状态码301、302、303 和307),有一个更好的方法:redirect。
res.set(name,value)
设置响应头。这通常不需要手动设置。res.cookie(name,vaue,[options]),res.clearCookie(name,[options])
设置或清除客户端cookies 值。需要中间件支持,详见第9 章。res.redirect([status],url)
重定向浏览器。默认重定向代码是302(建立)。通常,你应尽量减少重定向,除非永久移动一个页面,这种情况应当使用代码301(永久移动)。res.send(body),res.• send(status,body)
向客户端发送响应及可选的状态码。Express> 的默认内容类型是text/html。如果你想改为text/plain,需要在res.send> 之前调用res.set('Content-type','text/plain\')。如果body 是一个对象或一个数组,响应将会以JSON发送(内容类型需要被正确设置),不过既然你想发送JSON,我推荐你调用res.json。res.json(json),res.json(status,json)
向客户端发送JSON 以及可选的状态码。res.jsonp(json),req.jsonp(status,json)
向客户端发送JSONP 及可选的状态码。res.type(type)
一个简便的方法,用于设置Content-Type头信息。基本上相当于res.set('Content-Type','type'),只是如果你提供了一个没有斜杠的字符串,它会试图把其当作文件的扩展名映射为一个互联网媒体类型。比如,res.type('txt')会将Content-Type设为text/plain。此功能在有些领域可能会有用(例如自动提供不同的多媒体文件),但是通常应该避免使用它,以便明确设置正确的互联网媒体类型。res.format(object)
这个方法允许你根据接收请求报头发送不同的内容。这是它在API 中的主要用途,我们将会在第15章详细讨论。这里有一个非常简单的例子:res.format({'text/plain':'hithere','text/html':'<b>hithere</b>'})。res.attachment([filename]),res.download(path,[filename],[callback])
这两种方法会将响应报头Content-Disposition设为attachment,这样浏览器就会选择下载而不是展现内容。你可以指定filename给浏览器作为对用户的提示。用res.download> 可以指定要下载的文件,而res.attachment只是设置报头。另外,你还要将内容发送到客户端。res.sendFile(path,[option],[callback])
这个方法可根据路径读取指定文件并将内容发送到客户端。使用该方法很方便。使用静态中间件,并将发送到客户端的文件放在公共目录下,这很容易。然而,如果你想根据条件在相同的URL下提供不同的资源,这个方法可以派上用场。res.links(links)
设置链接响应报头。这是一个专用的报头,在大多数应用程序中几乎没有用处。- res.locals,res.render(view,[locals],callback)
res.locals 是一个对象,包含用于渲染视图的默认上下文。res.render使用配置的模板引擎渲染视图(不能把res.render 的locals 参数与res.locals 混为一谈,上下文在res.locals中会被重写,但在没有被重写的情况下仍然可用)。res.render的默认响应代码为200,使用res.status可以指定一个不同的代码。
响应对象的方法基本分三类:
- 响应的内容:
res.send(body),res.send(status,body)
res.json(json),res.json(status,json)
res.jsonp(json),req.jsonp(status,json)
res.sendFile(path,[option],[callback])
res.locals,res.render(view,[locals],callback) - 响应的报头:
res.status(code)
res.set(name,value)
res.type(type)
res.format(object)
res.attachment([filename]),res.download(path,[filename],[callback])
res.redirect([status],url) - 响应的数据:
res.cookie(name,vaue,[options]),res.clearCookie(name,[options])