基于Swoole的HTTP/HTTPS代理
N行代码实现一个简单的代理服务器
<?php
/**
 * Web代理服务器(支持http/https)
 * @author zhjx922
 */
class WebProxyServer
{
    private $_client = [];
    private $_server;
    /**
     * 日志打印
     * @author zhjx922
     * @param string $message
     */
    protected function log($message)
    {
        echo $message . PHP_EOL;
    }
    /**
     * 获取代理ip
     * @author zhjx922
     */
    protected function getLocalIp()
    {
        //获取代理IP
        $ipList = swoole_get_local_ip();
        foreach($ipList as $interface => $ip) {
            $this->log("{$interface}:{$ip}");
        }
    }
    /**
     * 初始化
     * @author zhjx922
     */
    protected function init()
    {
        $this->getLocalIp();
        $this->_server = new swoole_server("0.0.0.0", 8889);
        $this->_server->set([
            'buffer_output_size' => 64 * 1024 *1024, //必须为数字
        ]);
    }
    /**
     * 跑起来
     * @author zhjx922
     */
    public function run()
    {
        $this->init();
        $this->_server->on('connect', function ($server, $fd){
            $this->log("Server connection open: {$fd}");
        });
        $this->_server->on('receive', function ($server, $fd, $reactor_id, $buffer){
            //判断是否为新连接
            if(!isset($this->_client[$fd])) {
                //判断代理模式
                list($method, $url) = explode(' ', $buffer, 3);
                $url = parse_url($url);
                //ipv6为啥外面还有个方括号?
                if(strpos($url['host'], ']')) {
                    $url['host'] = str_replace(['[', ']'], '', $url['host']);
                }
                //解析host+port
                $host = $url['host'];
                $port = isset($url['port']) ? $url['port'] : 80;
                //ipv4/v6处理
                $tcpMode = strpos($url['host'], ':') !== false ? SWOOLE_SOCK_TCP6 : SWOOLE_SOCK_TCP;
                $this->_client[$fd] = new swoole_client($tcpMode, SWOOLE_SOCK_ASYNC);
                if($method == 'CONNECT')
                {
                    $this->_client[$fd]->on("connect", function (swoole_client $cli) use ($fd) {
                        $this->log("隧道模式-连接成功!");
                        //告诉客户端准备就绪,可以继续发包
                        $this->_server->send($fd, "HTTP/1.1 200 Connection Established\r\n\r\n");
                    });
                } else {
                    $this->_client[$fd]->on("connect", function(swoole_client $cli) use ($buffer) {
                        $this->log("正常模式-连接成功!");
                        //直接转发数据
                        $cli->send($buffer);
                    });
                }
                $this->_client[$fd]->on("receive", function(swoole_client $cli, $buffer) use ($fd){
                    //将收到的数据转发到客户端
                    if($this->_server->exist($fd)) {
                        $this->_server->send($fd, $buffer);
                    }
                });
                $this->_client[$fd]->on("error", function(swoole_client $cli) use ($fd){
                    $this->log("Client {$fd} error");
                });
                $this->_client[$fd]->on("close", function(swoole_client $cli) use ($fd){
                    $this->log("Client {$fd} connection close");
                });
                $this->_client[$fd]->connect($host, $port);
            } else {
                //已连接,正常转发数据
                if($this->_client[$fd]->isConnected()) {
                    $this->_client[$fd]->send($buffer);
                }
            }
        });
        $this->_server->on('close', function ($server, $fd) {
            $this->log("Server connection close: {$fd}");
            unset($this->_client[$fd]);
        });
        $this->_server->start();
    }
}
$server = new WebProxyServer();
$server->run();基于Swoole的HTTP/HTTPS代理的更多相关文章
- LaravelS - 基于Swoole加速Laravel/Lumen
		LaravelS LaravelS是一个胶水项目,用于快速集成Swoole到Laravel或Lumen,然后赋予它们更好的性能.更多可能性.Github 特性 内置Http/WebSocket服务器 ... 
