標籤:request mysq 空格 目錄 表單 出錯 配置 ddr uri
django+nginx+uwsgi部署的網站訪問某個URL時發生了400 bad request的錯誤,而使用django內建的開發版的web server時沒有遇到此問題。初步判斷是nginx或uwsgi配置問題。
網上有說是因為request header過大而nginx配置的client_header_buffer_size和large_client_header_buffers過小引起的,但就當前的狀態來看感覺不太可能。因為request header並不是特別大。至於是別的什麼原因還暫未找到,所以還是先試試看。
在nginx設定檔nginx.conf中的http部分加入如下兩行參數:
client_header_buffer_size 16k;
large_client_header_buffers 4 64k;
nginx預設會用client_header_buffer_size這個buffer來讀取header值,如果header過大,它會使用large_client_header_buffers來讀取header值。若該值設定過小而要求標頭/COOKIE過大則會報400 bad request錯誤。
調整參數重新載入設定檔重啟uwsgi後發現問題並未解決。
經仔細查看才發現原來是請求的URL中參數包含了特殊字元%,導致Web Server沒能夠正確解析出該URL,才報了這個錯誤。
在URL中下列字元具有特殊含義:
符號 含義 如何轉義
+ URL中+號表示空格 %2B
空格 URL中的空格可以用+號或者編碼 %20
/ 分隔目錄和子目錄 %2F
? 分隔實際的URL和參數 %3F
% 指定特殊字元 %25
# 表示書籤 %23
& URL中指定的參數間的分隔字元 %26
= URL中指定參數的值 %3D
比如sever端從提交的表單的輸入框中的值構造包含參數的URL,
若提交的內容為“pkgcr+awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%2Bawldb”,也即參數中q的值實際上為“pkgcr+awldb”
若提交的內容為“pkgcr awldb”,地址欄的URL顯示為“xxx/?q=pkgcr+awldb”,也即參數中q的值實際上為“pkgcr awldb”
若提交的內容為“pkgcr/awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%2Fawldb”,也即參數中q的值實際上為“pkgcr/awldb”
若提交的內容為“pkgcr?awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%3Fawldb”,也即參數中q的值實際上為“pkgcr?awldb”
若提交的內容為“pkgcr%awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%25awldb”,也即參數中q的值實際上為“pkgcr%awldb”
若提交的內容為“pkgcr#awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%23awldb”,也即參數中q的值實際上為“pkgcr#awldb”
若提交的內容為“pkgcr&awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%26awldb”,也即參數中q的值實際上為“pkgcr&awldb”
若提交的內容為“pkgcr=awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%3Dawldb”,也即參數中q的值實際上為“pkgcr=awldb”
若要是直接在server端構造URL呢?比如server端的檔案中有個變數ip,值為“172.142.%”,要在server端構造一個URL供用戶端訪問,如“href=?ip={ip}&q=‘mysql‘”(此處假定{ip}是對變數的一種引用方式),那麼我們點擊這個連結會是什麼結果呢?
我們會看到,因為變數ip中包含特殊字元“%”,而“%”在URL中具有特殊含義,我們通過上述方式構造的URL相當於是“href=?ip=172.142.%&q=mysql”,web伺服器解析該URL時無法解釋%&從而導致出錯。同樣的原因,包含其他一些特殊字元時也會發生一些意想不到的問題,比如有另一個變數addr,值為“china&america”,構造的URL為“href=?addr={addr}&q=‘mysql’”,此時構建的URL相當於是“href=?addr=china&america&q=mysql”,web伺服器會把該URL中的第一個“&”後的“america”解析為另外一個參數而不是將“china&america”整體作為“addr”參數的值。
那麼如何在需要的時候在URL中包含諸如%、&、+、=等等這樣的特殊的字元呢?答案就是用相應的編碼代替特殊字元本身來構建URL。比如上例中可以先將ip的值替換為“172.142.%25”,將addr的值替換為“china%26america”,這樣構建出的URL分別為“href=?ip=172.142.%25&q=mysql”和“href=?addr=china%26america&q=‘mysql’”,這樣最終能夠將URL中的參數ip的值成功解析為“172.142.%”而將addr的值成功解析為china&america,而且不會引起其他參數解析混亂。
最終,發現是在訪問url的中文未進行轉碼導致的400錯誤。
ps: js中文轉碼(encodeURIComponent)
記一次400錯誤引發的血案(URL中特殊符號的轉義/400 bad request錯誤)