/** * Sends the HTTP message [Request] to a remote server and processes * the response. * * @param Request $request request to send * @param Response $request response to send * @return Response */ public function _send_message(Request $request, Response $response) { $http_method_mapping = array(HTTP_Request::GET => HTTPRequest::METH_GET, HTTP_Request::HEAD => HTTPRequest::METH_HEAD, HTTP_Request::POST => HTTPRequest::METH_POST, HTTP_Request::PUT => HTTPRequest::METH_PUT, HTTP_Request::DELETE => HTTPRequest::METH_DELETE, HTTP_Request::OPTIONS => HTTPRequest::METH_OPTIONS, HTTP_Request::TRACE => HTTPRequest::METH_TRACE, HTTP_Request::CONNECT => HTTPRequest::METH_CONNECT); // Create an http request object $http_request = new HTTPRequest($request->uri(), $http_method_mapping[$request->method()]); if ($this->_options) { // Set custom options $http_request->setOptions($this->_options); } // Set headers $http_request->setHeaders($request->headers()->getArrayCopy()); // Set cookies $http_request->setCookies($request->cookie()); // Set query data (?foo=bar&bar=foo) $http_request->setQueryData($request->query()); // Set the body if ($request->method() == HTTP_Request::PUT) { $http_request->addPutData($request->body()); } else { $http_request->setBody($request->body()); } try { $http_request->send(); } catch (HTTPRequestException $e) { throw new Request_Exception($e->getMessage()); } catch (HTTPMalformedHeaderException $e) { throw new Request_Exception($e->getMessage()); } catch (HTTPEncodingException $e) { throw new Request_Exception($e->getMessage()); } // Build the response $response->status($http_request->getResponseCode())->headers($http_request->getResponseHeader())->cookie($http_request->getResponseCookies())->body($http_request->getResponseBody()); return $response; }
/** * Get the body */ public static function body() { if (is_null(self::$body)) { self::$body = @file_get_contents('php://input'); } return self::$body; }
/** * Basic cache key generator that hashes the entire request and returns * it. This is fine for static content, or dynamic content where user * specific information is encoded into the request. * * // Generate cache key * $cache_key = HTTP_Cache::basic_cache_key_generator($request); * * @param Request $request * @return string */ public static function basic_cache_key_generator(Request $request) { $uri = $request->uri(); $query = $request->query(); $headers = $request->headers()->getArrayCopy(); $body = $request->body(); return sha1($uri . '?' . http_build_query($query, NULL, '&') . '~' . implode('~', $headers) . '~' . $body); }
/** * Sends the HTTP message [Request] to a remote server and processes * the response. * * @param Request request to send * @return Response */ public function _send_message(Request $request) { // Response headers $response_headers = array(); // Set the request method $options[CURLOPT_CUSTOMREQUEST] = $request->method(); // Set the request body. This is perfectly legal in CURL even // if using a request other than POST. PUT does support this method // and DOES NOT require writing data to disk before putting it, if // reading the PHP docs you may have got that impression. SdF $options[CURLOPT_POSTFIELDS] = $request->body(); // Process headers if ($headers = $request->headers()) { $http_headers = array(); foreach ($headers as $key => $value) { $http_headers[] = $key . ': ' . $value; } $options[CURLOPT_HTTPHEADER] = $http_headers; } // Process cookies if ($cookies = $request->cookie()) { $options[CURLOPT_COOKIE] = http_build_query($cookies, NULL, '; '); } // Create response $response = $request->create_response(); $response_header = $response->headers(); // Implement the standard parsing parameters $options[CURLOPT_HEADERFUNCTION] = array($response_header, 'parse_header_string'); $this->_options[CURLOPT_RETURNTRANSFER] = TRUE; $this->_options[CURLOPT_HEADER] = FALSE; // Apply any additional options set to $options += $this->_options; $uri = $request->uri(); if ($query = $request->query()) { $uri .= '?' . http_build_query($query, NULL, '&'); } // Open a new remote connection $curl = curl_init($uri); // Set connection options if (!curl_setopt_array($curl, $options)) { throw new Request_Exception('Failed to set CURL options, check CURL documentation: :url', array(':url' => 'http://php.net/curl_setopt_array')); } // Get the response body $body = curl_exec($curl); // Get the response information $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($body === FALSE) { $error = curl_error($curl); } // Close the connection curl_close($curl); if (isset($error)) { throw new Request_Exception('Error fetching remote :url [ status :code ] :error', array(':url' => $request->url(), ':code' => $code, ':error' => $error)); } $response->status($code)->body($body); return $response; }
/** * Sends the HTTP message [Request] to a remote server and processes * the response. * * @param Request request to send * @return Response * @uses [PHP cURL](http://php.net/manual/en/book.curl.php) */ public function _send_message(Request $request) { // Calculate stream mode $mode = $request->method() === HTTP_Request::GET ? 'r' : 'r+'; // Process cookies if ($cookies = $request->cookie()) { $request->headers('cookie', http_build_query($cookies, NULL, '; ')); } // Get the message body $body = $request->body(); if (is_resource($body)) { $body = stream_get_contents($body); } // Set the content length $request->headers('content-length', (string) strlen($body)); list($protocol) = explode('/', $request->protocol()); // Create the context $options = array(strtolower($protocol) => array('method' => $request->method(), 'header' => (string) $request->headers(), 'content' => $body)); // Create the context stream $context = stream_context_create($options); stream_context_set_option($context, $this->_options); $uri = $request->uri(); if ($query = $request->query()) { $uri .= '?' . http_build_query($query, NULL, '&'); } $stream = fopen($uri, $mode, FALSE, $context); $meta_data = stream_get_meta_data($stream); // Get the HTTP response code $http_response = array_shift($meta_data['wrapper_data']); if (preg_match_all('/(\\w+\\/\\d\\.\\d) (\\d{3})/', $http_response, $matches) !== FALSE) { $protocol = $matches[1][0]; $status = (int) $matches[2][0]; } else { $protocol = NULL; $status = NULL; } // Create a response $response = $request->create_response(); $response_header = $response->headers(); // Process headers array_map(array($response_header, 'parse_header_string'), array(), $meta_data['wrapper_data']); $response->status($status)->protocol($protocol)->body(stream_get_contents($stream)); // Close the stream after use fclose($stream); return $response; }
/** * The default handler for following redirects, triggered by the presence of * a Location header in the response. * * The client's follow property must be set TRUE and the HTTP response status * one of 201, 301, 302, 303 or 307 for the redirect to be followed. * * @param Request $request * @param Response $response * @param Request_Client $client */ public static function on_header_location(Request $request, Response $response, Request_Client $client) { // Do we need to follow a Location header ? if ($client->follow() and in_array($response->status(), array(201, 301, 302, 303, 307))) { // Figure out which method to use for the follow request switch ($response->status()) { default: case 301: case 307: $follow_method = $request->method(); break; case 201: case 303: $follow_method = Request::GET; break; case 302: // Cater for sites with broken HTTP redirect implementations if ($client->strict_redirect()) { $follow_method = $request->method(); } else { $follow_method = Request::GET; } break; } // Prepare the additional request, copying any follow_headers that were present on the original request $orig_headers = $request->headers()->getArrayCopy(); $follow_header_keys = array_intersect(array_keys($orig_headers), $client->follow_headers()); $follow_headers = \Arr::extract($orig_headers, $follow_header_keys); $follow_request = Request::factory($response->headers('Location'))->method($follow_method)->headers($follow_headers); if ($follow_method !== Request::GET) { $follow_request->body($request->body()); } return $follow_request; } return NULL; }
public static function factory($uri = TRUE, $client_params = array(), $allow_external = TRUE, $injected_routes = array()) { if (!Request::$initial) { $protocol = HTTP::$protocol; if (isset($_SERVER['REQUEST_METHOD'])) { $method = $_SERVER['REQUEST_METHOD']; } else { $method = HTTP_Request::GET; } if (!empty($_SERVER['HTTPS']) and filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN) or isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { $secure = TRUE; } if (isset($_SERVER['HTTP_REFERER'])) { $referrer = $_SERVER['HTTP_REFERER']; } if (isset($_SERVER['HTTP_USER_AGENT'])) { Request::$user_agent = $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { $requested_with = $_SERVER['HTTP_X_REQUESTED_WITH']; } if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and isset($_SERVER['REMOTE_ADDR']) and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { $client_ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); Request::$client_ip = array_shift($client_ips); unset($client_ips); } elseif (isset($_SERVER['HTTP_CLIENT_IP']) and isset($_SERVER['REMOTE_ADDR']) and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { $client_ips = explode(',', $_SERVER['HTTP_CLIENT_IP']); Request::$client_ip = array_shift($client_ips); unset($client_ips); } elseif (isset($_SERVER['REMOTE_ADDR'])) { // The remote IP address Request::$client_ip = $_SERVER['REMOTE_ADDR']; } if ($method !== HTTP_Request::GET) { // Ensure the raw body is saved for future use $body = file_get_contents('php://input'); } if ($uri === TRUE) { // Attempt to guess the proper URI $uri = Request::detect_uri(); } $cookies = array(); if ($cookie_keys = array_keys($_COOKIE)) { foreach ($cookie_keys as $key) { $cookies[$key] = Cookie::get($key); } } // Create the instance singleton Request::$initial = $request = new Request($uri, $client_params, $allow_external, $injected_routes); // Store global GET and POST data in the initial request only $request->protocol($protocol)->query($_GET)->post($_POST); if (isset($secure)) { // Set the request security $request->secure($secure); } if (isset($method)) { // Set the request method $request->method($method); } if (isset($referrer)) { // Set the referrer $request->referrer($referrer); } if (isset($requested_with)) { // Apply the requested with variable $request->requested_with($requested_with); } if (isset($body)) { // Set the request body (probably a PUT type) $request->body($body); } if (isset($cookies)) { $request->cookie($cookies); } } else { $request = new Request($uri, $client_params, $allow_external, $injected_routes); } return $request; }
/** * Creates a new request object for the given URI. New requests should be * created using the [Request::instance] or [Request::factory] methods. * * $request = Request::factory($uri); * * If $cache parameter is set, the response for the request will attempt to * be retrieved from the cache. * * @param string $uri URI of the request * @param Cache $cache * @param array $injected_routes an array of routes to use, for testing * @return void * @throws Request_Exception * @uses Route::all * @uses Route::matches */ public static function factory($uri = TRUE, HTTP_Cache $cache = NULL, $injected_routes = array()) { // If this is the initial request if (!Request::$initial) { if (Kohana::$is_cli) { // Default protocol for command line is cli:// $protocol = 'cli'; // Get the command line options $options = CLI::options('uri', 'method', 'get', 'post', 'referrer'); if (isset($options['uri'])) { // Use the specified URI $uri = $options['uri']; } elseif ($uri === TRUE) { $uri = ''; } if (isset($options['method'])) { // Use the specified method $method = strtoupper($options['method']); } else { // Default to GET requests $method = HTTP_Request::GET; } if (isset($options['get'])) { // Overload the global GET data parse_str($options['get'], $_GET); } if (isset($options['post'])) { // Overload the global POST data parse_str($options['post'], $_POST); } if (isset($options['referrer'])) { $referrer = $options['referrer']; } } else { if (isset($_SERVER['SERVER_PROTOCOL'])) { $protocol = $_SERVER['SERVER_PROTOCOL']; } else { $protocol = HTTP::$protocol; } if (isset($_SERVER['REQUEST_METHOD'])) { // Use the server request method $method = $_SERVER['REQUEST_METHOD']; } else { // Default to GET requests $method = HTTP_Request::GET; } if (!empty($_SERVER['HTTPS']) and filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN)) { // This request is secure $secure = TRUE; } if (isset($_SERVER['HTTP_REFERER'])) { // There is a referrer for this request $referrer = $_SERVER['HTTP_REFERER']; } if (isset($_SERVER['HTTP_USER_AGENT'])) { // Browser type Request::$user_agent = $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { // Typically used to denote AJAX requests $requested_with = $_SERVER['HTTP_X_REQUESTED_WITH']; } if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and isset($_SERVER['REMOTE_ADDR']) and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { // Use the forwarded IP address, typically set when the // client is using a proxy server. // Format: "X-Forwarded-For: client1, proxy1, proxy2" $client_ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); Request::$client_ip = array_shift($client_ips); unset($client_ips); } elseif (isset($_SERVER['HTTP_CLIENT_IP']) and isset($_SERVER['REMOTE_ADDR']) and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { // Use the forwarded IP address, typically set when the // client is using a proxy server. $client_ips = explode(',', $_SERVER['HTTP_CLIENT_IP']); Request::$client_ip = array_shift($client_ips); unset($client_ips); } elseif (isset($_SERVER['REMOTE_ADDR'])) { // The remote IP address Request::$client_ip = $_SERVER['REMOTE_ADDR']; } if ($method !== HTTP_Request::GET) { // Ensure the raw body is saved for future use $body = file_get_contents('php://input'); } if ($uri === TRUE) { // Attempt to guess the proper URI $uri = Request::detect_uri(); } } // Create the instance singleton Request::$initial = $request = new Request($uri, $cache); // Store global GET and POST data in the initial request only $request->protocol($protocol)->query($_GET)->post($_POST); if (isset($secure)) { // Set the request security $request->secure($secure); } if (isset($method)) { // Set the request method $request->method($method); } if (isset($referrer)) { // Set the referrer $request->referrer($referrer); } if (isset($requested_with)) { // Apply the requested with variable $request->requested_with($requested_with); } if (isset($body)) { // Set the request body (probably a PUT type) $request->body($body); } } else { $request = new Request($uri, $cache, $injected_routes); } return $request; }
/** * Processes the request, executing the controller action that handles this * request, determined by the [Route]. * * 1. Before the controller action is called, the [Controller::before] method * will be called. * 2. Next the controller action will be called. * 3. After the controller action is called, the [Controller::after] method * will be called. * * By default, the output from the controller is captured and returned, and * no headers are sent. * * $request->execute(); * * @param Request $request A request object * @param Response $response A response object * @return Response * @throws Kohana_Exception * @uses [Kohana::$profiling] * @uses [Profiler] */ public function execute_request(Request $request, Response $response) { if (Kohana::$profiling) { // Set the benchmark name $benchmark = '"' . $request->uri() . '"'; if ($request !== Request::$initial and Request::$current) { // Add the parent request uri $benchmark .= ' « "' . Request::$current->uri() . '"'; } // Start benchmarking $benchmark = Profiler::start('Requests', $benchmark); } // Store the current active request and replace current with new request $previous = Request::$current; Request::$current = $request; // Resolve the POST fields if ($post = $request->post()) { $request->body(http_build_query($post, NULL, '&'))->headers('content-type', 'application/x-www-form-urlencoded; charset=' . Kohana::$charset); } $request->headers('content-length', (string) $request->content_length()); // If Kohana expose, set the user-agent if (Kohana::$expose) { $request->headers('user-agent', Kohana::version()); } try { $response = $this->_send_message($request, $response); } catch (Exception $e) { // Restore the previous request Request::$current = $previous; if (isset($benchmark)) { // Delete the benchmark, it is invalid Profiler::delete($benchmark); } // Re-throw the exception throw $e; } // Restore the previous request Request::$current = $previous; if (isset($benchmark)) { // Stop the benchmark Profiler::stop($benchmark); } // Return the response return $response; }
/** * Execute the request using PHP stream. (not recommended) * * @param Request $request Request to execute * @return Response */ protected function _native_execute(Request $request) { // Reset the headers Request_Client_External::$_processed_headers = array(); // Calculate stream mode $mode = $request->method() === HTTP_Request::GET ? 'r' : 'r+'; // Process cookies if ($cookies = $request->cookie()) { $request->headers('cookie', http_build_query($cookies, NULL, '; ')); } // Create the context $options = array($request->protocol() => array('method' => $request->method(), 'header' => (string) $request->headers(), 'content' => $request->body(), 'user-agent' => 'Kohana Framework ' . Kohana::VERSION . ' (' . Kohana::CODENAME . ')')); // Create the context stream $context = stream_context_create($options); stream_context_set_option($context, $this->_options); $stream = fopen($request->uri(), $mode, FALSE, $context); $meta_data = stream_get_meta_data($stream); // Get the HTTP response code $http_response = array_shift($meta_data['wrapper_data']); if (preg_match_all('/(\\w+\\/\\d\\.\\d) (\\d{3})/', $http_response, $matches) !== FALSE) { $protocol = $matches[1][0]; $status = (int) $matches[2][0]; } else { $protocol = NULL; $status = NULL; } // Process headers array_map(array('Request_Client_External', '_parse_headers'), array(), $meta_data['wrapper_data']); // Create a response $response = $request->create_response(); $response->status($status)->protocol($protocol)->headers(Request_Client_External::$_processed_headers)->body(stream_get_contents($stream)); // Close the stream after use fclose($stream); return $response; }
/** * Authentication check. * * @return bool */ public static function isAuthenticated() { if (is_null(self::$isAuthenticated)) { self::$isAuthenticated = false; // Do we have remote authentication data in the request ? if (!array_key_exists('signature', $_GET)) { return false; } if (!array_key_exists('timestamp', $_GET)) { return false; } $application = array_key_exists('remote_application', $_GET) ? $_GET['remote_application'] : null; $uid = array_key_exists('remote_user', $_GET) ? $_GET['remote_user'] : null; if (!$application && !$uid) { return false; } self::$attributes = array(); // Get data $received_signature = $_GET['signature']; $timestamp = (int) $_GET['timestamp']; if ($application) { // Check that application is known $applications = Config::get('auth_remote_applications'); if (!is_array($applications) || !array_key_exists($application, $applications)) { throw new AuthRemoteUknownApplicationException($application); } $application = new RemoteApplication($application, $applications[$application]); } // Check request time to avoid replays $late = time() - $timestamp - 15; if ($late > 0) { throw new AuthRemoteTooLateException($late); } // Get method from headers $method = null; foreach (array('X_HTTP_METHOD_OVERRIDE', 'REQUEST_METHOD') as $k) { if (!array_key_exists($k, $_SERVER)) { continue; } $method = strtolower($_SERVER[$k]); } // Build signed data $signed = $method . '&' . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME'] . (array_key_exists('PATH_INFO', $_SERVER) ? $_SERVER['PATH_INFO'] : ''); $args = $_GET; unset($args['signature']); if (count($args)) { $signed .= '?' . implode('&', RestUtilities::flatten($args)); } $input = Request::body(); if ($input) { $signed .= '&' . $input; } // Check signature if ($application) { $secret = $application->secret; } else { // Get user, fail if unknown or no user secret try { $user = User::fromId($uid); } catch (UserNotFoundException $e) { throw new AuthRemoteUserRejectedException($uid, 'user not found'); } if (!$user->auth_secret) { throw new AuthRemoteUserRejectedException($user->id, 'no secret set'); } $secret = $user->auth_secret; } $algorithm = Config::get('auth_remote_signature_algorithm'); if (!$algorithm) { $algorithm = 'sha1'; } $signature = hash_hmac($algorithm, $signed, $secret); if ($received_signature !== $signature) { throw new AuthRemoteSignatureCheckFailedException($signed, $secret, $received_signature, $signature); } // Register user id if given if ($uid) { self::$attributes['uid'] = $uid; } // Register admin level if asked for and enabled if ($application) { self::$isAdmin = $application->isAdmin; self::$application = $application; self::$attributes['remote_application'] = $application->name; } self::$isAuthenticated = true; } return self::$isAuthenticated; }
/** * @param string $uri * @param array $client_params * @param bool $allow_external * @param array $injected_routes * @internal param \HTTP_Cache $cache * @return \HAPI_Request|\Request|void */ public static function factory($uri = '', $client_params = array(), $allow_external = TRUE, $injected_routes = array()) { // If this is the initial request if (!Request::$initial) { if (isset($_SERVER['SERVER_PROTOCOL'])) { $protocol = $_SERVER['SERVER_PROTOCOL']; } else { $protocol = HTTP::$protocol; } if (isset($_SERVER['REQUEST_METHOD'])) { // Use the server request method $method = $_SERVER['REQUEST_METHOD']; } else { // Default to GET requests $method = HTTP_Request::GET; } if (!empty($_SERVER['HTTPS']) and filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN)) { // This request is secure $secure = TRUE; } if (isset($_SERVER['HTTP_REFERER'])) { // There is a referrer for this request $referrer = $_SERVER['HTTP_REFERER']; } if (isset($_SERVER['HTTP_USER_AGENT'])) { // Browser type Request::$user_agent = $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { // Typically used to denote AJAX requests $requested_with = $_SERVER['HTTP_X_REQUESTED_WITH']; } if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and isset($_SERVER['REMOTE_ADDR']) and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { // Use the forwarded IP address, typically set when the // client is using a proxy server. // Format: "X-Forwarded-For: client1, proxy1, proxy2" $client_ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); Request::$client_ip = array_shift($client_ips); unset($client_ips); } elseif (isset($_SERVER['HTTP_CLIENT_IP']) and isset($_SERVER['REMOTE_ADDR']) and in_array($_SERVER['REMOTE_ADDR'], Request::$trusted_proxies)) { // Use the forwarded IP address, typically set when the // client is using a proxy server. $client_ips = explode(',', $_SERVER['HTTP_CLIENT_IP']); Request::$client_ip = array_shift($client_ips); unset($client_ips); } elseif (isset($_SERVER['REMOTE_ADDR'])) { // The remote IP address Request::$client_ip = $_SERVER['REMOTE_ADDR']; } if ($method !== HTTP_Request::GET) { // Ensure the raw body is saved for future use $body = file_get_contents('php://input'); } $cookies = array(); if ($cookie_keys = array_keys($_COOKIE)) { foreach ($cookie_keys as $key) { $cookies[$key] = Cookie::get($key); } } // Create the instance singleton Request::$initial = $request = new Request($uri, $client_params, $allow_external, $injected_routes); // Store global GET and POST data in the initial request only $request->protocol($protocol)->query($_GET)->post($_POST); if (isset($secure)) { // Set the request security $request->secure($secure); } if (isset($method)) { // Set the request method $request->method($method); } if (isset($referrer)) { // Set the referrer $request->referrer($referrer); } if (isset($requested_with)) { // Apply the requested with variable $request->requested_with($requested_with); } if (isset($body)) { // Set the request body (probably a PUT type) $request->body($body); } if (isset($cookies)) { $request->cookie($cookies); } } else { $request = new HAPI_Request($uri, $client_params, $allow_external, $injected_routes); } return $request; }
public static function on_header_location(Request $request, Response $response, Request_Client $client) { if ($client->follow() and in_array($response->status(), array(201, 301, 302, 303, 307))) { switch ($response->status()) { default: case 301: case 307: $follow_method = $request->method(); break; case 201: case 303: $follow_method = Request::GET; break; case 302: if ($client->strict_redirect()) { $follow_method = $request->method(); } else { $follow_method = Request::GET; } break; } $orig_headers = $request->headers()->getArrayCopy(); $follow_header_keys = array_intersect(array_keys($orig_headers), $client->follow_headers()); $follow_headers = \Arr::extract($orig_headers, $follow_header_keys); $follow_request = Request::factory($response->headers("Location"))->method($follow_method)->headers($follow_headers); if ($follow_method !== Request::GET) { $follow_request->body($request->body()); } return $follow_request; } return NULL; }
public function refreshAccessToken($refresh_token) { return $this->base->body(['grant_type' => 'refresh_token', 'refresh_token' => $refresh_token]); }
public static function factory($uri = TRUE, Cache $cache = NULL) { // If this is the initial request if (!Request::$initial) { if (Kohana::$is_cli) { // Default protocol for command line is cli:// $protocol = 'cli'; // Get the command line options $options = CLI::options('uri', 'method', 'get', 'post', 'referrer'); if (isset($options['uri'])) { // Use the specified URI $uri = $options['uri']; } if (isset($options['method'])) { // Use the specified method $method = strtoupper($options['method']); } else { $method = 'GET'; } if (isset($options['get'])) { // Overload the global GET data parse_str($options['get'], $_GET); } if (isset($options['post'])) { // Overload the global POST data parse_str($options['post'], $_POST); } if (isset($options['referrer'])) { $referrer = $options['referrer']; } else { $referrer = NULL; } } else { if (isset($_SERVER['REQUEST_METHOD'])) { // Use the server request method $method = $_SERVER['REQUEST_METHOD']; } else { // Default to GET $method = Http_Request::GET; } if (!empty($_SERVER['HTTPS']) and filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN)) { // This request is secure $protocol = 'https'; } else { $protocol = 'http'; } if (isset($_SERVER['HTTP_REFERER'])) { // There is a referrer for this request $referrer = $_SERVER['HTTP_REFERER']; } else { $referrer = NULL; } if (isset($_SERVER['HTTP_USER_AGENT'])) { // Set the client user agent Request::$user_agent = $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { $requested_with = $_SERVER['HTTP_X_REQUESTED_WITH']; } if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { // Use the forwarded IP address, typically set when the // client is using a proxy server. Request::$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { // Use the forwarded IP address, typically set when the // client is using a proxy server. Request::$client_ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (isset($_SERVER['REMOTE_ADDR'])) { // The remote IP address Request::$client_ip = $_SERVER['REMOTE_ADDR']; } if ($method !== 'GET') { // Ensure the raw body is saved for future use $body = file_get_contents('php://input'); } if ($uri === TRUE) { $uri = Request::detect_uri(); } } // Create the instance singleton $request = new Request($uri, $cache); $request->protocol($protocol)->method($method)->referrer($referrer); // Apply the requested with variable isset($requested_with) and $request->requested_with($requested_with); // If there is a body, set it to the model isset($body) and $request->body($body); } else { $request = new Request($uri, $cache); } // Create the initial request if it does not exist if (!Request::$initial) { Request::$initial = $request; $request->query($_GET)->post($_POST); } return $request; }
/** * Process the request * * @throws lots of various exceptions */ public static function process() { try { @session_start(); // If undergoing maintenance report it as an error if (Config::get('maintenance')) { throw new RestUndergoingMaintenanceException(); } // Split request path to get tokens $path = array(); if (array_key_exists('PATH_INFO', $_SERVER)) { $path = array_filter(explode('/', $_SERVER['PATH_INFO'])); } // Get method from possible headers $method = null; foreach (array('X_HTTP_METHOD_OVERRIDE', 'REQUEST_METHOD') as $k) { if (!array_key_exists($k, $_SERVER)) { continue; } $method = strtolower($_SERVER[$k]); } // Record called method (for log), fail if unknown if (!in_array($method, array('get', 'post', 'put', 'delete'))) { throw new RestMethodNotAllowedException(); } // Get endpoint (first token), fail if none $endpoint = array_shift($path); if (!$endpoint) { throw RestEndpointNotFound(); } // Request data accessor self::$request = new RestRequest($method, $endpoint, $path); // Because php://input can only be read once for PUT requests we rely on a shared getter $input = Request::body(); // Get request content type from possible headers $type = array_key_exists('CONTENT_TYPE', $_SERVER) ? $_SERVER['CONTENT_TYPE'] : null; if (!$type && array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) { $type = $_SERVER['HTTP_CONTENT_TYPE']; } // Parse content type $type_parts = array_map('trim', explode(';', $type)); $type = array_shift($type_parts); self::$request->properties['type'] = $type; $type_properties = array(); foreach ($type_parts as $part) { $part = array_map('trim', explode('=', $part)); if (count($part) == 2) { self::$request->properties[$part[0]] = $part[1]; } } Logger::debug('Got "' . $method . '" request for endpoint "' . $endpoint . '/' . implode('/', $path) . '" with ' . strlen($input) . ' bytes payload'); // Parse body switch ($type) { case 'text/plain': self::$request->rawinput = trim(Utilities::sanitizeInput($input)); break; case 'application/octet-stream': // Don't sanitize binary input ! self::$request->rawinput = $input; break; case 'application/x-www-form-urlencoded': $data = array(); parse_str($input, $data); self::$request->input = (object) Utilities::sanitizeInput($data); break; case 'application/json': default: self::$request->input = json_decode(trim(Utilities::sanitizeInput($input))); } // Get authentication state (fills auth data in relevant classes) Auth::isAuthenticated(); if (Auth::isRemoteApplication()) { // Remote applications must honor ACLs $application = AuthRemote::application(); if (!$application->allowedTo($method, $endpoint)) { throw new RestNotAllowedException(); } } else { if (Auth::isRemoteUser()) { // Nothing peculiar to do } else { if (in_array($method, array('post', 'put', 'delete'))) { // SP or Guest, lets do XSRF check $token_name = 'HTTP_X_SECURITY_TOKEN'; $token = array_key_exists($token_name, $_SERVER) ? $_SERVER[$token_name] : ''; if ($method == 'post' && array_key_exists('security-token', $_POST)) { $token = $_POST['security-token']; } if (!$token || !Utilities::checkSecurityToken($token)) { throw new RestXSRFTokenInvalidException($token); } } } } // JSONP specifics if (array_key_exists('callback', $_GET) && $method != 'get') { throw new RestJSONPonlyGETException(); } // Get response filters foreach ($_GET as $k => $v) { switch ($k) { case 'count': case 'startIndex': if (preg_match('`^[0-9]+$`', $v)) { self::$request->{$k} = (int) $v; } break; case 'format': break; case 'filterOp': if (is_array($v)) { foreach ($v as $p => $f) { self::$request->filterOp[$p] = array(); foreach (array('equals', 'startWith', 'contains', 'present') as $k) { if (array_key_exists($k, $f)) { self::$request->filterOp[$p][$k] = $f[$k]; } } } } break; case 'sortOrder': if (in_array($v, array('ascending', 'descending'))) { self::$request->sortOrder = $v; } break; case 'updatedSince': // updatedSince takes ISO date, relative N days|weeks|months|years format and epoch timestamp (UTC) $updatedSince = null; if (preg_match('`^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:[0-9]{2})$`', $v)) { // ISO date $localetz = new DateTimeZone(Config::get('default_timezone')); $offset = $localetz->getOffset(new DateTime($v)); $updatedSince = strtotime($v) + $offset; } else { if (preg_match('`^([0-9]+)\\s*(hour|day|week|month|year)s?$`', $v, $m)) { // Relative N day|days|week|weeks|month|months|year|years format $updatedSince = strtotime('-' . $m[1] . ' ' . $m[2]); } else { if (preg_match('`^[0-9]+$`', $v)) { $updatedSince = (int) $v; } } } // Epoch timestamp if (!$updatedSince || !is_numeric($updatedSince)) { throw new RestUpdatedSinceBadFormatException($updatedSince); } self::$request->updatedSince = $updatedSince; break; } } $event = new Event('rest_request', self::$request); $data = $event->trigger(function () { $request = RestServer::getRequest(); // Forward to handler, fail if unknown or method not implemented $class = ucfirst($request->endpoint) . 'Endpoint'; if (!file_exists(APPLICATION_BASE . '/classes/endpoints/' . $class . '.class.php') && !file_exists(APPLICATION_BASE . '/classes/core/endpoints/' . $class . '.class.php')) { throw new RestEndpointNotFoundException(); } if (!method_exists($class, $request->method)) { throw new RestMethodNotImplementedException(); } Logger::debug('Forwarding call to ' . $class . '::' . $request->method . '() handler'); return call_user_func_array($class . '::' . $request->method, $request->path); }); Logger::debug('Got data to send back'); // Output data if (array_key_exists('callback', $_GET)) { header('Content-Type: text/javascript'); $callback = preg_replace('`[^a-z0-9_\\.-]`i', '', $_GET['callback']); echo $callback . '(' . json_encode($data) . ');'; exit; } if (array_key_exists('iframe_callback', $_GET)) { header('Content-Type: text/html'); $callback = preg_replace('`[^a-z0-9_\\.-]`i', '', $_GET['iframe_callback']); echo '<html><body><script type="text/javascript">window.parent.' . $callback . '(' . json_encode($data) . ');</script></body></html>'; exit; } header('Content-Type: application/json'); if ($method == 'post' && $data) { RestUtilities::sendResponseCode(201); if (substr($data['path'], 0, 1) != '/') { $data['path'] = '/' . $data['path']; } header('Location: ' . Config::get('application_url') . 'rest.php' . $data['path']); $data = $data['data']; } echo json_encode($data); } catch (Exception $e) { // Return exceptions as HTTP errors $code = $e->getCode(); if ($code < 400 || $code >= 600) { $code = 500; } RestUtilities::sendResponseCode($code); header('Content-Type: application/json'); echo json_encode(array('message' => $e->getMessage(), 'uid' => method_exists($e, 'getUid') ? $e->getUid() : null, 'details' => method_exists($e, 'getDetails') ? $e->getDetails() : null)); } }