laruence / yar

Light, concurrent RPC framework for PHP & C
Other
1.43k stars 319 forks source link

yar扩展无法在基于swoole环境的框架中使用 #150

Open qifengzhang007 opened 4 years ago

qifengzhang007 commented 4 years ago

本次测试基于 swoole 环境运行的 hyperf 框架。 以下相同的代码,在 Laravel 框架中测试一切OK

  1. 示例代码,创建一个Users类
    
    class Users
    {
function   Register(){
    var_dump("用户注册");
    echo '用户注册';
}

function   Login(){
    var_dump("用户登录");
    echo '用户登录';
}

}

> 2.yar扩展创建Server  
```php
    function TestYar(){
        $users=new \Yar_Server(new Users());
        $users->handle();
    }

3.客户端调用代码

<?php
$micro_client_user=new Yar_Client('http://139.196.101.31:9501/testYar');
$res=$micro_client_user->Register();
echo  $res ;

$res=$micro_client_user->Login();
echo  $res ;

报错代码

string(208) "
2020-03-15 17:27:23, OcurredError,Type: WAINING, errorFile: /home/wwwroot/www.hyperf.com/stock/app/Controller/IndexController.php, Line: 46, errorMessage: Yar_Server::handle(): headers already has been sent
"
string(16) "errorTrace:↓"
string(1759) "
1   {"function":"error_handle","args":[2,"Yar_Server::handle(): headers already has been sent","/home/wwwroot/www.hyperf.com/stock/app/Controller/IndexController.php",46,{"users":{}}]}

2   {"file":"/home/wwwroot/www.hyperf.com/stock/app/Controller/IndexController.php","line":46,"function":"handle","class":"Yar_Server","object":{},"type":"->","args":[]}
laruence commented 4 years ago

这是说Header已经被发送过了,或者之前已经有输出了,不确定是否是Swoole会默认输出什么东西?

laruence commented 4 years ago
PHP_METHOD(yar_server, handle)
{
    if (SG(headers_sent)) {
        php_error_docref(NULL, E_WARNING, "headers already has been sent");
        RETURN_FALSE;

@matyhtf 有没有可能swoole在一个请求结束后,没有重置这个SG(headers_sent)标志?

matyhtf commented 4 years ago

@laruence 由于 swoole 是并发服务器,没有SG(headers_sent)全局变量的概念。状态是绑定在RequestResponse对象上的。请求响应的处理不会设置SG(headers_sent)全局变量状态。只有局部变量,没有任何全局变量。

在 swoole 中也无法使用 PHP 的header()setcookie() 等函数

想不到太好的解决办法,这里应该有好几个地方不兼容。

<?php
$http = new swoole_http_server("127.0.0.1", 9501);

$http->on("start", function ($server) {
    echo "Swoole http server is started at http://127.0.0.1:9501 \n";
});

$http->on("request", function ($request, $response) {
    $response->header("Content-Type", "text/plain");
    $response->cookie("test", "value", time() + 3600);
    var_dump($requset->get, $requset->post, $request->cookie);
    $response->end("Hello World\n");
});

$http->start();
matyhtf commented 4 years ago

如果要兼容 swoole 或者 workerman 这样的服务器,yar 需要提供设置自定义 header、setcookie 的 API

laruence commented 4 years ago

hmm, 看起来没那么简单,不过在swoole场景下,还要yar干嘛呢?或者就不http了?