构造http请求对象，供测试使用.

@example
$request = Request::factory([
'uri' => '/',
'method' => 'post',
'cookies' => [
$key => $value,
...
],
'headers' => [
$key => $value,
...
],
'get' => [
$key => $value,
...
],
'post' => [
$key => $value,
...
],
]);
775011
public static function factory(array $options = [])
    {
        $options = array_merge([
            'uri' => '/',
            'method' => 'GET',
            'cookies' => [],
            'headers' => [],
            'get' => [],
            'post' => [],
            'ip' => '',
            '_SERVER' => [],
        ], $options);

        $server = array_change_key_case($options['_SERVER'], CASE_UPPER);
        $server['REQUEST_METHOD'] = strtoupper($options['method']);
        $server['REQUEST_URI'] = $options['uri'];

        if ($options['ip']) {
            $server['REMOTE_ADDR'] = $options['ip'];
        }

        if ($query = parse_url($options['uri'], PHP_URL_QUERY)) {
            parse_str($query, $get);
            $options['get'] = array_merge($get, $options['get']);
        }

        $cookies = $options['cookies'];
        $get = $options['get'];
        $post = $options['post'];

        if ('GET' === $server['REQUEST_METHOD']) {
            $post = [];
        }

        foreach ($options['headers'] as $key => $value) {
            $key = 'HTTP_' . strtoupper(str_replace('-', '_', $key));
            $server[$key] = $value;
        }

        return new self($get, $post, $server, $cookies);
    }
366191
public function verifyRedirect($request)
    {
        if(empty($request)) {//判断请求的参数是否为空
            return false;
        }

        //生成签名结果
        $data['prestr'] = Helper::buildRequestPreStr($request);
        $data['sign'] = $request['sign'];
        $isSign = $this->sign->verifySign($data, trim($this->config[$this->signKeyConfigName]));

        return $isSign;
    }
1136621
public function getUri()
    {
        if (PHP_SAPI == 'cli') {
            return '/'. trim(Arr::get($_SERVER['argv'], 1, '/'), '/');
        }

        $requestUri = parse_url('http://example.com' . Arr::get($_SERVER, 'REQUEST_URI', ''), PHP_URL_PATH);

        $requestUri = empty($requestUri) ? '/' : $this->filterPath($requestUri);

        return '/' . trim($requestUri, '/');

        // nginx 这种配置不可能走下边逻辑 try_files $uri $uri/ /index.php?$query_string;

        // Path
        // $requestScriptName = parse_url(Arr::get($_SERVER, 'SCRIPT_NAME', ''), PHP_URL_PATH);
        // $requestScriptDir = dirname($requestScriptName);

        // parse_url() requires a full URL. As we don't extract the domain name or scheme,
        // we use a stand-in.
        // $requestUri = parse_url('http://example.com' . Arr::get($_SERVER, 'REQUEST_URI', ''), PHP_URL_PATH);
        //
        // $basePath = '';
        // $virtualPath = $requestUri;
        // if (stripos($requestUri, $requestScriptName) === 0) {
        //     $basePath = $requestScriptName;
        // } elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) {
        //     $basePath = $requestScriptDir;
        // }
        //
        // if ($basePath) {
        //     $virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/');
        // }
        //
        // $requestUri = empty($virtualPath) ? '/' : $this->filterPath($virtualPath);
        //
        // return '/' . ltrim($requestUri, '/');
    }
740330
public function setCert(Http $http) {
        //两个文件合成一个.pem文件
        if (!empty($this->privateKeyFile)) {
            return $http->setOption(CURLOPT_SSLCERT, (string)$this->privateKeyFile);
        }
        //cert 与 key 分别属于两个.pem文件
        return $http->setOption([
            CURLOPT_SSLCERTTYPE => 'PEM',
            CURLOPT_SSLCERT => (string)$this->get('certFile'),
            CURLOPT_SSLCERTPASSWD => $this->get('mch_id'),
            CURLOPT_SSLKEYTYPE => 'PEM',
            CURLOPT_SSLKEY => (string)$this->get('keyFile'),
            CURLOPT_SSLKEYPASSWD => $this->get('mch_id'),
        ]);
    }
