swoole http 客户端

文件结构

复制代码
>ls -lR
total 0
drwxrwxrwx 1 root root 512 Jan 14 16:19 client
drwxrwxrwx 1 root root 512 Jan 15 10:42 public
drwxrwxrwx 1 root root 512 Jan 15 10:21 server
drwxrwxrwx 1 root root 512 Jan 15 01:12 test

./client:
total 8
-rwxrwxrwx 1 root root 367 Jan 14 10:13 tcp_client.php
-rwxrwxrwx 1 root root 745 Jan 14 17:08 tcp_client_2.php
-rwxrwxrwx 1 root root 367 Jan 14 10:13 udp_client.php
-rwxrwxrwx 1 root root 911 Jan 14 17:05 udp_client_2.php

./public:
total 0
-rwxrwxrwx 1 root root 226 Jan 15 10:42 index.html

./server:
total 16
-rwxrwxrwx 1 root root 6360 Jan 17 07:37 http_server.php
-rwxrwxrwx 1 root root  730 Jan 14 10:09 tcp_server.php
-rwxrwxrwx 1 root root  665 Jan 14 16:35 udp_server.php

定义常量

php 复制代码
define('DS', DIRECTORY_SEPARATOR);
defined('SERVER_PATH') or define('SERVER_PATH', __DIR__ . DS);
defined('FILES_PATH') or define('FILES_PATH', dirname(realpath(SERVER_PATH)) . DS);
defined('PUBLIC_PATH') or define('PUBLIC_PATH', FILES_PATH . "public" . DS);

定义监听

php 复制代码
$address = "0.0.0.0";
$part = "80";

$http = new Server($address, $part);
$http->set(['task_worker_num' => 1, 'worker_num' => 1]);
$app = new Application();
$http->set([
    'document_root' => PUBLIC_PATH,
    'enable_static_handler' => true,
    'http_autoindex' => true,
    'http_index_files' => ['index.html', 'index.txt'],
]);
// $http->on('request', [$app, "OnRequest"]);
$http->on('request', function ($request, $reponse) use ($http) {
    $app = new Application();
    $parseInfo = $app->parsePathInfo($request);
    if (1 == $parseInfo['isdetach']) {
        $reponse->detach();
        $http->task(strval($reponse->fd));
    } else {
        $app->OnRequest($request, $reponse, $parseInfo);
    }
});
$http->on('task', function ($serv, $task_id, $worker_id, $data) {
    $resp = Response::create($data);
    $resp->write("task");
    $resp->end();
    $isWritable = empty($resp->isWritable()) ? 0 : 1;
    var_dump('isWritable:' . $isWritable);
    echo "async task\n";
});
$http->start();

解析请求数据,解析方法在Application::parsePathInfo中。

请求路径第一个数据为detach则使用$reponse->detach()创建task,在task线程中执行逻辑。

使用task进程,必须设置worker进程后开启该进程,默认不开启worker进程。

定义Application类

