/** * 每个请求层,最终被调用的方法 * * @return mixed */ public function handle() { Base::getLog()->debug(__METHOD__ . ' handle request flow - start'); $request = new Request($this->flow->contexts['uri']); // 上下文 $this->flow->contexts['request'] = $request; // 处理HTTP相关,例如过滤变量,初始化相关设置 $flow = Flow::instance('tourze-http'); $flow->contexts =& $this->flow->contexts; $flow->layers = ['tourze\\Bootstrap\\Flow\\Http\\Initialization', 'tourze\\Bootstrap\\Flow\\Http\\Authentication', 'tourze\\Bootstrap\\Flow\\Http\\Authorization']; $flow->start(); // 执行请求 $response = $request->execute(); echo $response->sendHeaders(true)->body; Base::getLog()->debug(__METHOD__ . ' handle request flow - end'); }
/** * 检测execute功能是否正常 */ public function testExecute() { $request = Request::factory('http://www.baidu.com'); //$request->method = Http::POST; $request->query(['v1' => 'v2']); //$request->post(['v3' => 'v4']); $response = $request->execute(); $this->assertTrue(strpos($response->body, '百度') !== false); }
/** * 每个请求层,最终被调用的方法 * * @return mixed */ public function handle() { /** @var Request $request */ $request =& $this->flow->contexts['request']; // 如果当前请求是初始请求,那么对其进行额外处理 // 如果当前请求是CLI,那么直接当做为初始化请求 if (PHP_SAPI == 'cli' || $request->isInitial()) { if (!empty($_SERVER['HTTPS']) && filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] && in_array($_SERVER['REMOTE_ADDR'], Request::$trustedProxies)) { $request->secure = true; } if (isset($_SERVER['REQUEST_METHOD'])) { $method = $_SERVER['REQUEST_METHOD']; } else { $method = Http::GET; } if (isset($_SERVER['HTTP_REFERER'])) { $referrer = $_SERVER['HTTP_REFERER']; } if (isset($_SERVER['HTTP_USER_AGENT'])) { Request::$userAgent = $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { $requestedWith = $_SERVER['HTTP_X_REQUESTED_WITH']; } Request::$clientIp = Request::getClientIP(); if ($method !== Http::GET) { $body = file_get_contents('php://input'); } $cookies = []; if ($cookieKeys = array_keys($_COOKIE)) { foreach ($cookieKeys as $key) { $cookies[$key] = Cookie::get($key); } } if (isset($_SERVER['SERVER_PROTOCOL'])) { $request->protocol = $_SERVER['SERVER_PROTOCOL']; } $request->query($_GET)->post($_POST); if (isset($method)) { $request->method = $method; } if (isset($referrer)) { $request->referrer = $referrer; } if (isset($requestedWith)) { $request->requestedWith = $requestedWith; } if (isset($body)) { $request->body = $body; } if (isset($cookies)) { $request->cookie($cookies); } } }
/** * 执行外部请求,并返回接口 * * $request->execute(); * * @param Request $request * @param Response $response * @return Response * @throws Exception */ public function executeRequest(Request $request, Response $response) { $previous = Request::$current; Request::$current = $request; // 如果post数据了 if ($post = $request->post()) { $request->body = http_build_query($post, null, '&'); $request->headers('content-type', 'application/x-www-form-urlencoded; charset=' . $request->charset); } // 如果需要暴露框架信息 if (Base::$expose) { $request->headers('user-agent', Base::version()); } try { // 处理header $sendHeaders = []; if ($headers = $request->headers()) { foreach ($headers as $key => $value) { if (is_array($value)) { $value = implode(', ', $value); } $sendHeaders[$key] = $value; } } // 处理cookie if ($cookies = $request->cookie()) { $sendHeaders['Cookie'] = http_build_query($cookies, null, '; '); } $url = $request->uri; if ($query = $request->query()) { $url .= '?' . http_build_query($query, null, '&'); } // 执行请求 $result = Requests::request($url, $sendHeaders, $request->body, $request->method, $this->options); if (!$result->success) { throw new RequestException('Error fetching remote :url [ status :code ]', [':url' => $url, ':code' => $result->status_code]); } foreach ($result->headers as $k => $v) { $response->headers($k, $v); } $response->status = $result->status_code; $response->body = $result->body; } catch (Exception $e) { Request::$current = $previous; throw $e; } Request::$current = $previous; return $response; }
/** * 处理请求 * * $request->execute(); * * @param Request $request * @param Response $response * @return \tourze\Http\Response * @throws \tourze\Base\Exception\BaseException */ public function executeRequest(Request $request, Response $response) { $className = 'Controller'; // 控制器 $controller = $request->controller; $className = Inflector::classify($controller) . $className; // 目录 $directory = $request->directory; if ($directory) { $directory = str_replace('/', '\\', $directory); $className = $directory . $className; } // 保存请求状态 $previous = Request::$current; Request::$current = $request; Base::getLog()->info(__METHOD__ . ' controller class', ['class' => $className]); try { if (!class_exists($className)) { Base::getLog()->debug(__METHOD__ . ' class not found', ['class' => $className]); throw HttpException::factory(Http::NOT_FOUND, 'The requested URL :uri was not found on this server.', [':uri' => $request->uri])->request($request); } $class = new ReflectionClass($className); if ($class->isAbstract()) { Base::getLog()->error(__METHOD__ . ' calling abstract controller class', ['class' => $className]); throw new BaseException('Cannot create instances of abstract :controller', [':controller' => $className]); } $controller = $class->newInstance(['request' => $request, 'response' => $response]); $response = $class->getMethod('execute')->invoke($controller); if (!$response instanceof Response) { Base::getLog()->error(__METHOD__ . ' unknown response type'); throw new BaseException('Controller failed to return a Response'); } } catch (HttpException $e) { if (null === $e->request()) { $e->request($request); } $response = $e->getResponse(); } Request::$current = $previous; return $response; }
/** * 跳转状态码的处理 * * @param Request $request * @param Response $response * @param RequestClient $client * @return null|Request */ public static function onHeaderLocation(Request $request, Response $response, RequestClient $client) { if ($client->follow && in_array($response->status, [Http::CREATED, Http::MOVED_PERMANENTLY, Http::FOUND, Http::SEE_OTHER, Http::TEMPORARY_REDIRECT])) { switch ($response->status) { default: case Http::MOVED_PERMANENTLY: case Http::TEMPORARY_REDIRECT: $followMethod = $request->method; break; case Http::CREATED: case Http::SEE_OTHER: $followMethod = Http::GET; break; case Http::FOUND: if ($client->strictRedirect) { $followMethod = $request->method; } else { $followMethod = Http::GET; } break; } $origHeaders = $request->headers(); $followHeaders = array_intersect_assoc($origHeaders, array_fill_keys($client->followHeaders, true)); $followRequest = Request::factory($response->headers('Location')); $followRequest->method = $followMethod; $followRequest->headers($followHeaders); if ($followMethod !== Http::GET) { $followRequest->body = $request->body; } return $followRequest; } return null; }
/** * 执行请求 * * @return Response * @throws HttpException * @throws ClientRecursionException * @throws RequestException */ public function execute() { if (!$this->external) { Base::getLog()->debug(__METHOD__ . ' execute internal request'); $processed = Request::process($this, $this->routes); if ($processed) { // 保存匹配到的路由 $this->route = Arr::get($processed, 'route'); $params = Arr::get($processed, 'params'); // 是否为外部链接 $this->external = $this->route->isExternal(); // 控制器放在子目录中的情况 if (isset($params['directory'])) { $this->directory = $params['directory']; } // 附加上命名空间 if (isset($params['namespace'])) { $this->directory = $params['namespace']; } // 命名空间处理 if (!$this->directory) { $this->directory = Route::$defaultNamespace; } // 修正命名空间 if (false === strpos($this->directory, '\\')) { $this->directory = Route::$defaultNamespace . $this->directory . '\\'; } // 保存控制器 $this->controller = Arr::get($params, 'controller'); // 保存动作 $this->action = Arr::get($params, 'action', Route::$defaultAction); // 清理保留字段 foreach ($this->persistRouteParams as $name) { unset($params[$name]); } $this->_params = $params; Base::getLog()->debug(__METHOD__ . ' execute info', ['directory' => $this->directory, 'controller' => $this->controller, 'action' => $this->action, 'params' => $this->_params]); } else { Base::getLog()->debug(__METHOD__ . ' not route matched'); } } if (!$this->route instanceof Entry) { $e = HttpException::factory(Http::NOT_FOUND, 'Unable to find a route to match the URI: :uri', [':uri' => $this->uri]); $e->request($this); throw $e; } if (!$this->client instanceof RequestClient) { throw new RequestException('Unable to execute :uri without a RequestClient', [':uri' => $this->uri]); } return $this->client->execute($this); }