/** * Creates a context supporting HTTP proxies * * @param string $url URL the context is to be used for * @param array $defaultOptions Options to merge with the default * @param array $defaultParams Parameters to specify on the context * @return resource Default context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled */ public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array()) { $options = array('http' => array('follow_location' => 1, 'max_redirects' => 20)); // Handle system proxy if (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy'])) { // Some systems seem to rely on a lowercased version instead... $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); } // Override with HTTPS proxy if present and URL is https if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) { $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']); } // Remove proxy if URL matches no_proxy directive if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) { $pattern = new NoProxyPattern($_SERVER['no_proxy']); if ($pattern->test($url)) { unset($proxy); } } if (!empty($proxy)) { $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : ''; $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; if (isset($proxy['port'])) { $proxyURL .= ":" . $proxy['port']; } elseif ('http://' == substr($proxyURL, 0, 7)) { $proxyURL .= ":80"; } elseif ('https://' == substr($proxyURL, 0, 8)) { $proxyURL .= ":443"; } // http(s):// is not supported in proxy $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) { throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); } $options['http']['proxy'] = $proxyURL; // enabled request_fulluri unless it is explicitly disabled switch (parse_url($url, PHP_URL_SCHEME)) { case 'http': // default request_fulluri to true $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI'); if ($reqFullUriEnv === false || $reqFullUriEnv === '' || strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) { $options['http']['request_fulluri'] = true; } break; case 'https': // default request_fulluri to true $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI'); if ($reqFullUriEnv === false || $reqFullUriEnv === '' || strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) { $options['http']['request_fulluri'] = true; } break; } // add SNI opts for https URLs if ('https' === parse_url($url, PHP_URL_SCHEME)) { $options['ssl']['SNI_enabled'] = true; if (version_compare(PHP_VERSION, '5.6.0', '<')) { $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST); } } // handle proxy auth if present if (isset($proxy['user'])) { $auth = urldecode($proxy['user']); if (isset($proxy['pass'])) { $auth .= ':' . urldecode($proxy['pass']); } $auth = base64_encode($auth); // Preserve headers if already set in default options if (isset($defaultOptions['http']['header'])) { if (is_string($defaultOptions['http']['header'])) { $defaultOptions['http']['header'] = array($defaultOptions['http']['header']); } $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}"; } else { $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}"); } } } $options = array_replace_recursive($options, $defaultOptions); if (isset($options['http']['header'])) { $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']); } return stream_context_create($options, $defaultParams); }
public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array()) { $options = array('http' => array('follow_location' => 1, 'max_redirects' => 20)); if (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy'])) { $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); } if (!empty($proxy)) { $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : ''; $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; if (isset($proxy['port'])) { $proxyURL .= ":" . $proxy['port']; } elseif ('http://' == substr($proxyURL, 0, 7)) { $proxyURL .= ":80"; } elseif ('https://' == substr($proxyURL, 0, 8)) { $proxyURL .= ":443"; } $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) { throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); } $options['http']['proxy'] = $proxyURL; if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) { $pattern = new NoProxyPattern($_SERVER['no_proxy']); if ($pattern->test($url)) { unset($options['http']['proxy']); } } if (!empty($options['http']['proxy'])) { switch (parse_url($url, PHP_URL_SCHEME)) { case 'http': $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI'); if ($reqFullUriEnv === false || $reqFullUriEnv === '' || strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) { $options['http']['request_fulluri'] = true; } break; case 'https': $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI'); if ($reqFullUriEnv === false || $reqFullUriEnv === '' || strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) { $options['http']['request_fulluri'] = true; } break; } if (isset($proxy['user'])) { $auth = urldecode($proxy['user']); if (isset($proxy['pass'])) { $auth .= ':' . urldecode($proxy['pass']); } $auth = base64_encode($auth); if (isset($defaultOptions['http']['header'])) { if (is_string($defaultOptions['http']['header'])) { $defaultOptions['http']['header'] = array($defaultOptions['http']['header']); } $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}"; } else { $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}"); } } } } $options = array_replace_recursive($options, $defaultOptions); if (isset($options['http']['header'])) { $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']); } return stream_context_create($options, $defaultParams); }