/** * @covers Guzzle\Guzzle::getCurlInfo * @covers Guzzle\Guzzle::reset */ public function testDeterminesIfCurlCanFollowLocation() { Guzzle::reset(); if (!ini_get('open_basedir')) { $this->assertTrue(Guzzle::getCurlInfo('follow_location')); } else { $this->assertFalse(Guzzle::getCurlInfo('follow_location')); } }
/** * Factory method to create a new curl handle based on an HTTP request * * There are some helpful options you can set to enable specific behavior: * - disabled_wire: This is a performance improvement that will disable * some debugging functionality with cURL. The functionality * it disabled allows you to see the exact HTTP request sent over * the wire. * - progress: Set to true to enable progress function callbacks. Most * People don't need this, so it has been disabled by default. * * @param RequestInterface $request Request * * @return CurlHandle */ public static function factory(RequestInterface $request) { $handle = curl_init(); $mediator = new RequestMediator($request); $requestCurlOptions = $request->getCurlOptions(); // Array of default cURL options. $curlOptions = array(CURLOPT_URL => $request->getUrl(), CURLOPT_CUSTOMREQUEST => $request->getMethod(), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_USERAGENT => (string) $request->getHeader('User-Agent'), CURLOPT_ENCODING => '', CURLOPT_PORT => $request->getPort(), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1, CURLOPT_HTTPHEADER => array(), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader')); // Enable the progress function if the 'progress' param was set if ($requestCurlOptions->get('progress')) { $curlOptions[CURLOPT_PROGRESSFUNCTION] = array($mediator, 'progress'); $curlOptions[CURLOPT_NOPROGRESS] = false; } // Enable curl debug information if the 'debug' param was set if (!$requestCurlOptions->get('disable_wire')) { $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+'); $curlOptions[CURLOPT_VERBOSE] = true; } // HEAD requests need no response body, everything else might if ($request->getMethod() != 'HEAD') { $curlOptions[CURLOPT_WRITEFUNCTION] = array($mediator, 'writeResponseBody'); } // Account for PHP installations with safe_mode or open_basedir enabled // @codeCoverageIgnoreStart if (Guzzle::getCurlInfo('follow_location')) { $curlOptions[CURLOPT_FOLLOWLOCATION] = true; $curlOptions[CURLOPT_MAXREDIRS] = 5; } // @codeCoverageIgnoreEnd $headers = $request->getHeaders()->getAll(); // Specify settings according to the HTTP method switch ($request->getMethod()) { case 'GET': $curlOptions[CURLOPT_HTTPGET] = true; break; case 'HEAD': $curlOptions[CURLOPT_NOBODY] = true; unset($curlOptions[CURLOPT_WRITEFUNCTION]); break; case 'POST': $curlOptions[CURLOPT_POST] = true; break; case 'PUT': case 'PATCH': $curlOptions[CURLOPT_UPLOAD] = true; if ($request->hasHeader('Content-Length')) { unset($headers['Content-Length']); $curlOptions[CURLOPT_INFILESIZE] = (int) (string) $request->getHeader('Content-Length'); } break; } if ($request instanceof EntityEnclosingRequestInterface) { // If no body is being sent, always send Content-Length of 0 if (!$request->getBody() && !count($request->getPostFields())) { $headers['Content-Length'] = 0; unset($headers['Transfer-Encoding']); // Need to remove CURLOPT_UPLOAD to prevent chunked encoding unset($curlOptions[CURLOPT_UPLOAD]); unset($curlOptions[CURLOPT_POST]); // Not reading from a callback when using empty body unset($curlOptions[CURLOPT_READFUNCTION]); } else { // Add a callback for curl to read data to send with the request $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody'); } // If the Expect header is not present, prevent curl from adding it if (!$request->hasHeader('Expect')) { $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:'; } } // Set custom cURL options foreach ($requestCurlOptions as $key => $value) { if (is_numeric($key)) { $curlOptions[$key] = $value; } } // Check if any headers or cURL options are blacklisted $client = $request->getClient(); if ($client) { $blacklist = $client->getConfig('curl.blacklist'); if ($blacklist) { foreach ($blacklist as $value) { if (strpos($value, 'header.') === 0) { $blacklistHeader = substr($value, 7); // Remove headers that may have previously been set // but are supposed to be blacklisted unset($headers[$blacklistHeader]); $headers[$blacklistHeader] = ''; } else { unset($curlOptions[$value]); } } } } // Add any custom headers to the request. Emtpy headers will cause curl to // not send the header at all. foreach ($headers as $key => $value) { foreach ((array) $value as $val) { $curlOptions[CURLOPT_HTTPHEADER][] = trim("{$key}: {$val}"); } } // Apply the options to the cURL handle. curl_setopt_array($handle, $curlOptions); $request->getParams()->set('curl.last_options', $curlOptions); return new static($handle, $curlOptions); }