/** * 发起http请求, 并返回响应内容 * * @param [string] $path * url的拼接部份,将拼接到urlBase部份 * @param [string] $method * 使用的http请求方法, 目前只支持GET和POST * @param [mixed] $payload * 请求时的附加的数据. * @param [array] $reqHeaders * 请求时附加的header信息 * @param [array] $curlOpts * 每次请求时, 对curl的配置信息. * @throws HttpException 请求异常时, 抛出异常 * @return array http response信息 , 具有如下结构 array( * httpProtocol:'', * status:'', * statusMsg:'', * header:array(), * content:"" * ) */ function request($path = '', $method = "GET", $payload = "", $reqHeaders = null, $curlOpts = null) { if ($path === null) { throw new HttpException('path must be string'); } // 决定访问位置 $url = $this->resolve($path); $curlOptsFinal = $this->currentOpts; if (is_array($curlOpts)) { foreach ($curlOpts as $k => $v) { $curlOptsFinal[$k] = $v; } } if (is_array($reqHeaders)) { if (!is_array($curlOptsFinal[CURLOPT_HTTPHEADER])) { $curlOptsFinal[CURLOPT_HTTPHEADER] = array(); // 这玩意必须是个数组.不是就直接覆盖. } $curlOptsFinal[CURLOPT_HTTPHEADER] = array_merge($curlOptsFinal[CURLOPT_HTTPHEADER], $reqHeaders); //print_r($curlOptsFinal); } $port = parse_url($url, PHP_URL_PORT); $curlOptsFinal[CURLOPT_URL] = $url; $curlOptsFinal[CURLOPT_PORT] = empty($port) ? 80 : $port; $req = curl_init(); curl_setopt_array($req, $curlOptsFinal); switch ($method) { case self::HTTP_GET: curl_setopt($req, CURLOPT_CUSTOMREQUEST, 'GET'); break; case self::HTTP_POST: curl_setopt($req, CURLOPT_POST, true); curl_setopt($req, CURLOPT_POSTFIELDS, $payload); break; default: throw new HttpException("method not be support"); } $response = curl_exec($req); $errCode = curl_errno($req); if ($errCode === 0) { curl_close($req); // log http access $response = $this->parseResponse($response); $status = $response['status']; $this->log->log("HttpRequest: {$status} {$method} {$url}"); return $response; } else { // get message and close curl resource; $errMsg = curl_error($req); curl_close($req); throw new HttpException("curl_error({$errMsg}); with url({$url})", $errCode); } }
} include_once PUSH_SDK_HOME . '/lib/PushSimpleLog.php'; /** * 取得根据http状态码取得对应的默认状态消息 * @param unknown $code */ function send_http_status($code) { static $_status = array(100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Moved Temporarily ', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 509 => 'Bandwidth Limit Exceeded'); if (array_key_exists($code, $_status)) { header('HTTP/1.1 ' . $code . ' ' . $_status[$code]); } } $log = new PushSimpleLog('stdout', 0); if (array_key_exists('q', $_REQUEST)) { $log->log(print_r($_REQUEST['q'], true)); switch ($_REQUEST['q']) { case "404_1": send_http_status(404); echo '{"request_id":100, "error_code":10000 , "error_msg":"what is that??"}'; break; case "404_2": send_http_status(404); echo 'what is this??'; break; case "200_1": send_http_status(200); echo '{"request_id":100, "response_params":[1,2,3,4]}'; break; case "200_2": send_http_status(200);
/** * 解析response并判断响应内容是否正确. * 如果结果符合restAPI结果格式,则返回结果中包含的response_params内容, 否则依据配置中是不是压制错误产生错误或返回null * * @param array $response * 由httpRequest对象get,post,request等方法返回的结果数组 * @return mixed|NULL */ public function parse($response) { extract($response); $this->log->log("Parse Response: {$status}, {$statusMsg}, {$content}"); $result = json_decode($content, true); if ($result !== null && array_key_exists('request_id', $result)) { if ($status == 200) { if (array_key_exists('response_params', $result)) { // 状态200,并且成功解析出json结果. 表示请求成功 $this->onError($result['request_id']); return $result['response_params']; } else { // json可以解析, 但是格式不可理解. $this->onError($result['request_id'], 4, "http status is ok, but REST returned invalid json struct."); } } else { if (array_key_exists('error_code', $result) && array_key_exists('error_msg', $result)) { // 状态不等于200, 但能解析出结果. 表示请求成功, 但是服务端返回错误 $this->onError($result['request_id'], $result['error_code'], $result['error_msg']); } else { // json可以解析, 但是格式不可理解. $this->onError($result['request_id'], 4, "http status is ok, but REST returned invalid json struct."); } } } else { if ($status == 200) { // 无法解析出json, 响应200, $this->onError(null, 4, "http status is ok, but REST returned invalid json string."); } elseif ($status >= 400) { // 无法解析出json, 但是响应一个可理解的http错误 $this->onError(null, $status, "http response status : {$statusMsg}"); } else { // 响应200-399 , 即除200外任意http成功状态, 均不能被理解, 响应 (-1) 错误. $limitContent = strlen($content); if ($limitContent > 0) { $limitContent = substr($content, 200) . "..." . strlen($content); } else { $limitContent = 'Empty'; } $this->onError(null, -1, "Can not process the http response. with status ({$status}, {$statusMsg}), content ({$limitContent});"); } } return false; }