htttpServer结构
1、httpServer本质是Swoole_server,其协议解析部分固定使用http协议解析
2、完整的http协议请求会被解析并封装在swoole_http_request对象内
3、所有的http相应都通过swoole_http_response对象封装和发送
注意事项
1、swoole_http_server不接受onReceive回调,但是可以使用Task worker和定时器
2、swoole_http_server可以使用诸如onStart、onWorkerStart等回调
3、response/request对象传递给其他函数是,不要加&引用符号(有可能底层没有销毁)、结束请求一定要销毁
swoole_http_request
$header http请求头部信息。类型为数组,所有key均为小写
$server http请求相关的服务器信息
$get Http请求的post参数,相当于PHP中的$_GET
$post http请求的post参数,相当于php中的$_POST,Content-type限定为application/x-www-form-urlencode
$cookie http请求的cookie参数,相当于PHP中的$_COOKIE
$files Http上传文件的文件信息,相当于PHP中的$_FILES
rawcontent()原始的http POST内容,用于非application/x-www-form-urlencode
swoole_http_response
swoole_http_response::header($key,$value);
设置Http响应的头信息
swoole_http_response::cooke($key,$value=””,$expire=0,$path=”/”,$domian=”/”,$secure=false,$httponly=false);
设置http响应的cookie信息,等效于php的setcookie函数
swoole_http_response::status($code);
设置http响应的状态码,如200,404,503等
swoole_http_response::gzip($level=1);
开启GZIP压缩
swoole_http_response::write($data);
启用http chunk分段向浏览器发送响应内容
swoole_http_response::sendfile($filename);
发送文件到浏览器
swoole_http_response::end($data);
发送http响应
用httpserver模拟简单路由
代码结构
simple_route.php
新版本4.4开始命名方式为swoole\http\server
<?php
$http = new Swoole\Http\Server("0.0.0.0",80);
$http->set([
'worker_num' => 2,
'daemonize' => false, 'max_request' => 10000, 'dispatch_mode' => 2,
]);
$http->on('request',function(Swoole\Http\Request $request, Swoole\Http\Response $response){
var_dump($request);
$response->end("<h1>hello</h1>");
});
$http->on("start", function (Swoole\Http\Server $server) {
echo "Swoole http server is started at http://127.0.0.1:9501\n";
});
$http->on('close',function(Swoole\Http\Server $server){
echo "close";
});
$http->start();
老版本
<?php
/**
* Created by PhpStorm.
* User: lancelot
* Date: 16-7-9
* Time: 下午6:15
*/
$serv = new swoole_http_server("0.0.0.0", 9501);
$serv->set([
'worker_num' => 1
]);
$serv->on('Start' , function(){
swoole_set_process_name('simple_route_master');
});
$serv->on('ManagerStart' , function(){
swoole_set_process_name('simple_route_manager');
});
$serv->on('WorkerStart' , function(){
swoole_set_process_name('simple_route_worker');
var_dump(spl_autoload_register(function($class){
$baseClasspath = \str_replace('\\', DIRECTORY_SEPARATOR , $class) . '.php';
$classpath = __DIR__ . '/' . $baseClasspath;
if (is_file($classpath)) {
require "{$classpath}";
return;
}
}));
});
$serv->on('Request', function($request, $response) {
$path_info = explode('/',$request->server['path_info']);
if( isset($path_info[1]) && !empty($path_info[1])) { // ctrl
$ctrl = 'ctrl\\' . $path_info[1];
} else {
$ctrl = 'ctrl\\Index';
}
if( isset($path_info[2] ) ) { // method
$action = $path_info[2];
} else {
$action = 'index';
}
$result = "Ctrl not found";
if( class_exists($ctrl) )
{
$class = new $ctrl();
$result = "Action not found";
if( method_exists($class, $action) )
{
$result = $class->$action($request);
}
}
$response->end($result);
});
$serv->start();
ctrl\index.php
<?php
/**
* Created by PhpStorm.
* User: lancelot
* Date: 16-7-9
* Time: 下午6:37
*/
namespace ctrl;
class Index
{
public function index($request)
{
return "Hello World";
}
}
ctrl\Login.php
<?php
/**
* Created by PhpStorm.
* User: lancelot
* Date: 16-7-9
* Time: 下午6:38
*/
namespace ctrl;
class Login
{
public function login($request)
{
$post = isset($request->post) ? $request->post : array();
// TODO
return "login success";
}
}
reload.sh实现代码热加载(不必关闭所有进程、这样正在访问的程序不会报错)
#!/usr/bin/env bash
ps aux | grep simple_route_master | awk '{print $2}' | xargs kill -USR1
实现文件上传服务
uploader.php服务端server
<?php
/**
* Created by PhpStorm.
* User: lancelot
* Date: 16-7-9
* Time: 下午6:16
*/
$serv = new swoole_http_server("127.0.0.1", 9501);
$serv->set([
'max_package_length' => 200000000,
]);
//上传文件的大小 受到max_package_length的限制
$serv->on('Request', function($request, $response) use($serv) {
if($request->server['request_method'] == 'GET' )
{
return;
}
var_dump($request->files);
$file = $request->files['file'];
$file_name = $file['name'];
$file_tmp_path = $file['tmp_name'];
$upload_path = __DIR__ . '/uploader/';
if( !file_exists($upload_path) )
{
mkdir($upload_path);
}
move_uploaded_file($file_tmp_path , $upload_path . $file_name );
$response->end("<h1>Upload Success!</h1>");
});
$serv->start();
前端html
<!DOCTYPE html>
<html>
<body>
<form action="http://127.0.0.1:9501/" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
nginx和swoole的结合
nginx的反向代理的、php和静态文件的请求分流
server {
listen 80;
server_name swoole.solo365.cn;
#charset koi8-r;
access_log logs/access_www.log main ;
error_log logs/error_www.log;
root /usr/local/nginx/html/swoole;
location /{
if(!-e $request_filename){
rewrite ^/(.^)$ /index.php/$1 last;
break;
}
}
location /static{
root /usr/local/ningx/html/swoole/public/static;
}
location / {
index index.php index.html index.htm;
# #### 密码访问 ####
# auth_basic "test posernode";
# auth_basic_user_file /usr/local/nginx/conf/vhost/password;
autoindex on;
}
location ~\.ico {
root /root /usr/local/ningx/html/swoole/public;
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location ~ .+\.php.*$ {
proxy_pass http://127.0.0.1:9501;
}
}