代码研磨 Slim v3 (二)--app->run()
/**
* Run application
*
* This method traverses the application middleware stack and then sends the
* resultant Response object to the HTTP client.
*
* @param bool|false $silent
* @return ResponseInterface
*
* @throws Exception
* @throws MethodNotAllowedException
* @throws NotFoundException
*/
public function run($silent = false)
{
$request = $this->container->get('request');
$response = $this->container->get('response'); $response = $this->process($request, $response); if (!$silent) {
$this->respond($response);
}
return $response;
}
$request = $this->container->get('request');
if (!isset($this['request'])) {
/**
* PSR-7 Request object
*
* @param Container $c
*
* @return ServerRequestInterface
*/
$this['request'] = function ($c) {
return Request::createFromEnvironment($c->get('environment'));
};
} if (!isset($this['environment'])) {
/**
* This service MUST return a shared instance
* of \Slim\Interfaces\Http\EnvironmentInterface.
*
* @return EnvironmentInterface
*/
$this['environment'] = function () {
return new Environment($_SERVER);
};
}
首先看到Request是需要一个environment的,$c->get('environment')生成的是一个Environment对象。其次Environment 是通过$__SERVER构造的对象。
class Environment extends Collection implements EnvironmentInterface
这里可以看出Enviroment是继承了Collection,所有它的数组形式访问可以实现obj[’name’]。同时Environment中实现了EnvironmentInterface接口的mock方法。
/**
* Create new HTTP request with data extracted from the application
* Environment object
*
* @param Environment $environment The Slim application Environment
*
* @return self
*/
public static function createFromEnvironment(Environment $environment)
{
$method = $environment['REQUEST_METHOD'];
$uri = Uri::createFromEnvironment($environment);
var_dump($uri);
$headers = Headers::createFromEnvironment($environment);
$cookies = Cookies::parseHeader($headers->get('Cookie', []));
$serverParams = $environment->all();
$body = new RequestBody();
$uploadedFiles = UploadedFile::createFromEnvironment($environment); $request = new static($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles); if ($method === 'POST' &&
in_array($request->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data'])
) {
// parsed body must be $_POST
$request = $request->withParsedBody($_POST);
}
return $request;
}
'REDIRECT_STATUS' =>string'200'(length=3)
'UNIQUE_ID' =>string'Vqrb26wRQjYAAAOax40AAAAB'(length=24)
'HTTP_HOST' =>string'localhost'(length=9)
'HTTP_CONNECTION' =>string'keep-alive'(length=10)
'HTTP_CACHE_CONTROL' =>string'max-age=0'(length=9)
'HTTP_ACCEPT' =>string'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'(length=74)
'HTTP_UPGRADE_INSECURE_REQUESTS' =>string'1'(length=1)
'HTTP_USER_AGENT' =>string'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36'(length=121)
'HTTP_ACCEPT_ENCODING' =>string'gzip, deflate, sdch'(length=19)
'HTTP_ACCEPT_LANGUAGE' =>string'zh-CN,zh;q=0.8'(length=14)
'HTTP_COOKIE' =>string'CNZZDATA5718743=cnzz_eid%3D686564234-1452136358-%26ntime%3D1452136358'(length=69)
'PATH' =>string'/usr/bin:/bin:/usr/sbin:/sbin'(length=29)
'DYLD_LIBRARY_PATH' =>string'/Applications/XAMPP/xamppfiles/lib:/Applications/XAMPP/xamppfiles/lib'(length=69)
'SERVER_SIGNATURE' =>string''(length=0)
'SERVER_SOFTWARE' =>string'Apache/2.4.16 (Unix) OpenSSL/1.0.1p PHP/5.6.12 mod_perl/2.0.8-dev Perl/v5.16.3'(length=78)
'SERVER_NAME' =>string'localhost'(length=9)
'SERVER_ADDR' =>string'::1'(length=3)
'SERVER_PORT' =>string'80'(length=2)
'REMOTE_ADDR' =>string'::1'(length=3)
'DOCUMENT_ROOT' =>string'/Applications/XAMPP/xamppfiles/htdocs'(length=37)
'REQUEST_SCHEME' =>string'http'(length=4)
'CONTEXT_PREFIX' =>string''(length=0)
'CONTEXT_DOCUMENT_ROOT' =>string'/Applications/XAMPP/xamppfiles/htdocs'(length=37)
'SERVER_ADMIN' =>string'you@example.com'(length=15)
'SCRIPT_FILENAME' =>string'/Applications/XAMPP/xamppfiles/htdocs/example/index.php'(length=55)
'REMOTE_PORT' =>string'49719'(length=5)
'REDIRECT_URL' =>string'/example/forbase'(length=16)
'GATEWAY_INTERFACE' =>string'CGI/1.1'(length=7)
'SERVER_PROTOCOL' =>string'HTTP/1.1'(length=8)
'REQUEST_METHOD' =>string'GET'(length=3)
'QUERY_STRING' =>string''(length=0)
'REQUEST_URI' =>string'/example/forbase'(length=16)
'SCRIPT_NAME' =>string'/example/index.php'(length=18)
'PHP_SELF' =>string'/example/index.php'(length=18)
'REQUEST_TIME_FLOAT' =>float1454037979.728
/**
* Create new Uri from environment.
*
* @param Environment $env
*
* @return self
*/
public static function createFromEnvironment(Environment $env)
{
// Scheme
$isSecure = $env->get('HTTPS');
$scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https'; // Authority: Username and password
$username = $env->get('PHP_AUTH_USER', '');
$password = $env->get('PHP_AUTH_PW', ''); // Authority: Host
if ($env->has('HTTP_HOST')) {
$host = $env->get('HTTP_HOST');
} else {
$host = $env->get('SERVER_NAME');
} // Authority: Port
$port = (int)$env->get('SERVER_PORT', 80);
if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) {
$host = $matches[1]; if ($matches[2]) {
$port = (int) substr($matches[2], 1);
}
} else {
$pos = strpos($host, ':');
if ($pos !== false) {
$port = (int) substr($host, $pos + 1);
$host = strstr($host, ':', true);
}
} // Path
//文件名/脚本名
$requestScriptName = parse_url($env->get('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. //就是uri,主机名后面的字符串
$requestUri = parse_url('http://example.com' . $env->get('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)), '/');
} // Query string
$queryString = $env->get('QUERY_STRING', ''); // Fragment
$fragment = ''; // Build Uri
$uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password);
if ($basePath) {
$uri = $uri->withBasePath($basePath);
} return $uri;
}
protected 'scheme' => string 'http' (length=4)
protected 'user' => string '' (length=0)
protected 'password' => string '' (length=0)
protected 'host' => string 'localhost' (length=9)
protected 'port' => int
protected 'basePath' => string '/example' (length=8)
protected 'path' => string 'forbase' (length=7)
protected 'query' => string '' (length=0)
class Headers extends Collection implements HeadersInterface
/**
* Create new headers collection with data extracted from
* the application Environment object
*
* @param Environment $environment The Slim application Environment
*
* @return self
*/
public static function createFromEnvironment(Environment $environment)
{
$data = [];
foreach ($environment as $key => $value) {
$key = strtoupper($key);
if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) {
if ($key !== 'HTTP_CONTENT_LENGTH') {
$data[$key] = $value;
}
}
} return new static($data);
}
/**
* Set HTTP header value
*
* This method sets a header value. It replaces
* any values that may already exist for the header name.
*
* @param string $key The case-insensitive header name
* @param string $value The header value
*/
public function set($key, $value)
{
if (!is_array($value)) {
$value = [$value];
}
parent::set($this->normalizeKey($key), [
'value' => $value,
'originalKey' => $key
]);
} /**
* Get HTTP header value
*
* @param string $key The case-insensitive header name
* @param mixed $default The default value if key does not exist
*
* @return string[]
*/
public function get($key, $default = null)
{
if ($this->has($key)) {
return parent::get($this->normalizeKey($key))['value'];
} return $default;
}
protected 'data' =>
array (size=9)
'host' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_HOST' (length=9)
'connection' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_CONNECTION' (length=15)
'cache-control' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_CACHE_CONTROL' (length=18)
'accept' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_ACCEPT' (length=11)
'upgrade-insecure-requests' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_UPGRADE_INSECURE_REQUESTS' (length=30)
'user-agent' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_USER_AGENT' (length=15)
'accept-encoding' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_ACCEPT_ENCODING' (length=20)
'accept-language' =>
array (size=2)
'value' =>
array (size=1)
...
'originalKey' => string 'HTTP_ACCEPT_LANGUAGE' (length=20)
'cookie' =>
array (size=2)
'value' =>
array (size=1)
...
class Cookies implements CookiesInterface
/**
* Parse HTTP request `Cookie:` header and extract
* into a PHP associative array.
*
* @param string $header The raw HTTP request `Cookie:` header
*
* @return array Associative array of cookie names and values
*
* @throws InvalidArgumentException if the cookie data cannot be parsed
*/
public static function parseHeader($header)
{
if (is_array($header) === true) {
$header = isset($header[0]) ? $header[0] : '';
} if (is_string($header) === false) {
throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.');
} $header = rtrim($header, "\r\n");
$pieces = preg_split('@\s*[;,]\s*@', $header); $cookies = []; foreach ($pieces as $cookie) {
$cookie = explode('=', $cookie, 2); if (count($cookie) === 2) {
$key = urldecode($cookie[0]);
$value = urldecode($cookie[1]); if (!isset($cookies[$key])) {
$cookies[$key] = $value;
}
}
}
return $cookies;
}
//创建了一个body stream ,stream 指向php://input,这个php://input可以读取原始的POST数据
$body = new RequestBody();
其实是用来获取原始POST数据的。
public function __construct(
$method,
UriInterface $uri,
HeadersInterface $headers,
array $cookies,
array $serverParams,
StreamInterface $body,
array $uploadedFiles = []
) {
$this->originalMethod = $this->filterMethod($method);
$this->uri = $uri;
$this->headers = $headers;
$this->cookies = $cookies;
$this->serverParams = $serverParams;
$this->attributes = new Collection();
$this->body = $body;
$this->uploadedFiles = $uploadedFiles; if (isset($serverParams['SERVER_PROTOCOL'])) {
$this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']);
} if (!$this->headers->has('Host') || $this->uri->getHost() !== '') {
$this->headers->set('Host', $this->uri->getHost());
} $this->registerMediaTypeParser('application/json', function ($input) {
return json_decode($input, true);
}); $this->registerMediaTypeParser('application/xml', function ($input) {
$backup = libxml_disable_entity_loader(true);
$result = simplexml_load_string($input);
libxml_disable_entity_loader($backup);
return $result;
}); $this->registerMediaTypeParser('text/xml', function ($input) {
$backup = libxml_disable_entity_loader(true);
$result = simplexml_load_string($input);
libxml_disable_entity_loader($backup);
return $result;
}); $this->registerMediaTypeParser('application/x-www-form-urlencoded', function ($input) {
parse_str($input, $data);
return $data;
});
}
这样一个request就妥当了,而且含有method、body等数据。
代码研磨 Slim v3 (二)--app->run()的更多相关文章
- 代码研磨 Slim v3 (一)--app->get()&route->add()
index.php代码如下: $app->get('/forbase', function ($request, $response, $args){ Example\Module\Base:: ...
- Python库源码学习1:Flask之app.run
先列出app.run()实现的功能,我们以debug=True的情况下进行分析. 1. web服务器,处理http请求 2. 当代码修改后,重启服务器 那么app.run()是如何实现这两个功能的呢? ...
- 【转】【翻】Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏
转自:http://mrfufufu.github.io/android/2015/07/01/Codelab_Android_Design_Support_Library.html [翻]Andro ...
- Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏
原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fanc ...
- tf.app.run()
在很多TensorFlow公布的Demo中,都有这样的代码存在,如下,这是干什么的呢? if __name__ == "__main__": tf.app.run() 我们来看一下 ...
- tensorflow中的tf.app.run()的使用
指明函数的入口,即从哪里执行函数. 如果你的代码中的入口函数不叫main(),而是一个其他名字的函数,如test(),则你应该这样写入口tf.app.run(test()) 如果你的代码中的入口函数叫 ...
- tf.app.run() got unexpected keyword argument 'argv'
运行的代码是mnist_with_summaries.py.出现的问题是 tf.app.run() got unexpected keyword argument 'argv' 昨天一直以为是我自己不 ...
- tf.app.run()的作用
tf.app.run() 如果你的代码中的入口函数不叫main(),而是一个其他名字的函数,如test(),则你应该这样写入口tf.app.run(test) 如果你的代码中的入口函数叫main(), ...
- flask 源码专题(一):app.run()的背后
当我们用Flask写好一个app后, 运行app.run()表示监听指定的端口, 对收到的request运行app生成response并返回. 现在分析一下, 运行app.run()后具体发生了什么事 ...
随机推荐
- 批量更改数据库COLLATION
企业内部有很多系统是繁体的,由于各方面的原因,公司目前正在实行简体化,但各系统中又有数据间的交换,所以系统只能一个一个的更改,以防同时出现过多的问题.由于原先数据库只能存储繁体,而原先已存在的数据则可 ...
- xx.exe 中的 0x7c92e4df 处最可能的异常: 0xC0000008: An invalid handle was specified
今天遇到个超级奇怪的问题,昨天还好端端的程序,今天用VS打开后,在关闭主窗口的时候居然弹出错误提示:xx.exe 中的 0x7c92e4df 处最可能的异常: "0xC0000008: An ...
- ST10 Bootstrap Loader
Bootstrap Loader The built-in bootstrap loader (BSL) of the ST10F269 provides a mechanism to load th ...
- jQuery关于文字内容溢出用点点点(…)省略号表示
1.jQuery限制字符字数的方法代码很简单,使用也很方便,如下: $(document).ready(function(){//限制字符个数$(“.zxx_text_overflow”).each( ...
- iOS 本地企业发布流程
今天和后台弄了一下本地企业ipa发布, 准备工具:要发布的ipa文件一个,一个plist plist文件格式内容: <?xml version="1.0" encoding= ...
- .Net 应用程序如何在32位操作系统下申请超过2G的内存【转】
作者: eaglet 2008 年我写过一篇博客叫 <让.Net 应用程序突破2G的内存访问限制> 这篇博客主要讲述了如何在32位操作系统下利用AWE 扩展访问超过2G的内存.AWE方式虽 ...
- echarts通过ajax向服务器发送post请求,servlet从数据库读取数据并返回前端
1.echarts的官网上的demo,都是直接写死的随机数据,没有和数据库的交互,所以就自己写了一下,ok,我们开始一步一步走一遍整个流程吧. 就以官网最简单的那个小demo来做修改吧.官网上的小de ...
- JavaScript宝座:七大框架论剑
JavaScript宝座:七大框架论剑 一周前,Throne of JS大会在多伦多召开,这应该是我参加过的最有料也最不一样的一次大会.大会官网如是说: 加载整个页面,然后再“渐进增强”以添加动态行为 ...
- 【JavaScript】前端开发框架三剑客—AngularJS VS. Backone.js VS.Ember.js
摘要:透过对Github,StackOverflow,YouTube等社区进行数据收集后可知,AngularJS在各大主流社区中都是最受欢迎的,Backbone.js与Ember.js则不相伯仲.本文 ...
- 安装jasperwave出错
1.错误描写叙述 2.错误原因 无法下载"com.jasperwave.engine_1.1.0.jar",须要又一次下载 3.解决的方法 将"com.jasperwav ...