요약: http 요청에서 400 오류가 발생하는 경우 일반적으로 잘못된 http 요청(잘못된 요청) 및 잘못된 URL 매개변수 인코딩 형식으로 인해 발생합니다. URL에는 특정 형식 요구 사항이 있습니다. 일반적으로 URL을 사용하려면 영문자, 아라비아 숫자 및 일부 특수 문자만 사용할 수 있습니다. 1. 브라우저에서 직접 접속할 경우 브라우저가 자동으로 인코딩 처리를 수행합니다. 2. 그러나 프로그램에서 직접 호출할 경우에는 URL을 미리 인코딩해야 합니다. 예를 들어, 컬_exec를 사용하여 PHP를 호출하면 다음과 같은 잘못된 문자가 표시됩니다. 공백을 인코딩해야 하기 때문입니다. 3. 특히 url 매개변수에 포함된 json 데이터 값에 더욱 주의할 필요가 있습니다.
배경
현상 1 - PHP로 캡슐화된 http 요청 인터페이스는 url
1의 원시 헤더를 호출합니다. 응답 값은 400 오류를 표시합니다
HTTP/1.1 400 Unknown VersionServer: Tengine/2.0.3Date: Tue, 19 Jul 2016 07:38:15 GMTContent-Length: 0Connection: keep-alive
2. 자체 캡슐화된 전송 http 요청 인터페이스
/** * 发送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.php로 캡슐화된 요청 개체의 전송 메서드
nategood /httpful의 Request::send 메소드는 PHP의 컬_exec 인터페이스를 사용하여 http 요청을 시작합니다.
/** * 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.curl_exec가 호출되기 전의 url값
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"]}}
현상 2 - 브라우저에서 url에 직접 접근
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]}}
원인 분석
현상 1과 현상 2의 url 값을 비교하면 다음을 확인할 수 있습니다.
fileIndex 매개변수 값이 json 문자열입니다
fileIndex 매개변수 값의 title 속성은 현상 2에서 값의 공백 문자가 %20으로 인코딩되고, 큰따옴표 "가 %22로 인코딩됩니다. 이 작업은 브라우저
에서 자동으로 수행됩니다. URL의 공백을 인코딩하면 컬_exec 인터페이스는 200을 반환합니다
테스트 코드
_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);?>
퍼센트 인코딩(예: URL 인코딩)
일반적으로 URL은 영어만 사용할 수 있습니다. 문자, 아라비아 숫자 및 특정 구두점 기호, 기타 단어 및 기호는 사용할 수 없습니다. Ruan Yifeng은 자신의 블로그 게시물에서 네트워크 표준 RFC 1738에 엄격한 규칙이 있다고 언급했습니다.
"...영숫자만 [0- 9a-zA-Z], 특수 문자 "$-.+!*'()", [따옴표 제외 - ed] 및 예약된 목적으로 사용되는 예약 문자는 URL 내에서 인코딩되지 않은 상태로 사용될 수 있습니다."
"문자와 숫자[0-9a-zA-Z], 일부 특수 기호 "$-.+!*'()", [큰따옴표 제외] 및 특정 예약어만 인코딩 없이 URL에 직접 사용할 수 있습니다. . "
URL 인코딩은 특정 컨텍스트에서 URL(Uniform Resource Locator)의 인코딩 메커니즘입니다. 서버가 http 요청을 구문 분석할 때 비표준 문자를 발견하면 비표준 문자를 인코딩합니다.
요약
http 요청에서 400 오류가 발생하는 경우 일반적으로 잘못된 http 요청(잘못된 요청) 및 잘못된 URL 매개변수 인코딩 형식으로 인해 발생합니다. URL에는 특정 형식 요구 사항이 있으며 일반적으로 영문자와 아랍어를 사용할 수 있습니다. 사용자 URL
에 직접 액세스하려면 숫자와 일부 특수 문자, 공백 및 큰따옴표와 같은 기타 문자를 인코딩해야 브라우저가 자동으로 인코딩합니다.
하지만 프로그램에서 직접 호출할 때는 URL을 미리 인코딩해야 합니다. 예를 들어, 컬_exec를 사용하여 PHP를 호출할 때는 특히 공백
과 같은 잘못된 문자를 인코딩해야 합니다. url 매개변수에 json 데이터 값이 포함된 경우