7

I just set up Nginx, and I'm trying to use it to host a Laravel app, but I ran into 2 problems.

  1. For GET method, I always get an extra parameter in my inputs.
    • Using PostMan (Chrome) to do my testings, I set the destination URL and my desired parameters and send the request. The output that I get, it always includes the REQUEST_URI which it shouldn't. Example output:

.

Array (
  [/api/user] => // This shouldn't be here
  [test] => test
)
  1. My parameters (the above) will NOT show for DELETE or PUT, at all, and for POST I'll only get the REQUEST_URI

Nginx vhost (Followed Setting up Laravel w/ Nginx)

server {
    server_name local.test.com;
    root /var/www/test/public;

    location / {
        index index.php index.html index.htm;
    }

    # serve static files directly
    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
        access_log off;
        expires max;
    }

    # removes trailing slashes (prevents SEO duplicate content issues)
    if (!-d $request_filename) {
        rewrite ^/(.+)/$ /$1 permanent;
    }

    # unless the request is for a valid file (image, js, css, etc.), send to bootstrap
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php?/$1 last;
        break;
    }

    # catch all
    error_page 404 /index.php;

    # The PHP Inclusion Block
    # include /etc/nginx/includes/php;
    location ~ \..*/.*\.php$ {
        # I'm pretty sure this stops people trying to traverse your site to get to other PHP files
        return 403;
    }

    #location ~ \.php$ {
    location ~ \.php(.*)$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
    }

# Deny Any Access to .htaccess Files That May Be Present (not usually in issue in Laravel)
# include /etc/nginx/includes/deny_htaccess;
location ~ /\.ht
{
    deny all;
}

    error_log  /var/www/logs/test-error.log;
}

fastcgi_params :

fastcgi_param   QUERY_STRING            $query_string;
fastcgi_param   REQUEST_METHOD          $request_method;
fastcgi_param   CONTENT_TYPE            $content_type;
fastcgi_param   CONTENT_LENGTH          $content_length;

fastcgi_param   SCRIPT_FILENAME         $request_filename;
fastcgi_param   SCRIPT_NAME             $fastcgi_script_name;
fastcgi_param   REQUEST_URI             $request_uri;
fastcgi_param   DOCUMENT_URI            $document_uri;
fastcgi_param   DOCUMENT_ROOT           $document_root;
fastcgi_param   SERVER_PROTOCOL         $server_protocol;

fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
fastcgi_param   SERVER_SOFTWARE         nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR             $remote_addr;
fastcgi_param   REMOTE_PORT             $remote_port;
fastcgi_param   SERVER_ADDR             $server_addr;
fastcgi_param   SERVER_PORT             $server_port;
fastcgi_param   SERVER_NAME             $server_name;

#fastcgi_param  HTTPS                   $https;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS         200;

fastcgi_connect_timeout                 60;
fastcgi_send_timeout                    180;
fastcgi_read_timeout                    180;
fastcgi_buffer_size                     128k;
fastcgi_buffers 4                       256k;
fastcgi_busy_buffers_size               256k;
fastcgi_temp_file_write_size            256k;
fastcgi_intercept_errors                on;

nginx.conf Has only 1 thing changed, and that is keepalive_timeout from 65 to 15

So I absolutely have no clue, where all this thing goes wrong. But I do have to mention, that on another 2 environments that I have (One with Lighttpd and the other with Apache2) the app works perfectly.

From what I've noticed, its all reduced to the following code:

# unless the request is for a valid file (image, js, css, etc.), send to bootstrap
if (!-e $request_filename) {
    rewrite ^/(.*)$ /index.php?/$1 last;
    break;
}

Which will make the GET work... and add the additional parameter

Community
  • 1
  • 1
Alex
  • 7,538
  • 23
  • 84
  • 152

6 Answers6

6

It is best to avoid unneccessary rewrites in your nginx configuration (See Nginx Pitfalls), one in particular is the one responsible for passing the request to the Laravel front controller:

All you need for Laravel is:

location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ index.php?$query_string;
}

First that tries to access a file directly, then a directory, and if neither exists it passes the request to index.php. $query_string is important to pass along as that will contain the $_GET data that otherwise gets lost.

And here is my own FastCGI configuration piece:

location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME    $document_root/$fastcgi_script_name;
    include        fastcgi_params;
}

As for unexpected input, it could be the way your current rewrite works, but to say for sure, what are you outputting?