- tcpproxy:基于 Swoole 实现的 TCP 数据包转发工具的方法
		假设我们希望有一台机器A(ip 192.168.1.101)要开放端口6379给用户访问,但可能实际情况是用户无法直接访问到A(ip 192.168.1.101), 但却有一台机器B(ip 192.1 ... 
- 基于 SSL 的 Nginx 反向代理
		基于 SSL 的 Nginx 反向代理 描述: 线上zabbix因机房网络问题,外网接口无法对外访问,因此采用同机房的另外一台服务器做反向代理. 线上用于zabbix提供web访问的Nginx,采用h ... 
- 手撸基于swoole 的分布式框架 实现分布式调用(20)讲
		最近看的一个swoole的课程,前段时间被邀请的参与的这个课程 比较有特点跟一定的深度,swoole的实战教程一直也不多,结合swoole构建一个新型框架,最后讲解如何实现分布式RPC的调用. 内容听 ... 
- [Sw] Swoole 生态迷局,基于 Swoole 的第 109 框架
		这两天,又一全栈式 Swoole 协程框架面世了 - hyperf,实现思路是我内心点了赞同的,就集成现有 PHP 生态优质组件到 Swoole 的协程中来. 有人想到,为什么不是 Swoole 集成 ... 
- websocket和基于swoole的简易即时通讯
		这里描述个基于swoole的websocket 匿名群聊 UI <!DOCTYPE html> <html> <head> <meta charset=&qu ... 
- 一个基于swoole的作业调度组件,已经实现了redis和rabitmq队列消息存储。
		https://github.com/kcloze/swoole-jobs 一个基于swoole的作业调度组件,已经实现了redis和rabitmq队列消息存储.参考资料:swoole https:/ ... 
- 房产基于Swoole的PHP RPC框架设计
		房产基于Swoole的PHP RPC框架设计 https://mp.weixin.qq.com/s/XSrKEQ-0q4DvjOGTIwYYzg 
- Nginx安装及支持https代理配置和禁用TSLv1.0、TSLv1.1配置
		Linux安装Nginx Nginx安装及支持https代理配置和禁用TSLv1.0.TSLv1.1配置. 下载安装包 [root@localhost ~]# wget http://nginx.or ... 
随机推荐
- django类视图的装饰器验证
			django类视图的装饰器验证 django类视图的get和post方法是由View内部调用dispatch方法来分发,最后调用as_view来完成一个视图的流程. 函数视图可以直接使用对应的装饰器 ... 
- 2059 - Authentication plugin 'caching_sha2_password' cannot be loaded dlope
			今天在mac上使用navicat连接mysql报错弄了一下午,各种查询踩坑,总算解决了. 即从mysql5.7版本之后,默认采用了caching_sha2_password验证方式,我用的mysql8 ... 
- Solr复杂查询一:函数查询
			一.简介 Solr的函数可以动态计算每个文档的值,而不是返回在索引阶段对应字段的静态数值集.函数查询是一类特殊的查询,它可以像关键词一样添加到查询中,对所有文档进行匹配并返回它们的函数计算值作为文档得 ... 
- Linux下删除大量文件效率对比
			来自公众号:马哥Linux运维 今天我们来测试一下Linux下面删除大量文件的效率. 首先建立50万个文件 $ test for i in $(seq 1 500000);do echo text ... 
- Linux远程登陆
			Linux 远程登录 Linux一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的Linux服务器. 这时我们就需要远程登录到Linux服务器来管理维护系统. Linux系统中是通过ss ... 
- group_concat有长度限制
			group_concat有长度限制 group_concat 详细用法请点此链接. group_concat有长度限制!长度陷阱用了group_concat后,select里如果使用了li ... 
- AJ学IOS 之微博项目实战(6)导航控制器NavigationController 的滑动回退功能实现
			AJ分享,必须精品 一:效果 第二篇里面写了怎样自定义navigation实现自定义的导航控制器左右按钮样式,但是当我们自己实现后,系统自带的向右边滑动来实现回退的功能就不能用了. 这里主要实现滑动回 ... 
- 学会这项python技能,就再也不怕孩子偷偷打游戏了
			前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:鸟哥 PS:如果想了解更多关于python的应用,可以私信小编,资料 ... 
- 基于netty实现rpc框架-spring boot服务端
			demo地址 https://gitee.com/syher/grave-netty RPC介绍 首先了解一下RPC:远程过程调用.简单点说就是本地应用可以调用远程服务器的接口.那么通过什么方式调用远 ... 
- C#栈、堆的理解(2)
			接上一遍博文有关值类型和引用类型的相关概念. 所有值类型数据存放:栈(内存) 引用类型的数据存放:堆(内存) 栈:可以认为是一本书的目录部分称其为栈.栈可快速检索,运行速度比堆大,而且栈的空间小得多. ... 