1261439
public function send($request)
    {
        $this->request = $request;
        if([] !== ($queryParams = $this->request->getQueryParams()))
        {
            $this->request = $this->request->withUri($this->request->getUri()->withQuery(http_build_query($queryParams, '', '&')));
        }
        $uri = $this->request->getUri();
        $isLocation = false;
        $count = 0;
        do{
            $retry = $this->request->getAttribute('retry', 0);
            for($i = 0; $i <= $retry; ++$i)
            {
                $this->settings = $this->request->getAttribute('options', []);
                // 解析IP
                $ip = Coroutine::gethostbyname($uri->getHost());
                // 实例化
                $this->handler = new Client($ip, $uri->getPort(), 'https' === $uri->getScheme());
                $this->handler->setDefer();
                // method
                if($isLocation)
                {
                    $this->handler->setMethod('GET');
                }
                else
                {
                    $this->handler->setMethod($this->request->getMethod());
                }
                // cookie
                $this->handler->setCookies($this->request->getCookieParams());
                // body
                if(!$isLocation)
                {
                    $files = $this->request->getUploadedFiles();
                    $body = (string)$this->request->getBody();
                    if(isset($files[0]))
                    {
                        foreach($files as $file)
                        {
                            $this->handler->addFile($file->getTempFileName(), basename($file->getClientFilename()), $file->getClientMediaType());
                        }
                        parse_str($body, $body);
                    }
                    $this->handler->setData($body);
                }
                // headers
                $this->request = $this->request->withAddedHeader('Host', $uri->getHost());
                if(!$this->request->hasHeader('Content-Type'))
                {
                    $this->request = $this->request->withAddedHeader('Content-Type', MediaType::APPLICATION_FORM_URLENCODED);
                }
                $headers = [];
                foreach($this->request->getHeaders() as $name => $value)
                {
                    $headers[$name] = implode(',', $value);
                }
                $this->handler->setHeaders($headers);
                // 其它处理
                $this->parseSSL();
                $this->parseProxy();
                $this->parseNetwork();
                // 设置客户端参数
                if(!empty($this->settings))
                {
                    $this->settings['timeout'] = 30;
                    $this->handler->set($this->settings);
                }
                // 发送
                $path = $uri->getPath();
                if('' === $path)
                {
                    $path = '/';
                }
                $query = $uri->getQuery();
                if('' !== $query)
                {
                    $path .= '?' . $query;
                }
                if(null === ($saveFilePath = $this->request->getAttribute('saveFilePath')))
                {
                    $this->handler->execute($path);
                }
                else
                {
                    $this->handler->download($path, $saveFilePath);
                }
                $this->getResponse();
                $statusCode = $this->result->getStatusCode();
                // 状态码为5XX或者0才需要重试
                if(!(0 === $statusCode || (5 === (int)($statusCode/100))))
                {
                    break;
                }
            }
            if((301 === $statusCode || 302 === $statusCode) && ++$count <= $this->request->getAttribute('maxRedirects', 10))
            {
                // 自己实现重定向
                $uri = new Uri($this->result->getHeaderLine('location'));
                $isLocation = true;
            }
            else
            {
                break;
            }
        }while(true);
    }