Gargron
  • 808
  • 7
  • 10
  • `dd(Input::all());` it's what I'm outputting... and no, it's not `Input::all()` that set the undesired parameter – Alex Feb 13 '13 at 13:18
  • Alright. Try the suggested configuration and tell me if it does it. – Gargron Feb 13 '13 at 13:23
  • Just tried it, by commenting the `if`s containing a rewrite rule, and now I get no output of my parameters at all – Alex Feb 13 '13 at 13:24
  • Thanks for the help, but your conf is no of a help to me. – Alex Feb 15 '13 at 14:00
  • Have you replaced the part that you describe as "its all reduced to the following code" with my suggested code? I'm just not sure if that was clear – Gargron Feb 15 '13 at 22:17
  • Your suggested code regards anything ending in `.php` and accesing document root. even though, I do have tried your sugested code,and as mentioned, doesn't work – Alex Feb 17 '13 at 00:04
2

This works for me:

location / {
    index   index.php;
    try_files $uri $uri/ /index.php?q=$uri&$args;
}

location ~ \.php$ {

    include     fastcgi_params;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;

    fastcgi_split_path_info                 ^(.+\.php)(/.+)$;
    fastcgi_param PATH_INFO                 $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED           $document_root$fastcgi_path_info;
    fastcgi_param SCRIPT_FILENAME           $document_root$fastcgi_script_name;

}
Jason Prawn
  • 1,003
  • 11
  • 20
1

From your config:

rewrite ^/(.*)$ /index.php?/$1 last;

here you have a redirect to /index.php?/$1 (e.g. /index.php?/some/path).

fastcgi_split_path_info ^(.+\.php)(/.+)$;

and here you spilt path by ^(.+\.php)(/.+)$ regex (e.g. /index.php/some/path).

Have you noticed the difference?

VBart
  • 14,714
  • 4
  • 45
  • 49
  • I actually removed the `fastcgi_spli` part and now I get the parameters, but I still have the `[/api/user] => // This shouldn't be here` problem – Alex Feb 22 '13 at 14:23
  • I followed http://stackoverflow.com/questions/8856664/setting-up-laravel-w-nginx and just addapted a little bit – Alex Feb 22 '13 at 14:23
  • But you have configured nginx that way. Your `rewrite ^/(.*)$ /index.php?/$1 last;` is responsible for adding the path to the parameters. – VBart Feb 22 '13 at 15:14
  • please forgive my ignorance, but how else should I do it? That's what all the result I've seen on Google (searching `laravel nginx`) suggests. – Alex Feb 22 '13 at 15:32
  • You should do it the way that you want. Nginx has a very flexible configuration language, that allows to configure any desired behaviour. I suggest you to read the documentation and write your configuration from scratch. Useful links: http://nginx.org/en/docs/ and http://wiki.nginx.org/Pitfalls – VBart Feb 22 '13 at 16:59
  • Sorry, I cannot help because even don't know what `laravel` is, but it is clear to me that the example of configuration you have found is poorly written, probably by the person with a little knowledge of nginx. – VBart Feb 22 '13 at 17:10
1

I was facing similar issue and I fixed it with following configs:

server {
    listen 80;
    server_name subdomain.domain.com;
    root /var/www/dir/public;

    charset utf-8;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/registration.app-error.log error;
    error_page 404 /index.php;
    sendfile off;

    # Point index to the Laravel front controller.
    index index.php;

    location / {
       # try_files $uri $uri/ index.php?$query_string;
        try_files $uri $uri/ /index.php?&$args;
    }

    location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        #
        #       # With php7.0-cgi alone:
        #       fastcgi_pass 127.0.0.1:9000;
        #       # With php7.0-fpm:
                fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    }



    location ~ /\.ht {
        #deny all;
    }
}
Ravi Sharma
  • 1,162
  • 3
  • 11
  • 20
  • The only one that worked for me, critical bit was `index.php?&$args;`, running Laravel 4.2 and php7.0 on debian 9.6 – SteB Oct 03 '19 at 14:47
0

This is a configuration that works for me with NGINX and Laravel

server {

    listen  80;
    server_name sub.domain.com;
    set $root_path '/var/www/html/application_name/public';
    root $root_path;

    index index.php index.html index.htm;

    try_files $uri $uri/ @rewrite;

    location @rewrite {
        rewrite ^/(.*)$ /index.php?_url=/$1;
    }

    location ~ \.php {

        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index /index.php;

        include /etc/nginx/fastcgi_params;

        fastcgi_split_path_info       ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO       $fastcgi_path_info;
        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
        root $root_path;
    }

    location ~ /\.ht {
        deny all;
    }

}
ajtrichards
  • 29,723
  • 13
  • 94
  • 101
0

Same issue fixed as described in NGINX documentation: Embedded Variables: $is_args

Add this in NGINX location:

location / {
    try_files $uri $uri/ /index.php$is_args$args;
}
Ed Ward
  • 1
  • 2