php 复制代码
class Application {
    private function setReponseHeader($request, $reponse) {
        $reponse->header('Content-Type', 'application/json; charset=utf-8');
        $reponse->header('access-control-allow-credentials', 'true');
        $reponse->header('access-control-allow-methods', 'GET,HEAD,POST,OPTIONS');
        $reponse->header('access-control-allow-headers', 'content-type,Authorization');
        $reponse->header('Access-Control-Allow-Private-Network', 'true');
        $origin = empty($request->header['origin']) ? '*' : $request->header['origin'];
        $reponse->header('access-control-allow-origin', $origin);
    }
    public function OnRequest($request, $reponse, $parseInfo = null) {
        $this->doredirect($request, $reponse);
        $param = $this->getparam($request);
        try {
            $this->setReponseHeader($request, $reponse);
            if (empty($parseInfo)) {
                $parseInfo = $this->parsePathInfo($request);
            }
            $data = $this->execFunction($parseInfo['controller'], $parseInfo['function'], $param);
            $reponse->end($data);
        } catch (\Throwable $th) {
            $code = $th->getCode();
            $msg = $th->getMessage();
            $data = backjson($code, $msg);
            $reponse->end($data);
        }
    }
    public function parsePathInfo($request) {
        $uri = $request->server['request_uri'];
        $uri_arr = array_values(array_filter(explode("/", $uri)));
        $isdetach = 0;
        if (2 == count($uri_arr)) {
            $c = ucfirst($uri_arr[0]) . "Controller";
            $f = $uri_arr[1];
            if (!class_exists($c)) {
                throw new \Exception("class " . $c . " not found", UseError::$SYSTEM_ERR);
            }
            if (!method_exists($c, $f)) {
                throw new \Exception("function " . $c . "::" . $f . " not found", UseError::$SYSTEM_ERR);
            }
            $data = [
                'uri' => $uri,
                'isdetach' => $isdetach,
                'controller' => $c,
                'function' => $f,
            ];
            return $data;
        } else {
            if ('detach' == $uri_arr[0]) {
                $isdetach = 1;
                $c = ucfirst($uri_arr[1]) . "Controller";
                $f = $uri_arr[2];
            }
            $data = [
                'uri' => $uri,
                'isdetach' => $isdetach,
                'controller' => $c,
                'function' => $f,
            ];
            return $data;
        }
        throw new \Exception("request_uri error", UseError::$SYSTEM_ERR);
    }
    private function doredirect($request, $reponse) {
        $uri = $request->server['request_uri'];
        if ('/baidu' == $uri) {
            $reponse->redirect("http://www.baidu.com/", 301);
        }
    }
    private function getparam($request) {
        $method = $request->getMethod();
        if ('GET' == $method) {
            $param = $request->get;
        } elseif ("POST" == $method) {
            $param = $request->post;
        }
        return $param;
    }

    public function execFunction($controller, $function, $param = []) {
        $object = new $controller();
        $reflection = new ReflectionClass($object);
        $method = $reflection->getMethod($function);
        $neddparams = $method->getParameters();
        if (count($neddparams) > 0) {
            $name_arr = [];
            foreach ($neddparams as $key => $value) {
                $name = $value->getName();
                $isOptional = $value->isOptional();
                $name_arr[] = $name;
                if (!isset($param[$name]) && !$isOptional) {
                    throw new \Exception("param " . $name . " is null", UseError::$SYSTEM_ERR);
                }
            }
            foreach ($param as $key => $value) {
                if (!in_array($key, $name_arr)) {
                    unset($param[$key]);
                }
            }
        } else {
            $param = [];
        }
        $reault = $method->invokeArgs($object, $param);
        return $reault;
    }
}

Application类中判断请求路径是否符合跳转条件,类似于反代理。

反代理解析Controller类。

IndexController类

php 复制代码
Class IndexController {
    public function hello() {
        $data = [
            "msg" => "hello word",
        ];
        return backjson(200, "success", $data);
    }

    public function test($name) {
        $data = [
            "msg" => "hello " . $name,
        ];
        return backjson(200, "success", $data);
    }

}

定义Error类

php 复制代码
class UseError {
    public static $SYSTEM_ERR = 500;
}
相关推荐
Arwen30312 小时前
IP地址证书的常见问题有哪些?有没有特殊渠道可以申请免费IP证书?
服务器·网络·网络协议·tcp/ip·http·https
蜂蜜黄油呀土豆1 天前
深入理解计算机网络中的应用层协议
网络协议·计算机网络·http
txinyu的博客1 天前
HTTP
网络·网络协议·http
bugcome_com1 天前
HTTP 状态码详解
网络·网络协议·http
Jack_abu1 天前
记录一次由yum update引起的http服务ERR_CONTENT_LENGTH_MISMATCH问题
http·tcpoom·yum update
于归pro1 天前
浅谈HTTP状态响应码
网络·网络协议·http
掘根1 天前
【JSONRpc项目】项目前置准备
服务器·网络·网络协议·http
派大鑫wink1 天前
【Day31】Web 开发入门:HTTP 协议详解(请求 / 响应、状态码、请求头)
前端·网络协议·http
qq_411262421 天前
SOS的wifi报警器,通过按钮触发上报,上报就是一个标准的http协议接口
网络·网络协议·http