706959
public function handle(Request $request)
    {
        try {
            // 注册 Request
            $this->app::register('request', $request);

            // 启用 App
            $this->app->bootstrap();

            // 加载 Router
            $router = new Router();
            require $this->app->basePath.'/bootstrap/routes.php';

            // 注册 Router
            $this->app::register('router', $router);

            // 任务分发
            $response = $router->dispatch($request);
        }
        catch (Exception $e) {
            $this->app::make('log')->error('runtime exception: '. $e->getMessage(), [
                'code' => $e->getCode(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);

            if ($this->app->configGet('app.debug')) {
                throw new Exception('Http Request handle error', $e->getCode(), $e);
            }

            $response = new Response('', is_subclass_of($e, 'awheel\Exceptions\HttpException') ? $e->getStatusCode() : $e->getCode());
        }

        return $response;
    }
457615
public function handle($request)
    {
         $this->bootstrap();
         $this->setRouter(); //注册路由

         return $this->router->dispatch($request);
    }
204472
public function doRequest($request)
    {
        $inputStream = fopen('php://memory', 'r+');
        $content = $request->getContent();
        if ($content !== null) {
            fwrite($inputStream, $content);
            rewind($inputStream);
        }

        $queryParams = [];
        $postParams = [];
        $queryString = parse_url($request->getUri(), PHP_URL_QUERY);
        if ($queryString != '') {
            parse_str($queryString, $queryParams);
        }
        if ($request->getMethod() !== 'GET') {
            $postParams = $request->getParameters();
        }

        $serverParams = $request->getServer();
        if (!isset($serverParams['SCRIPT_NAME'])) {
            //required by WhoopsErrorHandler
            $serverParams['SCRIPT_NAME'] = 'Codeception';
        }
        
        $cookies = $request->getCookies();
        $headers = $this->extractHeaders($request);

        //set cookie header because dflydev/fig-cookies reads cookies from header
        if (!empty($cookies)) {
            $headers['cookie'] = implode(';', array_map(function ($key, $value) {
                return "$key=$value";
            }, array_keys($cookies), $cookies));
        }

        $zendRequest = new ServerRequest(
            $serverParams,
            $this->convertFiles($request->getFiles()),
            $request->getUri(),
            $request->getMethod(),
            $inputStream,
            $headers,
            $cookies,
            $queryParams,
            $postParams
        );

        $this->request = $zendRequest;

        $cwd = getcwd();
        chdir(codecept_root_dir());

        if ($this->config['recreateApplicationBetweenRequests'] === true || $this->application === null) {
            $application = $this->initApplication();
        } else {
            $application = $this->application;
        }

        if (method_exists($application, 'handle')) {
            //Zend Expressive v3
            $response = $application->handle($zendRequest);
        } else {
            //Older versions
            $application->run($zendRequest);
            $response = $this->responseCollector->getResponse();
            $this->responseCollector->clearResponse();
        }

        chdir($cwd);

        return new Response(
            (string)$response->getBody(),
            $response->getStatusCode(),
            $response->getHeaders()
        );
    }
1136217
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // 获取Response对象
        $response = $handler->handle($request);
        // 获取路由结果
        $result = RequestContext::get('routeResult');
        if(null === $result)
        {
            throw new \RuntimeException('RequestContent not found routeResult');
        }
        // 路由匹配结果是否是[控制器对象, 方法名]
        $isObject = is_array($result['callable']) && isset($result['callable'][0]) && $result['callable'][0] instanceof HttpController;
        if($isObject)
        {
            // 复制一份控制器对象
            $result['callable'][0] = clone $result['callable'][0];
            // 传入Request和Response对象
            $result['callable'][0]->request = $request;
            $result['callable'][0]->response = $response;
        }
        // 执行动作
        $actionResult = call_user_func_array($result['callable'], $this->prepareActionParams($request, $result));
        if($isObject)
        {
            // 获得控制器中的Response
            $response = $result['callable'][0]->response;
        }
        // 视图
        if($actionResult instanceof \Imi\Server\View\Annotation\View)
        {
            // 动作返回的值是@View注解
            $viewAnnotation = $actionResult;
        }
        else if($actionResult instanceof Response)
        {
            $response = $actionResult;
        }
        else
        {
            // 获取对应动作的视图注解
            $viewAnnotation = clone ViewParser::getInstance()->getByCallable($result['callable']);
            if(null !== $viewAnnotation)
            {
                if(is_array($actionResult))
                {
                    // 动作返回值是数组，合并到视图注解
                    $viewAnnotation->data = array_merge($viewAnnotation->data, $actionResult);
                }
                else
                {
                    // 非数组直接赋值
                    $viewAnnotation->data = $actionResult;
                }
            }
        }

        if(isset($viewAnnotation))
        {
            // 视图渲染
            $view = RequestContext::getServerBean('View');
            $response = $view->render($viewAnnotation, $response);
        }

        return $response;
    }
118296
private function initContext()
    {
        //request instance;
        $req=new Request();

        //request headers
        $req->headers=[];
        foreach ($_SERVER as $name => $value){
            if(strpos($name, "HTTP_")===0){
                $key=str_replace(" ", "-", ucwords(str_replace("_", " ", substr(strtolower($name), 5))));
                $req->headers[$key]=$value;
            }
        }
        if (isset($_SERVER["PHP_AUTH_DIGEST"])) {
            $req->headers["Authorization"] = $_SERVER["PHP_AUTH_DIGEST"];
        } elseif (isset($_SERVER["PHP_AUTH_USER"]) && isset($_SERVER["PHP_AUTH_PW"])) {
            $req->headers["Authorization"] = base64_encode($_SERVER["PHP_AUTH_USER"] . ":" . $_SERVER["PHP_AUTH_PW"]);
        }
        if (isset($_SERVER["CONTENT_LENGTH"])) {
            $req->headers["Content-Length"] = $_SERVER["CONTENT_LENGTH"];
        }
        if (isset($_SERVER["CONTENT_TYPE"])) {
            $req->headers["Content-Type"] = $_SERVER["CONTENT_TYPE"];
        }
        $req->charset=array_key_exists("HTTP_ACCEPT_CHARSET", $req->headers)?$req->headers["HTTP_ACCEPT_CHARSET"]:"utf-8";
        $req->contentType=array_key_exists("CONTENT_TYPE", $req->headers)?$req->headers["CONTENT_TYPE"]:"text/html";
        $req->contentLength=array_key_exists("CONTENT_LENGTH", $req->headers)?$req->headers["CONTENT_LENGTH"]:0;

        $req->method=$_SERVER["REQUEST_METHOD"];
        $req->protocol=$_SERVER["SERVER_PROTOCOL"];
        $req->scheme=$_SERVER["REQUEST_SCHEME"];
        $req->host=$_SERVER["HTTP_HOST"];
        $req->port=$_SERVER["SERVER_PORT"];
        $req->uri=$_SERVER["REQUEST_URI"];
        $req->get=$_GET;
        $req->post=$_POST;

        //response
        $rsp=new Response();
        $rsp->setCharset($req->charset);

        //context
        $this->m_context=new Context($req,$rsp);
    }
1097698
public static function fromRawSource(): Request
    {
        if (isset($_SERVER['REQUEST_METHOD'])
                && strtoupper(trim($_SERVER['REQUEST_METHOD'])) === Http::POST) {
            $params = $_POST;
        } else {
            $params = $_GET;
        }

        return new self($params, $_SERVER, $_COOKIE);
    }
606920
private function parseBy($rules, Request $request) {
		foreach ($rules as $rewrite) {
			if (isset($rewrite['uri'])) {
				if ($request->uri === $rewrite['uri']) {
					$dispatch = $rewrite['dispatch'];
					break;
				}
			} else {
				if (preg_match($rewrite['regex'], $request->uri, $matches)) {
					$param = [];
					unset($matches[0]);
					//参数
					foreach ($rewrite['param'] as $k => $v) {
						$param[$v] = $matches[$k + 1];
					}
					$dispatch = $rewrite['dispatch'];
					if ($dispatch instanceof \Closure) {
						$dispatch = $dispatch($param);
						if ($dispatch === null) {
							unset($dispatch);
							continue;
						}
					}
					break;
				}
			}
		}
		if (isset($dispatch)) {
			$request->module = isset($dispatch['module']) ? $dispatch['module'] : $this->module;
			$request->controller = $dispatch['controller'];
			$request->action = $dispatch['action'];
			if (isset($param)) {
				$request->param = $param;
			}
			return true;
		}
		return false;
	}
1168016
public function execute(IRequest $request)
    {
        $method        = $request->getMethod();
        $publicParams  = $this->getPublicParams();
        $serviceParams = $request->getParams();

        $params = array_merge(
            $publicParams,
            [
                'method' => $method
            ],
            $serviceParams
        );

        // 签名
        $params['sign'] = $this->generateSign($params);

        // 请求数据
        $resp = $this->curl($this->api_uri, $params);

        // 解析返回
        return $this->parseRep($resp);
    }
1313496
public static function createFromGlobals() {
        $request = new Request($_GET, $_POST, $_REQUEST, $_COOKIE, $_FILES, $_SERVER);

        //设置session实例
        $request->setSession(new SimpleSession());

        return $request;
    }
627063
protected function prepareError($http, $credential = [])
    {
        if (!$http->isSuccess()) {
            $this->code = -1;
            $this->message = '很抱歉,网络繁忙,请稍后再试';
        } else {
            // TODO 简化各类错误的处理
            if (isset($http['errcode']) && $http['errcode'] !== 0) {
                $code = $http['errcode'];
                $message = $http['errmsg'];
            } elseif (isset($http['base_resp'])) {
                $code = $http['base_resp']['errcode'];
                $message = $http['base_resp']['errmsg'];
            } elseif (isset($http['error_code'])) {
                $code = $http['error_code'];
                $message = $http['error_msg'];
            } else {
                $code = 1000;
                $message = '未知返回' . $http->getResponseText();
            }

            $this->code = -abs($code);
            $this->message = isset($this->messages[$code]) ? $this->messages[$code] : $message;
            $this->logError($http, $credential);
        }

        return false;
    }
217243
public function match(Request $request): array
    {
        $uri = $request->getUri()->getPath();

        // HTTP & WebSocket 请求
        if ($request->getProtocol() === Protocol::HTTP || $request->getProtocol() === Protocol::WEBSOCKET) {
            return $this->getDispatcher()->dispatch(
                $request->getMethod(),
                $uri
            );
        } else { // TCP & UDP 请求
            foreach (['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTION'] as $method) {
                $route = $this->getDispatcher()->dispatch($method, $uri);

                if ($route[0] === self::FOUND) {
                    return $route;
                }

                unset($route);
            }

            return [ self::NOT_FOUND ];
        }
    }
953157
public static function dispatch()
    {
        $currentRoute = isset($_GET[self::$name]) ? $_GET[self::$name] : '/';
        $found_route = false;
        $method = strtolower($_SERVER['REQUEST_METHOD']);
        foreach (self::$routes as $v) {
            if (!empty($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $currentRoute && ($v2['method'] == $method || $v2['method']=='any')) {
                        $found_route = true;
                        $_GET['r'] = $currentRoute;
                        // Call closure
                        $refFunc = new \ReflectionFunction($v2['callBack']);
                        $params = [];
                        foreach ($refFunc->getParameters() as $v3) {
                            if (isset($_REQUEST[$v3->name])) {
                                $params[$v3->name] = $_REQUEST[$v3->name];
                            }else{
                                //参数是否有默认值
                                if($v3->isDefaultValueAvailable()){
                                    $params[$v3->name] = $v3->getDefaultValue();
                                }else{
                                    //参数是否是个对象
                                    $classRef = $v3->getClass();
                                    if($classRef){
                                        $classProperties = $classRef->getProperties();
                                        /**
                                         * @var $class Model
                                         */
                                        $class = $classRef->newInstance();
                                        if($classProperties){
                                           foreach($classProperties as $v4){
                                               $propertyName  = $v4->name;
                                               if(isset($_REQUEST[$propertyName])){
                                                   $class->$propertyName = $_REQUEST[$propertyName];
                                               }
                                           }
                                        }
                                        //验证参数
                                        if($classRef->hasMethod('validate')){
                                            if(!$class->validate()){
                                                throw new \Exception(json_encode($class->getErrors(),JSON_UNESCAPED_UNICODE));
                                            }
                                        }
                                        $params = [$class];
                                    }else{
                                        throw new \Exception('参数不存在：'.$v3->name,400);
                                    }
                                }
                            }
                        }
                        //将post or get 参数传入
                        if (!empty($params)) {
                            return call_user_func_array($v2['callBack'], $params);
                        } else {
                            return call_user_func($v2['callBack']);
                        }
                       break;
                    }
                }
            }
        }

        if ($found_route == false) {
            header($_SERVER['SERVER_PROTOCOL'] . " 404 Not Found");
            if (self::$error_callback) {
                return call_user_func(self::$error_callback, ['message' => '404 Not Found']);;
            }
        }
        return false;

    }