diff --git a/README.md b/README.md index f06a1ca..af8cd88 100644 --- a/README.md +++ b/README.md @@ -180,18 +180,42 @@ php webman migrate ``` 3. **访问地址:** - - 安装向导:http://localhost:1818/install/ - - 前台地址:http://localhost:1818/index.html/#/ - - 后台地址:http://localhost:1818/index.html/#/admin + - 安装向导:http://localhost:1818/install/ + - 前台地址:http://localhost:1818/index.html/#/ + - 后台地址:http://localhost:1818/index.html/#/admin > 注意:前端通过 Vite 代理将 `/api`、`/admin`、`/install` 转发到后端 8787 端口,请勿直接访问 8787 端口的前端页面,否则可能出现 404。 +### 5.6 生产环境 Nginx(反向代理 Webman) + +部署到服务器时,若使用 **Nginx** 作为站点入口,需将请求转发到本机 **Webman** 进程(默认监听端口与 `config/process.php` 中 `listen` 一致,一般为 `8787`,反代目标使用 `127.0.0.1:8787`)。 + +在站点 **`server { }`** 块中可增加如下写法:**先由 Nginx 根据 `root` 判断是否存在对应静态文件;不存在则转发到 Webman**(`root` 建议指向项目 `public` 目录)。 + +```nginx +location ^~ / { + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection ""; + if (!-f $request_filename) { + proxy_pass http://127.0.0.1:8787; + } +} +``` + +修改配置后执行 `nginx -t` 校验,再重载 Nginx;并确保 Webman 已启动(如 `php start.php start -d`)。 + +若前端与接口为**不同域名**(跨域),除反代外还需保证 **HTTPS 证书与域名一致**,以及后端 **CORS / 预检(OPTIONS)** 与前端请求头(如 `think-lang`、`server` 等)配置一致,否则浏览器会报跨域相关错误。 + --- ## 六、路由说明 - **后台 API**:`/admin/{module}.{Controller}/{action}` - - 示例:`/admin/mall.Player/index` → `app\admin\controller\mall\Player::index` + - 示例:`/admin/mall.Player/index` → `app\admin\controller\mall\Player::index` - **前台 API**:`/api/...` - **安装**:`/api/Install/...` diff --git a/app/common/middleware/AllowCrossDomain.php b/app/common/middleware/AllowCrossDomain.php index 347eb79..842e724 100644 --- a/app/common/middleware/AllowCrossDomain.php +++ b/app/common/middleware/AllowCrossDomain.php @@ -30,7 +30,7 @@ class AllowCrossDomain implements MiddlewareInterface 'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Max-Age' => '1800', 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, PATCH, OPTIONS', - 'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, think-lang', + 'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, think-lang, server', ]; $origin = $request->header('origin'); if (is_array($origin)) { diff --git a/app/process/Http.php b/app/process/Http.php index c2f1f0d..10a5b93 100644 --- a/app/process/Http.php +++ b/app/process/Http.php @@ -3,12 +3,12 @@ namespace app\process; use Webman\App; -use Webman\Http\Response; class Http extends App { /** * 在父类处理前拦截 OPTIONS 预检,直接返回 CORS 头(避免预检未命中路由时无 CORS) + * 必须与 AllowCrossDomain::optionsResponse 一致,否则会覆盖中间件里对 Allow-Headers(如 server)的配置 */ public function onMessage($connection, $request): void { @@ -18,19 +18,8 @@ class Http extends App $path = is_string($path) ? trim($path, '/') : ''; $isApiOrAdmin = $path !== '' && (str_starts_with($path, 'api') || str_starts_with($path, 'admin')); if ($isApiOrAdmin) { - $origin = $request->header('origin'); - $origin = is_array($origin) ? ($origin[0] ?? '') : (is_string($origin) ? trim($origin) : ''); - if ($origin === '') { - $origin = '*'; - } - $headers = [ - 'Access-Control-Allow-Origin' => $origin, - 'Access-Control-Allow-Credentials' => 'true', - 'Access-Control-Max-Age' => '1800', - 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, PATCH, OPTIONS', - 'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, think-lang', - ]; - $connection->send(new Response(204, $headers, '')); + $response = \app\common\middleware\AllowCrossDomain::optionsResponse($request); + $connection->send($response); return; } }