请求与响应对象

在用 Express 构建 Web 服务器时,大部分工作都是从请求对象开始,到响应对象终止。这两个对象起源于 Node,Express 对其进行了扩展,在进行探讨前,我们首先看一下服务端如何通过url对客户端返回一个页面。
URL的组成部分
Screenshot from 2017-07-30 21-43-57.png
  • 协议
    • 协议确定如何传输请求,我们主要使用http与https,常见的还有ftp与file
  • 主机名
    • 主机名标识服务器。运行在本地计算机(localhost)和本地网络的服务器可以简单地表示,比如用一个单词,或一个数字 IP 地址。在 Internet 环境下,主机名通常以一个顶级域名(TLD)结尾,比如 .com 或 .net。另外,也许还会有子域名作为主机名的前缀。子域名可以是任何形式的,其中 www 最为常见。子域名通常是可选的。
  • 端口
    • 每一台服务器都有一系列端口号。一些端口号比较“特殊”,如 80 和 443 端口。如果省略端口值,那么默认 80 端口负责 HTTP 传输,443 端口负责 HTTPS 传输。如果不使用 80 和 443 端口,就需要一个大于 1023 1 的端口号。通常使用容易记忆的端口号,如3000、8080 或 8088。
  • 路径
    • URL 中影响应用程序的第一个组成部分通常是路径(在考虑协议、主机名和端口的基础上做决定很合理,但是不够好)。路径是应用中的页面或其他资源的唯一标识。
  • 查询字符串
    • 查询字符串是一种键值对集合,是可选的。它以问号(?)开头,键值对则以与号(&)分隔开。所有的名称和值都必须是 URL 编码的。对此,JavaScript 提供了一个嵌入式的函数 encodeURIComponent 来处理。例如,空格被加号(+)替换。其他特殊字符被数字型字符替换。
  • 信息片断
    • 该信息不会发送到服务端,一般只涉及到前段设置锚点,用于页面的跳转
http请求方法
  • HTTP 协议确定了客户端与服务器通信的请求方法集合(通常称为 HTTP verbs)。很显然,GET 和 POST 最为常见。在浏览器中键入一个 URL(或点击一个链接),服务器会接收到一个 HTTP GET 请求,其中的重要信息是 URL 路径和查询字符串。至于如何响应,则需要应用程序结合方法、路径和查询字符串来决定。
  • 对于一个网站来说,大部分页面都响应 GET 请求。 POST 请求通常用来提交信息到服务器后台(例如表单处理)。服务器将请求中包含的所有信息(例如表单)处理完成之后,用以响应的 HTML 通常与相应的 GET 请求是一样的。与服务器通信时,浏览器只使用 GET 和POST 方法(如果没有使用 AJAX)
请求报头
  • 我们浏览网页时,发送到服务器的并不只是 URL。当你访问一个网站时,浏览器会发送很多“隐形”信息。服务器会因此得知优先响应哪种语言的页面(例如,在西班牙下载 Chrome 浏览器,如果有西班牙语的版本,就会接收到一个西班牙语的访问页面)。它也会发送“用户代理”信息(浏览器、操作系统和硬件设备)和其他一些信息。所有能够确保你了解请求对象头文件属性的信息都将会作为请求报头发送。
响应报头
  • 正如浏览器以请求报头的形式发送隐藏信息到服务器,当服务器响应时,同样会回传一些浏览器没必要渲染和显示的信息,通常是元数据和服务器信息。我们已经熟悉内容类型头信息,它告诉浏览器正在被传输的内容类型(网页、图片、样式表、客户端脚本等)。特别要注意的是,不管 URL 路径是什么,浏览器都根据内容类型报头处理信息。因此你可以通过一个叫作 /image.jpg 的路径提供网页,也可以通过一个叫作 /text.html 的路径提供图片。除了内容类型之外,报头还会指出响应信息是否被压缩,以及使用的是哪种编码。响应报头还可以包含关于浏览器对资源缓存时长的提示。响应报头也会返回一些服务器信息。
互联网媒体类型
  • 内容类型报头信息极其重要,没有它,客户端很难判断如何渲染接收到的内容。内容类型报头就是一种互联网媒体类型,由一个类型、一个子类型以及可选的参数组成。例如,text/html;charset=UTF-8 说明类型是 text,子类型是 html,字符编码是 UTF-8。互联网编号分配机构维护了一个官方的互联网媒体类型清(http://www.iana.org/assignments/media-
    types/media-types.xhtml)。我们常见的 content type、Internet media type 和 MIME type 是可以互换的。MIME(多用途互联网邮件扩展)是互联网媒体类型的前身,它们大部分是相同的。
请求体
  • 除请求报头外,请求还有一个主体(就像作为实际内容返回的响应主体一样)。一般 GET请求没有主体内容,但 POST 请求是有的。 POST 请求体最常见的媒体类型是 application/x-www-form-urlendcoded ,是键值对集合的简单编码,用 & 分隔(基本上和查询字符串的格式一样)。如果 POST 请求需要支持文件上传,则媒体类型是 multipart/form-data ,它是一种更为复杂的格式。最后是 AJAX 请求,它可以使application/json 。
请求对象

请求对象(通常传递到回调方法,这意味着你可以随意命名,通常命名为 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

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

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

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

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

响应对象(通常传递到回调方法,这意味着你可以随意命名它,通常命名为 res 、 resp 或response )的生命周期始于 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 中的主要用途,我们这里有一个非常简单的例子:
      res.format({'text/plain':'hithere','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 可以指定一个不同的代码。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容