查詢字符串

查詢字符串（query string）是統一資源定位符 (URL) 的一部分，用於將值分配給指定的參數。查詢字符串通常包括由Web瀏覽器或其他客戶端應用程序添加到基本URL的字段，例如作為HTML文檔的一部分、選擇頁面的外觀或跳轉到多媒體內容中的位置。 

Google Chrome瀏覽器的地址欄顯示帶有查詢字符串title=Query_string&action=edit的URL。
Web服務器可以通過基於URL路徑從其文件系統讀取文件或使用特定於資源類型的邏輯處理請求來處理超文本傳輸協議 (HTTP) 請求。在調用特殊邏輯的情況下，查詢字符串以及URL的路徑組件將可供該邏輯在其處理中使用。

**結構**
包含查詢字符串的典型URL如下：1=
當服務器收到對此類頁面的請求時，它可以運行一個程序，將查詢字符串（在本例中為name=ferret）傳遞給該程序，不做任何更改。問號用作分隔符，不是查詢字符串的一部分。
Web框架可能提供用於解析查詢字符串中的多個參數的方法，這些參數由某些分隔符分隔。在下面的示例URL中，多個查詢參數由與號“&”分隔： 
查詢字符串的確切結構尚未標準化。用於解析查詢字符串的方法可能因網站而異。
網頁中的鏈接可能具有包含查詢字符串的URL。HTML定義了用戶代理生成查詢字符串的三種方式：- 通過form元素生成HTML表單- 通過open元素上的ismap屬性和params=ismap構造的服務器端圖像映射 - 通過現已棄用的open元素進行索引搜索 

**網頁表單**
最初的用途之一是包含HTML表單（也稱為Web表單）的內容。特別地，當提交包含字段field1, field2, field3的表單時，字段的內容被編碼為查詢字符串，如下所示：- 查詢字符串由一系列“字段-值”對組成。- 在每對中，字段名稱和值由等號“=”分隔。 - 該系列的“字段-值”對由與號“&”分隔（W3C不再推薦使用分號“;”，請參見下文）。  
雖然沒有明確的標準，但大多數Web框架允許多個值與單個字段關聯（例如field1=value1&field1=value2&field2=value3）。
對於表單的每個字段，查詢字符串包含一對field=value。 Web 表單可能包含用戶不可見的字段； 提交表單時，這些字段將包含在查詢字符串中。
該約定是W3C的建議。在1999年的建議中，W3C建議所有Web服務器除了&符號分隔符之外還支持分號分隔符，以允許HTML文檔的URL中的application/x-www-form-urlencoded查詢字符串，而無需對&符號進行實體轉義。自2014年起，W3C建議僅使用&符號作為查詢分隔符。     
當表單提交方法為GET時，表單內容僅編碼在URL的查詢字符串中。當提交方法為POST時，默認使用相同的編碼，但結果作為HTTP request body 提交，而不是包含在修改後的URL 中。


**索引搜索**
在將表單添加到HTML之前，瀏覽器將open元素呈現為單行文本輸入控件。輸入到此控件中的文本作為查詢字符串發送到服務器，附加到對基本URL或action屬性指定的另一個URL的GET請求。這樣做的目的是允許Web服務器使用提供的文本作為查詢條件，以便它們可以返回匹配頁面的列表。
當輸入到索引搜索控件的文本被提交時，它被編碼為查詢字符串，如下所示：- 查詢字符串由一系列參數組成，通過將文本解析為該空間處的單詞。 - 該系列由加號“+”分隔。 
儘管open元素已被棄用，並且大多數瀏覽器不再支持或呈現它，但仍然存在索引搜索的一些痕跡。 例如，這就是瀏覽器URL的百分號編碼中加號“+”特殊處理的來源（如今，隨著索引搜索的棄用，%20幾乎是多餘的）。此外，如果查詢字符串不包含等號“=”（根據CGI 1.1的第4.4節），一些支持CGI的Web服務器（例如Apache）會將查詢字符串處理為命令行參數。一些CGI腳本仍然依賴並使用這種歷史行為來嵌入HTML中的URL。 

