Curl::setup_handle( string $url, array $headers, string|array $data, array $options )

In this article

This function’s access is marked private. This means it is not intended for use by plugin or theme developers, only in other core functions. It is listed here for completeness.

Setup the cURL handle for the given data

Parameters

$urlstringrequired
URL to request
$headersarrayrequired
Associative array of request headers
$datastring|arrayrequired
Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
$optionsarrayrequired
Request options, see WpOrgRequestsRequests::response() for documentation

Source

private function setup_handle($url, $headers, $data, $options) {
	$options['hooks']->dispatch('curl.before_request', [&$this->handle]);

	// Force closing the connection for old versions of cURL (<7.22).
	if ($this->version < self::CURL_7_22_0 && !isset($headers['Connection'])) {
		$headers['Connection'] = 'close';
	}

	/**
	 * Add "Expect" header.
	 *
	 * By default, cURL adds a "Expect: 100-Continue" to most requests. This header can
	 * add as much as a second to the time it takes for cURL to perform a request. To
	 * prevent this, we need to set an empty "Expect" header. To match the behaviour of
	 * Guzzle, we'll add the empty header to requests that are smaller than 1 MB and use
	 * HTTP/1.1.
	 *
	 * https://curl.se/mail/lib-2017-07/0013.html
	 */
	if (!isset($headers['Expect']) && $options['protocol_version'] === 1.1) {
		$headers['Expect'] = $this->get_expect_header($data);
	}

	$headers = Requests::flatten($headers);

	if (!empty($data)) {
		$data_format = $options['data_format'];

		if ($data_format === 'query') {
			$url  = self::format_get($url, $data);
			$data = '';
		} elseif (!is_string($data)) {
			$data = http_build_query($data, '', '&');
		}
	}

	switch ($options['type']) {
		case Requests::POST:
			curl_setopt($this->handle, CURLOPT_POST, true);
			curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data);
			break;
		case Requests::HEAD:
			curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']);
			curl_setopt($this->handle, CURLOPT_NOBODY, true);
			break;
		case Requests::TRACE:
			curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']);
			break;
		case Requests::PATCH:
		case Requests::PUT:
		case Requests::DELETE:
		case Requests::OPTIONS:
		default:
			curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']);
			if (!empty($data)) {
				curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data);
			}
	}

	// cURL requires a minimum timeout of 1 second when using the system
	// DNS resolver, as it uses `alarm()`, which is second resolution only.
	// There's no way to detect which DNS resolver is being used from our
	// end, so we need to round up regardless of the supplied timeout.
	//
	// https://github.com/curl/curl/blob/4f45240bc84a9aa648c8f7243be7b79e9f9323a5/lib/hostip.c#L606-L609
	$timeout = max($options['timeout'], 1);

	if (is_int($timeout) || $this->version < self::CURL_7_16_2) {
		curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout));
	} else {
		// phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_timeout_msFound
		curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000));
	}

	if (is_int($options['connect_timeout']) || $this->version < self::CURL_7_16_2) {
		curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout']));
	} else {
		// phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_connecttimeout_msFound
		curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000));
	}

	curl_setopt($this->handle, CURLOPT_URL, $url);
	curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']);
	if (!empty($headers)) {
		curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers);
	}

	if ($options['protocol_version'] === 1.1) {
		curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
	} else {
		curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
	}

	if ($options['blocking'] === true) {
		curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, [$this, 'stream_headers']);
		curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, [$this, 'stream_body']);
		curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE);
	}
}

User Contributed Notes

You must log in before being able to contribute a note or feedback.