/** * Calculates length of the request body, adds proper headers * * @param array associative array of request headers, this method will * add proper 'Content-Length' and 'Content-Type' headers * to this array (or remove them if not needed) */ protected function calculateRequestLength(&$headers) { $this->requestBody = $this->request->getBody(); if (is_string($this->requestBody)) { $this->contentLength = strlen($this->requestBody); } elseif (is_resource($this->requestBody)) { $stat = fstat($this->requestBody); $this->contentLength = $stat['size']; rewind($this->requestBody); } else { $this->contentLength = $this->requestBody->getLength(); $headers['content-type'] = 'multipart/form-data; boundary=' . $this->requestBody->getBoundary(); $this->requestBody->rewind(); } if (in_array($this->request->getMethod(), self::$bodyDisallowed) || 0 == $this->contentLength) { // No body: send a Content-Length header nonetheless (request #12900), // but do that only for methods that require a body (bug #14740) if (in_array($this->request->getMethod(), self::$bodyRequired)) { $headers['content-length'] = 0; } else { unset($headers['content-length']); // if the method doesn't require a body and doesn't have a // body, don't send a Content-Type header. (request #16799) unset($headers['content-type']); } } else { if (empty($headers['content-type'])) { $headers['content-type'] = 'application/x-www-form-urlencoded'; } $headers['content-length'] = $this->contentLength; } }
/** * Handles HTTP redirection * * This method will throw an Exception if redirect to a non-HTTP(S) location * is attempted, also if number of redirects performed already is equal to * 'max_redirects' configuration parameter. * * @param Diglin_HTTP_Request2 Original request * @param Diglin_HTTP_Request2_Response Response containing redirect * @return Diglin_HTTP_Request2_Response Response from a new location * @throws Diglin_HTTP_Request2_Exception */ protected function handleRedirect(Diglin_HTTP_Request2 $request, Diglin_HTTP_Request2_Response $response) { if (is_null($this->redirectCountdown)) { $this->redirectCountdown = $request->getConfig('max_redirects'); } if (0 == $this->redirectCountdown) { // Copying cURL behaviour throw new Diglin_HTTP_Request2_Exception('Maximum (' . $request->getConfig('max_redirects') . ') redirects followed'); } $redirectUrl = new Diglin_Net_URL2($response->getHeader('location'), array(Diglin_Net_URL2::OPTION_USE_BRACKETS => $request->getConfig('use_brackets'))); // refuse non-HTTP redirect if ($redirectUrl->isAbsolute() && !in_array($redirectUrl->getScheme(), array('http', 'https'))) { throw new Diglin_HTTP_Request2_Exception('Refusing to redirect to a non-HTTP URL ' . $redirectUrl->__toString()); } // Theoretically URL should be absolute (see http://tools.ietf.org/html/rfc2616#section-14.30), // but in practice it is often not if (!$redirectUrl->isAbsolute()) { $redirectUrl = $request->getUrl()->resolve($redirectUrl); } $redirect = clone $request; $redirect->setUrl($redirectUrl); if (303 == $response->getStatus() || !$request->getConfig('strict_redirects') && in_array($response->getStatus(), array(301, 302))) { $redirect->setMethod(Diglin_HTTP_Request2::METHOD_GET); $redirect->setBody(''); } if (0 < $this->redirectCountdown) { $this->redirectCountdown--; } return $this->sendRequest($redirect); }
/** * Tries to detect MIME type of a file * * The method will try to use fileinfo extension if it is available, * deprecated mime_content_type() function in the other case. If neither * works, default 'application/octet-stream' MIME type is returned * * @param string filename * @return string file MIME type */ protected static function detectMimeType($filename) { // finfo extension from PECL available if (function_exists('finfo_open')) { if (!isset(self::$_fileinfoDb)) { self::$_fileinfoDb = @finfo_open(FILEINFO_MIME); } if (self::$_fileinfoDb) { $info = finfo_file(self::$_fileinfoDb, $filename); } } // (deprecated) mime_content_type function available if (empty($info) && function_exists('mime_content_type')) { return mime_content_type($filename); } return empty($info) ? 'application/octet-stream' : $info; }
/** * Sends request to the remote server and returns its response * * @param Diglin_HTTP_Request2 * @return Diglin_HTTP_Request2_Response * @throws Diglin_HTTP_Request2_Exception */ public function sendRequest(Diglin_HTTP_Request2 $request) { if (!extension_loaded('curl')) { throw new Diglin_HTTP_Request2_Exception('cURL extension not available'); } $this->request = $request; $this->response = null; $this->position = 0; $this->eventSentHeaders = false; $this->eventReceivedHeaders = false; try { if (false === curl_exec($ch = $this->createCurlHandle())) { $errorMessage = 'Error sending request: #' . curl_errno($ch) . ' ' . curl_error($ch); } } catch (Exception $e) { } $this->lastInfo = curl_getinfo($ch); curl_close($ch); $response = $this->response; unset($this->request, $this->requestBody, $this->response); if (!empty($e)) { throw $e; } elseif (!empty($errorMessage)) { throw new Diglin_HTTP_Request2_Exception($errorMessage); } if (0 < $this->lastInfo['size_download']) { $request->setLastEvent('receivedBody', $response); } return $response; }