Ive faced this problem when trying to execute an action from a controller in fuelphp framework, I get an 404 message from nginx. Im able to see, for e.g. localhost/index.php or just localhost, but when I try to access to an action-controller like localhost/index.php/login/huehue I get the 404 error. Can anyone help me? this app is currently working in apache, I was facing this trouble here too but everything got fine when I executed
a2enmod rewrite
then I tried to search for equivalent config for nginx and I found this like:
location /{ try_files $uri $uri/ /index.php?$args
/index.php?q=$request_uri }
or this:
location /{
rewrite ^ /index.php?/$request_uri;}
but they didnt work for me. Ive spent several hours trying to find out the reason. This is my actual vhost file config for my site:
server {
listen 80;
listen [::]:80;
root /var/www/nginx/goutmeet;
index index.php index.html index.htm index.nginx-debian.html;
server_name goutmeet.local www.goutmeet.local;
location / {
try_files $uri $uri/ /index.php?$args /index.php?q=$request_uri #handler;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location #handler {
rewrite ^ /index.php?/$request_uri;
}
}
Id love to know how to solve this since using nginx sometimes is a better option than apache, and having this issue with fuelphp framework and not being able to use this two great tools together is awful.
Thanks in advance.
The try_files directive can have one default action. You have three! See this document for more.
Choose one:
try_files $uri $uri/ /index.php?$args;
try_files $uri $uri/ /index.php?q=$request_uri;
try_files $uri $uri/ #handler;
I do not know which is the appropriate default action for your application. They all send the request to the PHP controller, but with different sets of parameters.
The first case passes the query string; the second case passes a single parameter containing the request URI; and the third case invokes the rewrite in the named location.
I found a workaround for this problem, just add this line to config file:
error_page 404 /index.php;
I know is not the best solution but its been the only thing that has worked for me. In my opinion its acceptable since all routes should be managed by the framework and not by the web server.
Hope this helps someone.
Related
I'm trying to create a server mapping in nginx so that I can reach http://example.com/blog. I am using the following configuration
server {
listen 80;
server_name example.com;
root /home/www/blog;
index index.php index.html index.htm;
try_files $uri $uri/ /index.php$args;
location /blog/ {
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
}
If I go to http://example.com/blog it does not work, but http://example.com/blog/index.php does at least for the welcome page. Unfortunately, browsing to another sub-category doesn't work. This will lead to a URL like http://example.com/blog/food/. Weird thing is: if I remove the location /blog/ everything works fine. With it, it keeps downloading (Chrome) the index.php file.
I think the URL rewriting makes it not work (although the URL in the browser looks correct).
Can you suggest me ways to debug nginx behaviour like this? What am I missing that it works for http://example.com/food, but not for the subfolder one?
Btw: I modified pico's base_url property in the config.php to match either http://example.com or http://example.com/blog (depending on the scenarios I tried).
I've tried literally every suggestion on the web and it doesn't seem to work.
I'm using slim framework to create REST services, and I call them in this format:
http://localhost:8080/myProject/resources/myapp.php/test/
and in myapp.php I have this defined:
$app->get('/test/', ...
when I used xampp this of course worked, but when I migrated to nginx, I get the 404 error.
On the official page they say I should add this to location:
try_files $uri $uri/ /index.php?$args;
I've changed the nginx.conf accordingly:
location / {
root html;
try_files $uri $uri/ /index.php?$args;
}
I still get the 'No input file specified.' 404 error.
Any suggestions are greatly appreciated!
Kiitos Mika.... that worked perfectly.
I had several problems with my routes on production server using nginx. It seemed for me only the subfolders were not working in GET when there were variables, all were getting 404.
Adding the query_string fixed it.
Try this (from URL it appears you are not using index.php, but myapp.php):
try_files $uri $uri/ /myapp.php?$args;
The following in nginx.conf is known to work.
try_files $uri $uri/ /index.php?$query_string;
I'm quite new to Nginx so please bear with me.
I'm trying to redirect all requests from one subdirectory (store) to the root of another subdirectory (trade). See my progress below. The site in the target subdirectory (trade) is a magento site so that is what most of the current rules are for.
server {
server_name example.com *.example.com;
root /usr/share/nginx/html/example.com/public_html;
index index.php index.html index.htm;
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;
location / {
try_files $uri $uri/ /index.html;
}
location /trade/ {
index index.html index.php;
try_files $uri $uri/ #handler;
expires 30d;
}
location ~ /store {
rewrite /trade permanent;
}
location ~ ^/trade/(app|includes|lib|media/downloadable|pkginfo|report/config.xml|var)/ { internal; }
location /trade/var/export/ { internal; }
location /. { return 404; }
location #handler { rewrite / /trade/index.php; }
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The section I am using to redirect is the following:
location ~ /store {
rewrite /trade permanent;
}
This works for example.com/store but not example/store/index.php or any other uri with args. I have a feeling that the php file section at the bottom is overriding the processing. That is why I have put the ~ in front of the store location as the documentation here states this will be processed first. Does the processing stop or continue on?
I have read about nesting a php rule but I have tried this to no avail.
I would greatly appreciate any help.
ok try something like this
location ^~ /store(.*) {
return 301 $scheme://$http_host/trade$1$is_args$query_string;
}
Trying to avoid hardcoded stuff as much as possible and using return because it's prefered over permanent rewrites
Ok,
Coming back to this I can see the issue.
In Nginx when you prepend a location directive with ~ this means that you want to process regular expressions in your directive (case sensitive, ~* for case insensitive). I believe that all regex directives will process before any others but I stand to be corrected.
So when I am using:
location ~/store {
rewrite /trade permanent;
}
There is no regex there. Its is simply matching /store and redirecting to trade.
After some investigation (and polishing up on my regex, which is rubbish), I came back to it and have come up with a working solution.
location ~ ^/store/(.*) {
rewrite ^/store(.*) /trade permanent;
}
Here I am asking the directive to process the regex by entering ~ then match any url with /store/ in it.
Then, according to the docs, the rewrite syntax is:
rewrite regex replacement [ flag ]
so I am matching all urls with store in it and permanently redirecting them to the new subfolder.
Pretty easy really, embarrassingly so actually but hey, every day is a school day. I'm open to correction on all of this and hope it helps someone.
You need to ensure that your location ~ \.php$ handler does not take any URLs below the old folder. Indeed, precedence rules are clearly documented within http://nginx.org/r/location, and you can either use regular expressions, or, better yet, use prefix-based matching with the ^~ modifier to instruct that the search must stop without trying to see if that regex-based \.php$ location would match:
location ^~ /old/long/path/ { # will match /old/long/path/index.php, too
rewrite ^/old/long/path/(.*)$ /new/$1 permanent;
}
The above snippet is likely the most efficient way of doing this, but here is another way of doing the same:
location ~ /old/long/path/(.*) {
return 301 /new/$1$is_args$args;
}
Why does one example has $is_args$args and the other one doesn't? Good question! Note that location directive as well as the first parameter of the rewrite directive both operate based on the contents of the $uri variable, as opposed to $request_uri. Long story short, but $uri does not contain $args, so, in both cases, $1 will not contain any args; however, in the case of rewrite, the case is deemed so common that $args are automatically added back by nginx, unless the new string ends with a ? character, see http://nginx.org/r/rewrite.
I just migrated a site from apache to nginx, and am very pleased so far. However, the server doesn't seem to recognize a $_GET parameter.
I've read that the answer is to change the try_files directive to:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
But this isn't working for me. I suspect it's because the query string I'm using is a few directories in, with the url something like:
http://www.mysite.com/thedirectory/thefile?sortby=director
I just can't tweak the try_files directive to work in that instance, and the documentation seems sparse or obsolete.
Any ideas? If I don't get this resolved, I'm going to have to go back to Apache.
I don't know where you got that answer from,but in the context of your problem I don't see the relevance. Let's first get something clarified:
Try_files looks to match the URI with a physical location on disk and allows you to control the fallback action.
The default fallback is to throw a 404.
$query_string is not relevant to the matching process. It is used for try_files constructs where something has to be added to the query string.
There are three possible causes and remedies for your problem:
The uri matches a real file, but without the file extension, which causes the php processing location to not get triggered. In this case your statement should be:
try_files $uri $uri/ $uri.php;
This is a virtual location and the router is in index.php, like it it's with many applications, like WordPress and Magento.
In this case the try_files should be:
try_files $uri $uri/ #appname;
Without more context providing a location block for #appname is not possible.
You are not including relevant fastcgi_param directives. In this case your try_files is noise. Fix the actual problem first, by including the provided example fastcgi_param, as mentioned in the comments.
I have both PHP and Rails running on the same server.
I used to have a rewrite rule at nginx.conf
location / {
index index.php;
}
and in case of URL like /foo/bar /foo/bar/index.php was served.
But now I have also Rails (Passenger) and with this rule I can't hit rails.
How do I check if there exist index.php before and hit rails only if it does not.
Thanks.
If I understood Your question, You will need to define another location block, that "hits" rails and use try_files in current one. Something like this.
index index.html index.php # better place this outside location block
upstream thin {
unix:/tmp/thin.0.socket; # this could be any other rails server socket
unix:/tmp/thin.1.socket;
}
location / {
try_files $uri #rails;
}
location #rails {
proxy_pass http://thin;
}
These would be essential parts for such configuration, of course it lacks proxy configuration.
a more detailed example for similar application
Should try_files
server {
try_files $uri $uri/ $uri/index.php #passenger;
location #passenger {
passenger_enabled on;
rails_env development;
}
}