public function testMultilineHeader() { $values = $this->readResponse('response_multiline_header'); $response = Stream::fromStream($values['data'], $values['stream']); // Make sure we got the corrent no. of headers $this->assertEquals(6, count($response->getHeaders()), 'Header count is expected to be 6'); // Check header integrity $this->assertEquals('timeout=15,max=100', $response->getHeaders()->get('keep-alive')->getFieldValue()); $this->assertEquals('text/html;charset=iso-8859-1', $response->getHeaders()->get('content-type')->getFieldValue()); }
/** * Send HTTP request * * @param Request $request * @return Response * @throws Exception\RuntimeException * @throws Client\Exception\RuntimeException */ public function send(Request $request = null) { if ($request !== null) { $this->setRequest($request); } $this->redirectCounter = 0; $response = null; $adapter = $this->getAdapter(); // Send the first request. If redirected, continue. do { // uri $uri = $this->getUri(); // query $query = $this->getRequest()->getQuery(); if (!empty($query)) { $queryArray = $query->toArray(); if (!empty($queryArray)) { $newUri = $uri->toString(); $queryString = http_build_query($queryArray, null, $this->getArgSeparator()); if ($this->config['rfc3986strict']) { $queryString = str_replace('+', '%20', $queryString); } if (strpos($newUri, '?') !== false) { $newUri .= $this->getArgSeparator() . $queryString; } else { $newUri .= '?' . $queryString; } $uri = new Http($newUri); } } // If we have no ports, set the defaults if (!$uri->getPort()) { $uri->setPort($uri->getScheme() == 'https' ? 443 : 80); } // method $method = $this->getRequest()->getMethod(); // this is so the correct Encoding Type is set $this->setMethod($method); // body $body = $this->prepareBody(); // headers $headers = $this->prepareHeaders($body, $uri); $secure = $uri->getScheme() == 'https'; // cookies $cookie = $this->prepareCookies($uri->getHost(), $uri->getPath(), $secure); if ($cookie->getFieldValue()) { $headers['Cookie'] = $cookie->getFieldValue(); } // check that adapter supports streaming before using it if (is_resource($body) && !$adapter instanceof Client\Adapter\StreamInterface) { throw new Client\Exception\RuntimeException('Adapter does not support streaming'); } // calling protected method to allow extending classes // to wrap the interaction with the adapter $response = $this->doRequest($uri, $method, $secure, $headers, $body); if (!$response) { throw new Exception\RuntimeException('Unable to read response, or response is empty'); } if ($this->config['storeresponse']) { $this->lastRawResponse = $response; } else { $this->lastRawResponse = null; } if ($this->config['outputstream']) { $stream = $this->getStream(); if (!is_resource($stream) && is_string($stream)) { $stream = fopen($stream, 'r'); } $streamMetaData = stream_get_meta_data($stream); if ($streamMetaData['seekable']) { rewind($stream); } // cleanup the adapter $adapter->setOutputStream(null); $response = Response\Stream::fromStream($response, $stream); $response->setStreamName($this->streamName); if (!is_string($this->config['outputstream'])) { // we used temp name, will need to clean up $response->setCleanup(true); } } else { $response = $this->getResponse()->fromString($response); } // Get the cookies from response (if any) $setCookies = $response->getCookie(); if (!empty($setCookies)) { $this->addCookie($setCookies); } // If we got redirected, look for the Location header if ($response->isRedirect() && $response->getHeaders()->has('Location')) { // Avoid problems with buggy servers that add whitespace at the // end of some headers $location = trim($response->getHeaders()->get('Location')->getFieldValue()); // Check whether we send the exact same request again, or drop the parameters // and send a GET request if ($response->getStatusCode() == 303 || !$this->config['strictredirects'] && ($response->getStatusCode() == 302 || $response->getStatusCode() == 301)) { $this->resetParameters(false, false); $this->setMethod(Request::METHOD_GET); } // If we got a well formed absolute URI if (($scheme = substr($location, 0, 6)) && ($scheme == 'http:/' || $scheme == 'https:')) { // setURI() clears parameters if host changed, see #4215 $this->setUri($location); } else { // Split into path and query and set the query if (strpos($location, '?') !== false) { list($location, $query) = explode('?', $location, 2); } else { $query = ''; } $this->getUri()->setQuery($query); // Else, if we got just an absolute path, set it if (strpos($location, '/') === 0) { $this->getUri()->setPath($location); // Else, assume we have a relative path } else { // Get the current path directory, removing any trailing slashes $path = $this->getUri()->getPath(); $path = rtrim(substr($path, 0, strrpos($path, '/')), "/"); $this->getUri()->setPath($path . '/' . $location); } } ++$this->redirectCounter; } else { // If we didn't get any location, stop redirecting break; } } while ($this->redirectCounter <= $this->config['maxredirects']); $this->response = $response; return $response; }
/** * Send the HTTP request and return an HTTP response object * * @param string $method * @return \Zend\Http\Response * @throws \Zend\Http\Client\Exception */ public function request($method = null) { if (!$this->uri instanceof Uri\Url) { throw new Client\Exception('No valid URI has been passed to the client'); } if ($method) { $this->setMethod($method); } $this->redirectCounter = 0; $response = null; // Make sure the adapter is loaded if ($this->adapter == null) { $this->setAdapter($this->config['adapter']); } // Send the first request. If redirected, continue. do { // Clone the URI and add the additional GET parameters to it $uri = clone $this->uri; if (!empty($this->paramsGet)) { $query = $uri->getQuery(); if (!empty($query)) { $query .= '&'; } $query .= http_build_query($this->paramsGet, null, '&'); $uri->setQuery($query); } $body = $this->_prepareBody(); $headers = $this->_prepareHeaders(); // check that adapter supports streaming before using it if (is_resource($body) && !$this->adapter instanceof Client\Adapter\Stream) { throw new Client\Exception('Adapter does not support streaming'); } // Open the connection, send the request and read the response $this->adapter->connect($uri->getHost(), $uri->getPort(), $uri->getScheme() == 'https' ? true : false); if ($this->config['output_stream']) { if ($this->adapter instanceof Client\Adapter\Stream) { $stream = $this->_openTempStream(); $this->adapter->setOutputStream($stream); } else { throw new Client\Exception('Adapter does not support streaming'); } } $this->last_request = $this->adapter->write($this->method, $uri, $this->config['httpversion'], $headers, $body); $response = $this->adapter->read(); if (!$response) { throw new Client\Exception('Unable to read response, or response is empty'); } if ($this->config['output_stream']) { rewind($stream); // cleanup the adapter $this->adapter->setOutputStream(null); $response = Response\Stream::fromStream($response, $stream); $response->setStreamName($this->_stream_name); if (!is_string($this->config['output_stream'])) { // we used temp name, will need to clean up $response->setCleanup(true); } } else { $response = Response::fromString($response); } if ($this->config['storeresponse']) { $this->last_response = $response; } // Load cookies into cookie jar if (isset($this->cookiejar)) { $this->cookiejar->addCookiesFromResponse($response, $uri); } // If we got redirected, look for the Location header if ($response->isRedirect() && ($location = $response->getHeader('location'))) { // Check whether we send the exact same request again, or drop the parameters // and send a GET request if ($response->getStatus() == 303 || !$this->config['strictredirects'] && ($response->getStatus() == 302 || $response->getStatus() == 301)) { $this->resetParameters(); $this->setMethod(self::GET); } // If we got a well formed absolute URI $url = new Uri\Url($location); if ($url->isValid()) { $this->setHeaders('host', null); $this->setUri($location); } else { // Split into path and query and set the query if (strpos($location, '?') !== false) { list($location, $query) = explode('?', $location, 2); } else { $query = ''; } $this->uri->setQuery($query); // Else, if we got just an absolute path, set it if (strpos($location, '/') === 0) { $this->uri->setPath($location); // Else, assume we have a relative path } else { // Get the current path directory, removing any trailing slashes $path = $this->uri->getPath(); $path = rtrim(substr($path, 0, strrpos($path, '/')), "/"); $this->uri->setPath($path . '/' . $location); } } ++$this->redirectCounter; } else { // If we didn't get any location, stop redirecting break; } } while ($this->redirectCounter < $this->config['maxredirects']); return $response; }