1. 程式人生 > >PHP規範PSR7(HTTP訊息介面)介紹(二)

PHP規範PSR7(HTTP訊息介面)介紹(二)

1.3 流

HTTP訊息由起始行,標題和正文組成。 HTTP訊息的主體可能非常小或非常大。嘗試將訊息正文表示為字串很容易消耗比預期更多的記憶體,因為正文必須完全儲存在記憶體中。嘗試將請求或響應的主體儲存在記憶體中將阻止使用該實現能夠使用大型訊息體。 StreamInterface用於在讀取或寫入資料流時隱藏實現細節。對於字串是適當的訊息實現的情況,可以使用內建流,例如php:// memory和php:// temp。

StreamInterface公開了幾種方法,可以有效地讀取,寫入和遍歷流。

Streams使用三種方法公開它們的功能:isReadable(),isWritable()和isSeekable()。流協作者可以使用這些方法來確定流是否能夠滿足其要求。

每個流例項都具有各種功能:它可以是隻讀,只寫或讀寫。它還可以允許任意隨機訪問(向前或向後搜尋任何位置),或僅允許順序訪問(例如,在套接字,管道或基於回撥的流的情況下)。

最後,StreamInterface定義了一個__toString()方法,以簡化一次檢索或發出整個主體內容的過程。

與請求和響應介面不同,StreamInterface不會對不可變性進行建模。在包裝實際PHP流的情況下,不可能實現不可變性,因為與資源互動的任何程式碼都可能潛在地改變其狀態(包括游標位置,內容等)。我們的建議是實現使用只讀流來處理伺服器端請求和客戶端響應。消費者應該意識到流例項可能是可變的,因此可能會改變訊息的狀態;如有疑問,請建立一個新的流例項並將其附加到訊息以強制執行狀態。

1.4 請求目標和URI

根據RFC 7230,請求訊息包含“請求目標”作為請求行的第二個段。請求目標可以是以下形式之一:

origin-form,由路徑和查詢字串(如果存在)組成;這通常被稱為相對URL。通過TCP傳輸的訊息通常是原始形式;方案和許可權資料通常僅通過CGI變數存在。

absolute-form,由方案,許可權(“[user-info @] host [:port]”,括號中的項是可選的),路徑(如果存在),查詢字串(如果存在)和片段(如果存在)。這通常被稱為絕對URI,並且是RFC 3986中詳細說明的唯一指定URI的形式。此表單通常在向HTTP代理髮出請求時使用。

authority-form,僅由權威機構組成。這通常僅用於CONNECT請求,以在HTTP客戶端和代理伺服器之間建立連線。

asterisk-form,僅由字串*組成,與OPTIONS方法一起使用,以確定Web伺服器的常規功能。

除了這些請求目標之外,通常還有一個與請求目標分開的“有效URL”。有效URL不在HTTP訊息中傳輸,但它用於確定用於發出請求的協議(http / https),埠和主機名。

有效的URL由UriInterface表示。 UriInterface模擬RFC 3986(主要用例)中指定的HTTP和HTTPS URI。該介面提供了與各種URI部分互動的方法,這將消除重複解析URI的需要。它還指定了一個__toString()方法,用於將建模的URI轉換為其字串表示形式。

使用getRequestTarget()檢索請求目標時,預設情況下,此方法將使用URI物件並提取所有必需的元件來構造原始表單。原始形式是迄今為止最常見的請求目標。

如果終端使用者希望使用其他三種表單中的一種,或者如果使用者想要顯式覆蓋請求目標,則可以使用withRequestTarget()來執行此操作。

呼叫此方法不會影響URI,因為它是從getUri()返回的。

例如,使用者可能希望向伺服器發出星號形式的請求:

$request = $request
    ->withMethod('OPTIONS')
    ->withRequestTarget('*')
    ->withUri(new Uri('https://example.org/'));

此示例最終可能會導致HTTP請求如下所示:

OPTIONS * HTTP/1.1

但HTTP客戶端將能夠使用有效的URL(來自getUri())來確定協議,主機名和TCP埠。

HTTP客戶端必須忽略Uri :: getPath()和Uri :: getQuery()的值,而是使用getRequestTarget()返回的值,預設為連線這兩個值。

選擇不實現4個請求目標表單中的一個或多個的客戶端必須仍然使用getRequestTarget()。這些客戶端必須拒絕它們不支援的請求目標,並且不得依賴於getUri()的值。

RequestInterface提供了檢索請求目標或使用提供的請求目標建立新例項的方法。預設情況下,如果例項中沒有專門組合請求目標,則getRequestTarget()將返回組合URI的原始形式(如果沒有組成URI,則返回“/”)。 withRequestTarget($ requestTarget)使用指定的請求目標建立一個新例項,從而允許開發人員建立表示其他三個請求目標表單(絕對錶單,許可權表單和星號表單)的請求訊息。使用時,組合的URI例項仍然可以使用,特別是在客戶端中,它可以用於建立與伺服器的連線。