/** * Add a HTTP call to the data * * @param Request $request Call request * @param Response $response Call response * @param float $time duration of the call */ public static function addCall($request, $response, $time = null) { $calls = static::config('calls'); $trace = Debugger::trace(['start' => 2]); $calls[] = ['request' => ['uri' => (string) $request->getUri(), 'body' => $request->body(), 'method' => $request->getMethod(), 'headers' => $request->getHeaders(), 'content-type' => $request->getHeader('Content-Type')], 'response' => ['body' => $response->body(), 'status_code' => $response->getStatusCode(), 'headers' => $response->getHeaders(), 'content-type' => $response->getHeader('Content-Type')], 'time' => $time, 'trace' => $trace]; static::drop('calls'); static::config('calls', $calls); }
/** * Sorts and normalizes request data and oauthValues * * Section 9.1.1 of Oauth spec. * * - URL encode keys + values. * - Sort keys & values by byte value. * * @param \Cake\Http\Client\Request $request The request object. * @param array $oauthValues Oauth values. * @return string sorted and normalized values */ protected function _normalizedParams($request, $oauthValues) { $query = parse_url($request->url(), PHP_URL_QUERY); parse_str($query, $queryArgs); $post = []; $body = $request->body(); if (is_string($body) && $request->getHeaderLine('content-type') === 'application/x-www-form-urlencoded') { parse_str($body, $post); } if (is_array($body)) { $post = $body; } $args = array_merge($queryArgs, $oauthValues, $post); uksort($args, 'strcmp'); $pairs = []; foreach ($args as $k => $val) { if (is_array($val)) { sort($val, SORT_STRING); foreach ($val as $nestedVal) { $pairs[] = "{$k}={$nestedVal}"; } } else { $pairs[] = "{$k}={$val}"; } } return implode('&', $pairs); }
/** * Generate the header Authorization * * @param \Cake\Http\Client\Request $request The request object. * @param array $credentials Authentication credentials. * @return string */ protected function _generateHeader(Request $request, $credentials) { $path = $request->getUri()->getPath(); $a1 = md5($credentials['username'] . ':' . $credentials['realm'] . ':' . $credentials['password']); $a2 = md5($request->method() . ':' . $path); if (empty($credentials['qop'])) { $response = md5($a1 . ':' . $credentials['nonce'] . ':' . $a2); } else { $credentials['cnonce'] = uniqid(); $nc = sprintf('%08x', $credentials['nc']++); $response = md5($a1 . ':' . $credentials['nonce'] . ':' . $nc . ':' . $credentials['cnonce'] . ':auth:' . $a2); } $authHeader = 'Digest '; $authHeader .= 'username="******"'], ['\\\\', '\\"'], $credentials['username']) . '", '; $authHeader .= 'realm="' . $credentials['realm'] . '", '; $authHeader .= 'nonce="' . $credentials['nonce'] . '", '; $authHeader .= 'uri="' . $path . '", '; $authHeader .= 'response="' . $response . '"'; if (!empty($credentials['opaque'])) { $authHeader .= ', opaque="' . $credentials['opaque'] . '"'; } if (!empty($credentials['qop'])) { $authHeader .= ', qop="auth", nc=' . $nc . ', cnonce="' . $credentials['cnonce'] . '"'; } return $authHeader; }
/** * Open the stream and send the request. * * @param \Cake\Http\Client\Request $request The request object. * @return array Array of populated Response objects * @throws \Cake\Core\Exception\Exception */ protected function _send(Request $request) { $deadline = false; if (isset($this->_contextOptions['timeout']) && $this->_contextOptions['timeout'] > 0) { $deadline = time() + $this->_contextOptions['timeout']; } $url = $request->url(); $this->_open($url); $content = ''; $timedOut = false; while (!feof($this->_stream)) { if ($deadline !== false) { stream_set_timeout($this->_stream, max($deadline - time(), 1)); } $content .= fread($this->_stream, 8192); $meta = stream_get_meta_data($this->_stream); if ($meta['timed_out'] || $deadline !== false && time() > $deadline) { $timedOut = true; break; } } $meta = stream_get_meta_data($this->_stream); fclose($this->_stream); if ($timedOut) { throw new Exception('Connection timed out ' . $url); } $headers = $meta['wrapper_data']; if (isset($headers['headers']) && is_array($headers['headers'])) { $headers = $headers['headers']; } return $this->createResponses($headers, $content); }
/** * Creates a new request object based on the parameters. * * @param string $method HTTP method name. * @param string $url The url including query string. * @param mixed $data The request body. * @param array $options The options to use. Contains auth, proxy etc. * @return \Cake\Http\Client\Request */ protected function _createRequest($method, $url, $data, $options) { $headers = isset($options['headers']) ? (array) $options['headers'] : []; if (isset($options['type'])) { $headers = array_merge($headers, $this->_typeHeaders($options['type'])); } if (is_string($data) && !isset($headers['Content-Type']) && !isset($headers['content-type'])) { $headers['Content-Type'] = 'application/x-www-form-urlencoded'; } $request = new Request($url, $method, $headers, $data); $request->cookie($this->_cookies->get($url)); if (isset($options['cookies'])) { $request->cookie($options['cookies']); } if (isset($options['auth'])) { $request = $this->_addAuthentication($request, $options); } if (isset($options['proxy'])) { $request = $this->_addProxy($request, $options); } return $request; }