status = intval($status); $this->body = $body; $this->version = $version; $this->message = $message; foreach ($headers as $k => $v) { $k = ucwords(strtolower($k)); $this->headers[$k] = $v; } } /** * Check whether the response in successful * * @return boolean */ public function isSuccessful() { return ($this->status >= 200 && $this->status < 300); } /** * Check whether the response is an error * * @return boolean */ public function isError() { return ($this->status >= 400 && $this->status < 600); } /** * Check whether the response is a redirection * * @return boolean */ public function isRedirect() { return ($this->status >= 300 && $this->status < 400); } /** * Get the HTTP response status code * * @return int */ public function getStatus() { return $this->status; } /** * Return a message describing the HTTP response code * (Eg. "OK", "Not Found", "Moved Permanently") * * @return string */ public function getMessage() { return $this->message; } /** * Get the response body as string * * @return string */ public function getBody() { // Decode the body if it was transfer-encoded switch (strtolower($this->getHeader('transfer-encoding'))) { // Handle chunked body case 'chunked': return self::decodeChunkedBody($this->body); break; // No transfer encoding, or unknown encoding extension: // return body as is default: return $this->body; break; } } /** * Get the raw response body (as transfered "on wire") as string * * If the body is encoded (with Transfer-Encoding, not content-encoding - * IE "chunked" body), gzip compressed, etc. it will not be decoded. * * @return string */ public function getRawBody() { return $this->body; } /** * Get the HTTP version of the response * * @return string */ public function getVersion() { return $this->version; } /** * Get the response headers * * @return array */ public function getHeaders() { return $this->headers; } /** * Get a specific header as string, or null if it is not set * * @param string$header * @return string|array|null */ public function getHeader($header) { $header = ucwords(strtolower($header)); if (array_key_exists($header, $this->headers)) { return $this->headers[$header]; } else { return null; } } /** * Get all headers as string * * @param boolean $statusLine Whether to return the first status line (ie "HTTP 200 OK") * @param string $br Line breaks (eg. "\n", "\r\n", "
") * @return string */ public function getHeadersAsString($statusLine = true, $br = "\n") { $str = ''; if ($statusLine) { $str = "HTTP/{$this->version} {$this->status} {$this->message}{$br}"; } // Iterate over the headers and stringify them foreach ($this->headers as $name => $value) { if (is_string($value)) { $str .= "{$name}: {$value}{$br}"; } elseif (is_array($value)) { foreach ($value as $subval) { $str .= "{$name}: {$subval}{$br}"; } } } return $str; } /** * Create an EasyRdf_Http_Response object from a HTTP response string * * @param string $responseStr * @return EasyRdf_Http_Response */ public static function fromString($responseStr) { // First, split body and headers $matches = preg_split('|(?:\r?\n){2}|m', $responseStr, 2); if ($matches and sizeof($matches) == 2) { list ($headerLines, $body) = $matches; } else { throw new EasyRdf_Exception( "Failed to parse HTTP response." ); } // Split headers part to lines $headerLines = preg_split('|[\r\n]+|m', $headerLines); $status = array_shift($headerLines); if (preg_match("|^HTTP/([\d\.x]+) (\d+) ([^\r\n]+)|", $status, $m)) { $version = $m[1]; $status = $m[2]; $message = $m[3]; } else { throw new EasyRdf_Exception( "Failed to parse HTTP response status line." ); } // Process the rest of the header lines $headers = array(); foreach ($headerLines as $line) { if (preg_match("|^([\w-]+):\s+(.+)$|", $line, $m)) { $hName = ucwords(strtolower($m[1])); $hValue = $m[2]; if (isset($headers[$hName])) { if (! is_array($headers[$hName])) { $headers[$hName] = array($headers[$hName]); } $headers[$hName][] = $hValue; } else { $headers[$hName] = $hValue; } } } return new EasyRdf_Http_Response($status, $headers, $body, $version, $message); } /** * Decode a "chunked" transfer-encoded body and return the decoded text * * @param string $body * @return string */ public static function decodeChunkedBody($body) { $decBody = ''; while (trim($body)) { if (preg_match('/^([\da-fA-F]+)[^\r\n]*\r\n/sm', $body, $m)) { $length = hexdec(trim($m[1])); $cut = strlen($m[0]); $decBody .= substr($body, $cut, $length); $body = substr($body, $cut + $length + 2); } else { throw new EasyRdf_Exception( "Failed to decode chunked body in HTTP response." ); } } return $decBody; } /** * Get the entire response as string * * @param string $br Line breaks (eg. "\n", "\r\n", "
") * @return string */ public function asString($br = "\n") { return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody(); } /** * Implements magic __toString() * * @return string */ public function __toString() { return $this->asString(); } }