* @package generis */ class common_http_Request { const METHOD_POST = 'POST'; const METHOD_GET = 'GET'; /** * Creates an request from the current call * * The scheme in used (http|https) will be derived from * * * $_SERVER['HTTPS'] in case of a standard deployment * * $_SERVER['HTTP_X_FORWARDED_PROTO'] or $_SERVER['HTTP_X_FORWARDED_SSL'] in case of being deployed behing a load balancer/proxy. * * If no clues about whether HTTPS is in use are found, HTTP will be the scheme of the current request. * * @return common_http_Request A request corresponding to the current HTTP(S) context. * @throws common_exception_Error In case of a CLI execution context. */ public static function currentRequest() { if (php_sapi_name() == 'cli') { throw new common_exception_Error('Cannot call ' . __FUNCTION__ . ' from command line'); } $https = self::isHttps(); $scheme = $https ? 'https' : 'http'; $port = empty($_SERVER['HTTP_X_FORWARDED_PORT']) ? $_SERVER['SERVER_PORT'] : $_SERVER['HTTP_X_FORWARDED_PORT']; $url = $scheme . '://' . $_SERVER['SERVER_NAME'] . ':' . $port . $_SERVER['REQUEST_URI']; $method = $_SERVER['REQUEST_METHOD']; if ($_SERVER['REQUEST_METHOD'] == self::METHOD_GET) { $params = $_GET; } else { $params = $_POST; } if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); } else { $headers = []; if (isset($_SERVER['CONTENT_TYPE'])) { $headers['Content-Type'] = $_SERVER['CONTENT_TYPE']; } if (isset($_ENV['CONTENT_TYPE'])) { $headers['Content-Type'] = $_ENV['CONTENT_TYPE']; } foreach ($_SERVER as $key => $value) { if (substr($key, 0, 5) == "HTTP_") { // this is chaos, basically it is just there to capitalize the first // letter of every word that is not an initial HTTP and strip HTTP // code from przemek $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5))))); $headers[$key] = $value; } } } return new self($url, $method, $params, $headers); } private $url; private $method; private $params; private $headers; private $body; public function __construct($url, $method = self::METHOD_POST, $params = [], $headers = [], $body = "") { $this->url = $url; $this->method = $method; $this->params = $params; $this->headers = $headers; $this->body = $body; } /** * Detect whether we use https or http * @return bool */ public static function isHttps() { // Default is http scheme. $https = false; if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") { // $_SERVER['HTTPS'] is NOT set behind a proxy / load balancer $https = true; } elseif ( // $_SERVER['HTTPS'] is set behind a proxy / load balancer !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on' ) { $https = true; } return $https; } public function getUrl() { return $this->url; } public function getMethod() { return $this->method; } public function getParams() { return $this->params; } public function setParam($key, $value) { return $this->params[$key] = $value; } public function setHeader($key, $value) { return $this->headers[$key] = $value; } public function getHeaders() { return $this->headers; } /** * Get the value of an HTTP header * The lookup is case insensitive. * @param string $headerName the HTTP header name, 'Content-Type' for example * @return boolean|string the value or false if not found */ public function getHeaderValue($headerName) { if (is_string($headerName) && count($this->headers) > 0) { $lowCaseHeaders = array_change_key_case($this->headers, CASE_LOWER); $lowCaseHeaderName = strtolower($headerName); if (isset($lowCaseHeaders[$lowCaseHeaderName])) { return $lowCaseHeaders[$lowCaseHeaderName]; } } return false; } /** * set request body to send */ public function setBody($requestBodyData) { $this->body = $requestBodyData; } public function getBody() { return $this->body; } /** * @return common_http_Response */ public function send() { $curlHandler = curl_init($this->getUrl()); //set the headers if ((is_array($this->headers)) and (count($this->headers) > 0)) { curl_setopt($curlHandler, CURLOPT_HTTPHEADER, self::headerEncode($this->headers)); } switch ($this->getMethod()) { case "HEAD":{ curl_setopt($curlHandler, CURLOPT_NOBODY, true); curl_setopt($curlHandler, CURLOPT_HEADER, true); break; } case "POST":{ curl_setopt($curlHandler, CURLOPT_POST, 1); if (is_array($this->params) and (count($this->params) > 0)) { $params = $this->postEncode($this->params); //application/x-www-form-urlencoded curl_setopt($curlHandler, CURLOPT_POSTFIELDS, $params); } else { //common_Logger::i(serialize($this->getBody())); if (!is_null(($this->getBody()))) { curl_setopt($curlHandler, CURLOPT_POSTFIELDS, ($this->getBody())); } } //analyse if there is a body or structured postfields break; } case "PUT":{ break; } case "GET":{ //curl_setopt($curlHandler,CURLOPT_HTTPGET, true); break; } } curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, 1); //curl_setopt($curlHandler, CURLINFO_HEADER_OUT, 1); //curl_setopt($curlHandler, CURLOPT_HEADER, true); $responseData = curl_exec($curlHandler); $httpResponse = new common_http_Response(); $httpResponse->httpCode = curl_getinfo($curlHandler, CURLINFO_HTTP_CODE); $httpResponse->headerOut = curl_getinfo($curlHandler, CURLINFO_HEADER_OUT); $httpResponse->effectiveUrl = curl_getinfo($curlHandler, CURLINFO_EFFECTIVE_URL); $httpResponse->responseData = $responseData; //curl_setopt($curlHandler, ); curl_close($curlHandler); return $httpResponse; } /** * @param array * @return string */ public static function postEncode($parameters) { //todo //$content_type = isset($this->headers['Content-Type']) ? $this->headers['Content-Type'] : 'text/plain'; //should detect suitable encoding $format = 'text/plain'; switch ($format) { default: return http_build_query($parameters, null, '&'); break; } } public static function headerEncode($headers) { $encodedHeaders = []; //todo using aray_walk foreach ($headers as $key => $value) { $encodedHeaders[] = $key . ": " . $value . ""; } //print_r($encodedHeaders); return $encodedHeaders; } }