NGINX多个域主要部分在Laravel Web中丢失

d8tt03nd  于 2023-08-03  发布在  Nginx
关注(0)|答案(3)|浏览(115)

我已经找到了一种可能的方法,可以在一个NGINX服务器上动态地处理多个Laravel项目(所以在一个foldder中,每个laravel项目可能有多个文件夹。每个laravel项目的入口点是index.php所在的/public文件夹)。这背后的主要思想是通过添加一个新的文件夹来轻松安装新的laravel项目,并能够通过我的子域和路径访问它。像www.webs.example.com/my-new-project
全部归功于Henno
这是我的域名的NGINX conf

# Capture $project from /$projectname/controller/action
map $request_uri $project {

    ~^/(?<captured_project>[a-zA-Z0-9_-]+)/? $captured_project;
    default / ;
}

server {

    listen 443; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/webs.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/webs.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    server_name webs.example.com www.webs.example.com;

    # Use $project/public as root
    root /var/www/laravel/$project/public;

    # Use index.php as directory index
    index index.php;

    # Include the basic h5bp config set (see https://github.com/h5bp/server-configs-nginx)
    # include h5bp/basic.conf;

    # Process /projectname/the/rest/of/the/url
    location ~ ^/([^/]+)/(.*) {

        # Save the rest of the URL after project name as $request_url
        set $request_url /$2;

        # If the saved url refers to a file in public folder (a static file), serve it,
        # else redirect to index.php, passing along any ?var=val URL parameters
        try_files $uri $request_url /index.php?$is_args$args;

    }

    # Process any URL containing .php (we arrive here through previous location block)
    # If you don't need to serve any other PHP files besides index.php, use location /index.php here
    # instead, to prevent possible execution of user uploaded PHP code
    location ~ [^/]\.php(/|$) {

        # Define $fastcgi_script_name and $fastcgi_path_info
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;

        # Immediately return 404 when script file does not exist
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }

        # Mitigate https://httpoxy.org/ vulnerabilities
        fastcgi_param HTTP_PROXY "";

        # Define PHP backend location (find yours by grepping "listen ="
        # from your PHP config folder, e.g. grep -r "listen =" /etc/php/)
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;

        # Set SCRIPT_FILENAME to execute
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

        # Include the default fastcgi parameters
        include fastcgi_params;

        # Overwrite REQUEST_URI (default is $request_uri) with $request_url we saved earlier
        fastcgi_param  REQUEST_URI        $request_url;
    }

}

字符串
此配置适用于Web入口点**
如果我访问webs.example.com/<project_name>(例如webs.example.com/myProject)我得到一个呈现的索引页面。因此,请求被正确处理以运行/var/www/laravel/<project_name>/public/index.php文件。
然而,页面却“残破不堪”
它的破坏,因为所有的资源(如css和js文件,图像,...)都在文件夹/public/resources/public/images中,并在代码中访问,如

<link rel="stylesheet" href="{{ asset('/resources/fontawesome/css/all.css') }}">

<img src="{{ url('/') }}{{$banner->image}}" alt="" class="img-fluid">


这将分别导致url webs.example.com/resources/fontawesome/css/all.csswebs.example.com/images/banners/1.jpg($banner->图像包含/images/banners/1.jpg)
这是没有找到的明显原因-有一个失踪的部分在网址,网址不包含项目名称,因为它应该。
所以正确的URL是(<project_name>是URL的动态部分,如myProject)

webs.example.com/<project_name>/resources/fontawesome/css/all.css
webs.example.com/<project_name>/images/banners/1.jpg


在我看来,这可能是由于NGINX配置不好造成的。因为当我尝试将Web根路径硬编码到其/public文件夹(/var/www/laravel/myProject/public)时,一切正常。因此,我正在寻求一个选项来实现这一点,默认情况下,在一些文件夹中的所有项目。在Apache上,这工作得很好
在Apache中(我正在从Apache迁移到NGINX,并且一切正常),有一种简单的方法可以解决这个问题,通过添加.htaccess,只需将root上的所有内容重定向到/public。NGINX没有这种可能性。
为了更清楚地说明,我可以将项目根文件夹(与公共文件夹处于同一级别)上的默认.htaccess内容传递给公共重定向

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ ^$1 [N]

    RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
    RewriteRule ^(.*)$ public/$1

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ server.php

</IfModule>


在/public文件夹中还有另一个.htaccess权限

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

3okqufwl

3okqufwl1#

所以如果我理解正确的话,问题根本不是你的Web服务器--而是你的Laravel应用程序生成的URL,它缺少子目录?
首先你应该知道的是,Laravel不推荐或支持你用来服务多个应用的方法。
Laravel应该总是在为您的Web服务器配置的“Web目录”的根目录中提供服务。你不应该试图从“web目录”的子目录中提供Laravel应用程序。
一个更好的(并且得到适当支持的)解决方案是从子域提供服务,例如https://my-new-project.webs.example.com/。这可以很容易地使用您现在使用的相同方法来完成,但使用主机名而不是路径来确定要服务的应用程序。有关解析主机名组件的示例,请参见this Server Fault answer
也就是说,如果已经解决了其他所有问题,您应该能够通过简单地修复.env中的APP_URL变量以包括子目录来解决生成的URL的问题。

APP_URL="https://webs.example.com/my-new-project"

字符串
但是,我再次强烈反对这种子目录方法。它很脆弱,很可能会被Laravel代码库的更改所破坏。

x8diyxa7

x8diyxa72#

你有没有尝试为每个子目录定制ASSET_URL?
也许你可以直接在index.php文件上设置env变量:第一个月
但最好的方法是根据子目录名使用config(['app.asset_url' => config('app.url') . $subdirectory]);动态设置

odopli94

odopli943#

您可以在Nginx配置中添加额外的位置块。

location ~ ^/([^/]+)/(images|css|js|fonts|resources)/(.*)$ {
    alias /var/www/laravel/$1/public/$2/$3;
    try_files $uri $uri/ =404;

字符串
^/([^/]+)捕获项目名称
(images|css|js|fonts|resources)捕获子目录(根据需要调整)
/(.*)$捕获所请求文件的剩余路径

相关问题