mattvb91/caddy-php

通过PHP控制您的Caddy实例

v0.0.16-alpha 2024-06-17 16:54 UTC

README

.github/workflows/ci_cd.yml codecov Total Downloads Latest Stable Version License

通过PHP控制您的Caddy实例

这更像是一个概念验证,而不是一个完全工作的项目。它试图通过链式PHP类来复制caddy JSON API的结构。

目前,只有Caddy 2.0的一小部分命令可用,覆盖了我当前所需的使用场景。

安装

composer require mattvb91/caddy-php

基本用法

一个简单的HTTP服务器示例,具有静态响应

$caddy = new Caddy();

$caddy->addApp(
    (new Http())->addServer(
        'server1', (new Http\Server())->addRoute(
        (new Route())->addHandle(
            new StaticResponse('Hello world', 200)
        )
    ))
);

$caddy->load();

这将生成以下Caddy配置

{
  "admin": {
    "disabled": false,
    "listen": ":2019"
  },
  "apps": {
    "http": {
      "servers": {
        "server1": {
          "listen": [
            ":80"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "static_response",
                  "body": "Hello world",
                  "status_code": 200
                }
              ]
            }
          ]
        }
      }
    }
  }
}
curl -v localhost

-----
< HTTP/1.1 200 OK
< Server: Caddy
Hello world       

管理主机名

如果您正在动态管理主机名(在数据库中),并且无法使用现有主机名列表构建配置,因为您需要在运行时管理它们,您可以执行以下操作

此示例中重要的一部分是host_group_name标识符,稍后用于向此主机添加/删除域名。

$caddy = new Caddy();
$caddy->addApp(
    (new Http())->addServer(
        'server1', (new Http\Server())->addRoute(
        (new Route())->addHandle(
            new StaticResponse('host test', 200)
        )->addMatch((new Host('host_group_name'))
            ->setHosts(['localhost'])
        )
    )->addRoute((new Route())
        ->addHandle(new StaticResponse('Not found', 404))
        ->addMatch((new Host('notFound'))
            ->setHosts(['*.localhost'])
        )
    ))
);
$caddy->load();

添加主机名

稍后,在脚本或系统事件中,您可以从caddy配置对象中获取新的域名并将其发布到该路由下

$caddy->addHostname('host_group_name', 'new.localhost')
$caddy->addHostname('host_group_name', 'another.localhost')
curl -v new.localhost
> GET / HTTP/1.1
> Host: new.localhost
> 
< HTTP/1.1 200 OK

curl -v another.localhost
> GET / HTTP/1.1
> Host: another.localhost
> 
< HTTP/1.1 200 OK

删除主机名

$caddy->syncHosts('host_group_name'); //Sync from caddy current hostname list

$caddy->removeHostname('host_group_name', 'new.localhost');
$caddy->removeHostname('host_group_name', 'another.localhost');
curl -v new.localhost
> GET / HTTP/1.1
> Host: new.localhost
> 
< HTTP/1.1 404 Not Found

curl -v another.localhost
> GET / HTTP/1.1
> Host: another.localhost
> 
< HTTP/1.1 404 Not Found

高级示例

让我们考虑一个场景,您想要有一个Node前端和PHP后端,在/api/*路由上处理请求。在这种情况下,示例分解为两个反向代理,具有路由匹配器以过滤/api/*到PHP上游。

这假设3个主机(Caddy、Node、PHP)都是docker容器,并且可以在同一docker网络中通过容器名称访问,因此您可能需要根据需要调整主机名。

use mattvb91\CaddyPhp\Caddy;
use mattvb91\CaddyPhp\Config\Apps\Http;
use mattvb91\CaddyPhp\Config\Apps\Http\Server;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Route;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Routes\Handle\ReverseProxy;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Routes\Handle\ReverseProxy\Transport\FastCGI;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Routes\Handle\ReverseProxy\Upstream;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Routes\Handle\Subroute;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Routes\Match\Host;
use mattvb91\CaddyPhp\Config\Apps\Http\Server\Routes\Match\Path;

$apiReverseProxy = (new ReverseProxy())
    ->addUpstream((new Upstream())
        ->setDial('laravel-api:9000')
    )->addTransport((new FastCGI())
        ->setRoot('/app/public/index.php')
        ->setSplitPath([''])
    );

$apiMatchPath = (new Path())
    ->setPaths([
        '/api/*',
    ]);

$backendAPIRoute = (new Route())
    ->addHandle($apiReverseProxy)
    ->addMatch($apiMatchPath);

$route = new Route();
$route->addHandle((new Subroute())
    ->addRoute($backendAPIRoute)
    ->addRoute((new Route())
        ->addHandle((new ReverseProxy())
            ->addUpstream((new Upstream())
                ->setDial('nextjs:3000')
            )
        )
    )
)->addMatch((new Host())
    ->setHosts([
        'localhost',
    ])
)->setTerminal(true);

$caddy = new Caddy();
$caddy->addApp((new Http())
    ->addServer('myplatform', (new Server())
        ->addRoute($route)
    )
);
$caddy->load();

这将发布以下caddy配置

{
  "admin": {
    "disabled": false,
    "listen": ":2019"
  },
  "apps": {
    "http": {
      "servers": {
        "myplatform": {
          "listen": [
            ":80"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "transport": {
                            "protocol": "fastcgi",
                            "root": "/app/public/index.php",
                            "split_path": [
                              ""
                            ]
                          },
                          "upstreams": [
                            {
                              "dial": "laravel-api:9000"
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "path": [
                            "/api/*"
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "nextjs:3000"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "localhost"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}
curl -v localhost

< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Server: Caddy
< X-Powered-By: Next.js
< Transfer-Encoding: chunked
< 
<!DOCTYPE html><html>....
curl -v localhost/api/testroute

< HTTP/1.1 200 OK
< Content-Type: application/json
< Server: Caddy
< X-Powered-By: PHP/8.1.7
< 
{"status":200}

查看测试以获取更多示例。