**URL編碼**
有些字符不能是URL的一部分（例如空格），而其他一些字符在URL中具有特殊含義：例如，字符#可用於進一步指定文檔的小節（或片段）。在HTML表單中，字符=用於分隔名稱和值。URI通用語法使用URL編碼來處理此問題，而HTML表單會進行一些額外的替換，而不是對所有此類字符應用百分比編碼。
HTML5指定以下轉換，用於使用“GET”方法向Web服務器提交HTML表單。以下是該算法的簡要總結：- 無法轉換到正確字符集的字符將替換為HTML字符值引用- 空格被編碼為“+”或“%20”。- 字母（A–Z和a–z）、數字 (0–9) 和字符'~','-','.' and '_'保持原樣 - +由%2B編碼- 所有其他字符均編碼為%HH十六進制表示形式，任何非ASCII字符首先編碼為UTF-8（或其他指定的編碼）     

RFC 3986允許在查詢字符串中使用與波浪號（“~”）相對應的八位字節，但需要在HTML表單中將其百分比編碼為“%7E”。
將SPACE編碼為“+”或者選擇“原樣”表示該字符，這是HTML5編碼與RFC 3986的差異。

**例子**
把如下表單遷入HTML網頁:



用戶在兩個文本輸入框中寫入字符串“this is a field”和“ it clear ()?”並按提交按鈕，程序test.cgi（上例中由form元素的action屬性指定的程序）將收到以下查詢字符串：first=this+is+a+field&second=was+it+clear+%28already%29%3F
如果表單由CGI腳本在服務器上處理，則該腳本通常可以將查詢字符串作為名為QUERY_STRING的環境變量接收。

**跟蹤用戶狀態**
接收查詢字符串的程序可以忽略部分或全部查詢字符串。如果請求的URL對應於文件而不是程序，則忽略整個查詢字符串。但是，無論是否使用查詢字符串，包括它的整個URL都會存儲在服務器日誌文件中。
這些事實允許使用查詢字符串以類似於HTTP cookie提供的方式跟蹤用戶。為此，每次用戶下載頁面時，都必須選擇一個唯一標識符並將其作為查詢字符串添加到該頁面包含的所有鏈接的URL中。一旦用戶點擊其中一個鏈接，就會向服務器請求相應的URL。這樣，本頁的下載就與上一頁鏈接起來了。
例如，當請求包含以下內容的網頁時：
see my page!
mine is better
選擇一個唯一的字符串，例如e0a72cb2a2c7，並將頁面修改如下： 
see my page!
mine is better
添加查詢字符串不會改變頁面向用戶顯示的方式。例如，當用戶點擊第一個鏈接時，瀏覽器會向服務器請求頁面foo.html?e0a72cb2a2c7，而服務器會忽略?後面的內容並按預期發送頁面foo.html，同時將查詢字符串添加到其鏈接中。 
這樣，來自該用戶的任何後續頁面請求都將攜帶相同的查詢字符串e0a72cb2a2c7，從而可以確定所有這些頁面已被同一用戶查看。 查詢字符串通常與網絡信標結合使用。
用於跟蹤的查詢字符串和 HTTP cookie 之間的主要區別是：
# 查詢字符串構成URL的一部分，因此如果用戶保存URL或將URL發送給其他用戶，查詢字符串也會包含在內；cookie可以跨瀏覽會話進行維護，但不會與URL一起保存或發送。
# 如果用戶通過兩個（或多個）獨立路徑到達同一個Web服務器，它將被分配兩個不同的查詢字符串，而存儲的cookie是相同的。
# 用戶可以禁用cookie，在這種情況下，使用cookie進行跟蹤將不起作用。但是，使用查詢字符串進行跟蹤應該適用於所有情況。
# 不同的頁面訪問所傳遞的不同查詢字符串將意味著頁面永遠不會從瀏覽器（或代理，如果存在）緩存中獲取服務，從而增加Web服務器上的負載並降低用戶體驗。

**兼容性問題**
根據HTTP規範：
在實踐中發現了對請求行長度的各種臨時限制。建議所有HTTP發送方和接收方至少支持8000個八位字節的請求行長度。
如果URL太長，Web服務器將失敗並顯示HTTP狀態碼：414 Request-URI Too Long。
這些問題的常見解決方法是使用POST而不是GET並將參數存儲在請求體中。請求體的長度限制通常遠高於URL長度的長度限制。例如，默認情況下，POST大小限制在IIS 4.0上為 2 MB，在IIS 5.0上為 128 KB。該限制在Apache2上可使用LimitRequestBody指令進行配置，該指令指定請求體中允許的從 0（表示無限制）到2147483647 (2 GB) 的字節數。

**參見**
 URI fragment- URI normalization- URL (Uniform Resource Locator)- Clean URL- Click identifier- Common Gateway Interface (CGI)- HTTP cookie- 超文本傳輸協議 (HTTP)- Semantic URL- URI scheme- UTM parameters- 網絡信標

**參考文獻==