Abstract: When a 400 error occurs in an http request, it is usually caused by an invalid http request (bad request) and incorrect url parameter encoding format. The URL has certain format requirements. Generally, only English letters, Arabic numerals and some special characters can be used. Other characters such as spaces and double quotes need to be encoded before the URL can be used. 1. When accessing directly in the browser, the browser will automatically perform encoding processing. 2. However, when calling directly in the program, the URL needs to be encoded in advance. For example, when PHP is called using curl_exec, illegal characters such as spaces must be encoded. 3. In particular, you need to pay more attention to the json data value contained in the url parameter.
Background
Phenomena 1 - The php encapsulated http request interface calls the url
1. The rawheader value of response shows a 400 error
HTTP/1.1 400 Unknown VersionServer: Tengine/2.0.3Date: Tue, 19 Jul 2016 07:38:15 GMTContent-Length: 0Connection: keep-alive
2. Self-encapsulated sending http request interface
/** * 发送httpful get请求 * @param [array] $params [description] * @return [object] [description] */public function sendGetRequest($serverUrl,$params){ try{ $str_params = ''; foreach ($params as $key => $value) { $str_params .= "&$key=".$value; } $response = \Httpful\Request::get($serverUrl.$str_params)->send(); return $response->body; }catch(Execption $e){ return array("statuscode"=>'-1',"message"=>'服务器出错了'); } }
3.Request The send method of the Request object encapsulated in .php
The Request::send method in nategood/httpful uses the curl_exec interface of PHP to initiate an http request.
/** * Actually send off the request, and parse the response * @return string|associative array of parsed results * @throws ConnectionErrorException when unable to parse or communicate w server */public function send(){ if (!$this->hasBeenInitialized()) $this->_curlPrep(); $result = curl_exec($this->_ch); if ($result === false) { if ($curlErrorNumber = curl_errno($this->_ch)) { $curlErrorString = curl_error($this->_ch); $this->_error($curlErrorString); throw new ConnectionErrorException('Unable to connect: ' . $curlErrorNumber . ' ' . $curlErrorString); } $this->_error('Unable to connect.'); throw new ConnectionErrorException('Unable to connect.'); } $info = curl_getinfo($this->_ch); // Remove the "HTTP/1.x 200 Connection established" string and any other headers added by proxy $proxy_regex = "/HTTP\/1\.[01] 200 Connection established.*?\r\n\r\n/s"; if ($this->hasProxy() && preg_match($proxy_regex, $result)) { $result = preg_replace($proxy_regex, '', $result); } $response = explode("\r\n\r\n", $result, 2 + $info['redirect_count']); $body = array_pop($response); $headers = array_pop($response); curl_close($this->_ch); return new Response($body, $headers, $this, $info); }
4. The url value before curl_exec is called
http://192.168.59.146/api?version=1.0&format=json&appkey=KtSNKxk3&access_token=changyanyun&method=pan.file.export&uid=3062000039000412278&fileId=3aaaa5c8-3eaa-4511-91e7-46831d418f10&fileIndex={"lifecycle":{"auditstatus":"0"},"general":{"source":"UGC","creator":"\u6559\u5e080523","uploader":"gsres_iflytek_f968bca78360d38abcbaf23a5a318b12","extension":"ppt","title":"Unit12 What did you do last weekdend\u8bfe\u65f64\uff081\uff09"},"properties":{"subject":["01"],"edition":["01"],"stage":["010001"],"book":["01010101-001"],"unit":["01"],"course":[""],"unit1":["01"],"unit2":[""],"unit3":[""],"phase":["03"],"type":["0100"],"rrtlevel1":["08"]}}
Phenomenon 2 - Directly accessing the url in the browser
http://192.168.59.146/api?version=1.0&format=json&appkey=KtSNKxk3&access_token=changyanyun&method=pan.file.export&uid=3062000039000412278&fileId=3aaaa5c8-3eaa-4511-91e7-46831d418f10&fileIndex={ %22lifecycle%22:{ %22auditstatus%22:%220%22},%22general%22:{ %22source%22:%22UGC%22,%22creator%22:%22\u6559\u5e080523%22,%22uploader%22:%22gsres_iflytek_f968bca78360d38abcbaf23a5a318b12%22,%22extension%22:%22ppt%22,%22title%22:%22Unit12%20What%20did%20you%20do%20last%20weekdend\u8bfe\u65f64\uff081\uff09%22},%22properties%22:{ %22subject%22:[%2201%22],%22edition%22:[%2201%22],%22stage%22:[%22010001%22],%22book%22:[%2201010101-001%22],%22unit%22:[%2202%22],%22course%22:[%22%22],%22unit1%22:[%2202%22],%22unit2%22:[%22%22],%22unit3%22:[%22%22],%22phase%22:[%2203%22],%22type%22:[%220100%22],%22rrtlevel1%22:[%2208%22]}}
Cause analysis
Comparing the url values in Phenomenon 1 and Phenomenon 2, we can find:
fileIndex parameter The value is a json string
The space character in the title attribute value in the fileIndex parameter value is encoded as %20 in phenomenon 2, and the double quotation mark " is encoded as %22. This operation is automatically performed by the browser
Replace the url After the spaces in are encoded, the curl_exec interface returns 200
Test code
_ch)) { $curlErrorString = curl_error($this->_ch); $this->_error($curlErrorString); throw new ConnectionErrorException('Unable to connect: ' . $curlErrorNumber . ' ' . $curlErrorString); } $this->_error('Unable to connect.'); throw new ConnectionErrorException('Unable to connect.'); } var_dump("ch"); var_dump($ch); $info = curl_getinfo($ch); var_dump("info"); var_dump($info);// Remove the "HTTP/1.x 200 Connection established" string and any other headers added by proxy$proxy_regex = "/HTTP\/1\.[01] 200 Connection established.*?\r\n\r\n/s";if (preg_match($proxy_regex, $result)) { $result = preg_replace($proxy_regex, '', $result); } $response = explode("\r\n\r\n", $result, 2 + $info['redirect_count']); var_dump("response"); var_dump($response); $body = array_pop($response); var_dump("body"); var_dump($body); $headers = array_pop($response); var_dump("headers"); var_dump($headers);// 关闭cURL资源,并且释放系统资源curl_close($ch);?>
Percent encoding (that is, url encoding)
Generally speaking, URLs can only use English letters, Arabic numerals and certain punctuation marks, and cannot be used Other words and symbols. Ruan Yifeng mentioned in his blog post that the network standard RFC 1738 has a mandatory requirement:
"...Only alphanumerics [0-9a-zA-Z], the special characters "$-.+ !*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."
"Only letters and numbers [0-9a-zA-Z], some The special symbols "$-.+!*'()," [excluding double quotes], and certain reserved words can be used directly in URLs without encoding. "
url encoding is the encoding mechanism of the Uniform Resource Locator (URL) in a specific context. If the server encounters non-standard characters when parsing the http request, it will encode the non-standard characters.
Summary
When the http request appears with 400 When the error occurs, it is usually caused by an invalid http request (bad request) and incorrect URL parameter encoding format. URLs have certain format requirements. Generally, only English letters, Arabic numerals and some special characters can be used. Other characters such as spaces and double characters can be used. Quotation marks need to be encoded before the user URL can be used.
The browser will automatically encode it when accessed directly in the browser. However, when calling directly in the program, the url needs to be encoded in advance. For example, when calling PHP using curl_exec, it will be encoded. Encoding illegal characters such as spaces
Especially when url parameters contain json data values
.