express-6 请求和响应对象(1)

时间:2023-03-08 20:58:53

URL的组成部分###

express-6 请求和响应对象(1)

  • 协议:

    协议确定如何传输请求。我们主要是处理http和https。其他常见的协议还有file和ftp。
  • 主机名:

    主机名标识服务器。运行在本地计算机(localhost)和本地网络的服务器可以简单地表示,比如用一个单词,或一个数字IP地址。在Internet环境下,主机名通常以一个*域名(TLD)结尾,比如.com或.net。另外,也许还会有子域名作为主机名的前缀。子域名可以是任何形式的,其中www最为常见。子域名通常是可选的。
  • 端口:

    每一台服务器都有一系列端口号。一些端口号比较“特殊”,如80和443端口。如果省略端口值,那么默认80端口负责HTTP传输,443端口负责HTTPS传输。如果不使用80和443端口,就需要一个大于1023(0~1023端口为“知名端口”)的端口号。通常使用容易记忆的端口号,如3000、8080或8088。
  • 路径:

    查询字符串是一种键值对集合,是可选的。它以问号(?)开头,键值对则以与号(&)分隔开。所有的名称和值都必须是URL编码的。对此,JavaScript提供了一个嵌入式的函数encodeURIComponent来处理。例如,空格被加号(+)替换。其他特殊字符被数字型字符替换。
  • 信息片段:

    **信息片段(或散列)被严格限制在浏览器中使用,不会传递到服务器。用它控制单页应用或AJAX富应用越来越普遍。最初,信息片段只是用来让浏览器展现文档中通过锚点标记(<a id="chapter06">)指定的部分。

    **

互联网媒体类型###

内容类型报头信息极其重要,没有它,客户端很难判断如何渲染接收到的内容。内容类型报头就是一种互联网媒体类型,由一个类型、一个子类型以及可选的参数组成。例如,text/html;charset=UTF-8说明类型是text,子类型是html,字符编码是UTF-8。

互联网编号分配机构维护了一个官方的互联网媒体类型清单

常见的content type、Internet media type和MIME type是可以互换的。MIME(多用途互联网邮件扩展)是互联网媒体类型的前身,它们大部分是相同的。

HTTP请求方法###

在浏览器中键入一个URL(或点击一个链接),服务器会接收到一个HTTP GET请求,其中的重要信息是URL路径和查询字符串。至于如何响应,则需要应用程序结合方法、路径和查询字符串来决定。

对于一个网站来说,大部分页面都响应GET请求。POST请求通常用来提交信息到服务器后台(例如表单处理)。

使用Node和Express,可以完全掌控响应方法。在Express中,通常要针对特殊方法编写处理程序。

请求报头###

我们浏览网页时,发送到服务器的并不只是URL。当你访问一个网站时,浏览器会发送很多“隐形”信息; 服务器会因此得知优先响应哪种语言的页面,也会发送“用户代理”信息(浏览器、操作系统和硬件设备)和其他一些信息。

app.get('/header', 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);
});

请求体###

除请求报头外,请求还有一个主体。一般GET请求没有主体内容,但POST请求是有的。POST请求体最常见的媒体类型是application/x-www-form-urlendcoded,是键值对集合的简单编码,用&分隔(基本上和查询字符串的格式一样)。如果POST请求需要支持文件上传,则媒体类型是multipart/form-data,它是一种更为复杂的格式。最后是AJAX请求,它可以使用application/json

参数###

对于任何一个请求,参数可以来自查询字符串、会话(请求cookies)、请求体或指定的路由参数。

在Node应用中,请求对象的参数方法会重写所有的参数

请求对象###

请求对象(通常传递到回调方法,这意味着可以随意命名,通常命名为req或request)的生命周期始于Node的一个核心对象http.IncomingMessage的实例。Express添加了一些附加功能。看看请求对象中最有用的属性和方法(除了来自Node的req.headers和req.url,所有这些方法都由Express添加)。

  • 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

    用于标识请求的协议(httphttps)。
  • req.secure

    一个简便属性,如果连接是安全的,将返回true。等同于req.protocol==='https'
  • req.url/req.originalUrl

    有点用词不当,这些属性返回了路径和查询字符串(它们不包含协议、主机或端口)。req.url若是出于内部路由目的,则可以重写,但是req.orginalUrl旨在保留原始请求和查询字符串。
  • req.acceptedLanguages

    一个简便方法,用来返回客户端首选的一组(人类的)语言。这些信息是从请求报头中解析而来的。

响应报头###

当服务器响应时,同样会回传一些浏览器没必要渲染和显示的信息,通常是元数据和服务器信息; 包括内容类型,响应信息是否被压缩,以及使用的是哪种编码。响应报头还可以包含关于浏览器对资源缓存时长的提示。响应报头还经常会包含一些关于服务器的信息,一般会指出服务器的类型,有时甚至会包含操作系统的详细信息。返回服务器信息存在一个问题,那就是它会给黑客一个可乘之机,从而使站点陷入危险。非常重视安全的服务器经常忽略此信息,甚至提供虚假信息。禁用Express的X-Powered-By头信息(显示服务器信息)很简单:

app.disable('x-powered-by');

响应对象###

响应对象(通常传递到回调方法,这意味着你可以随意命名它,通常命名为resrespresponse)的生命周期始于Node核心对象http.ServerResponse的实例。Express添加了一些附加功能。看看响应对象中最有用的属性和方法(所有这些方法都是由Express添加的)。

  • 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值。需要中间件支持

  • 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':'hi there','text/html':'<b>hi there</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可以指定一个不同的代码。