請求與響應對象

在用 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?;ヂ摼W編號分配機構維護了一個官方的互聯網媒體類型清(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 可以指定一個不同的代碼。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容