PHP and Rails for NginX configuration - php

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;
}
}

Related

Pass entire URL to $_GET variable in PHP built-in server

I'm running a PHP built-in server with
php -S 127.0.0.1:80 index.php
I want to pass the entire URI string to a field called "url" in the $_GET array. When I enter http://localhost/thisIsAURLString, I want var_dump($_GET); to return array(1) { ["url"]=> string(16) "thisIsAURLString" }
Is there some way to do this with the PHP built in server?
The web application is usually run in a production environment with nginx, and with a configuration file as shown below. This configuration passes the URL to a field "url" in the $_GET variable, but I want to do something similar with the PHP built-in server.
server {
listen 5001 default_server;
listen [::]:5001 default_server ipv6only=on;
root [myRoot];
index index.php index.html index.htm;
server_name [myServerName];
location /uploads {
try_files $uri $uri/ =404;
}
location /assets {
try_files $uri $uri/ =404;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
rewrite ^/(.*)$ /index.php?url=$1 last;
}
location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php/php7.0-fpm-01.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
EDIT (some context) :
The context is that I'm a TA with many students. The web application in question is currently in a production environment with nginx and runs smoothly, but all of my ~100 students need to download and deploy the very same web application locally on their own computers. I can't alter the PHP code. The deployment should be as simple and smooth as possible, and if they can do this with some easily reproducible php command, that would be ideal.
You could bootstrap your application with this script. Save this snippet to a file, and set it as your entry point in whatever web server software you're using. It will produce the results you're asking for.
<?php
$root=__dir__;
$uri=parse_url($_SERVER['REQUEST_URI'])['path'];
$page=trim($uri,'/');
if (file_exists("$root/$page") && is_file("$root/$page")) {
return false; // serve the requested resource as-is.
exit;
}
$_GET['url']=$page;
require_once 'index.php';
?>
I'm not sure what you're asking but let me start with:
What "field" are you talking about?
Are you trying to print the url where?
What do you mean by "PHP built-in server"?
$_GET is a superglobal variable, array type, that's populated by PHP (a server-side scripting language). All you gotta do is call it (e.g. $_GET['link'] whereas link could be anything you'd want) or something similar (please check http://php.net/manual/en/reserved.variables.get.php). You can use it in any php file.
You may want to look at the global $_SERVER array. This contains the HTTP_HOST, QUERY_STRING, REQUEST_SCHEME and REQUEST_URI array keys. These can be used to assemble a full url. Try a var_dump($_SERVER); to see all the key => values.
Is there a particular reason you need to use the $_GET global array?
Hope this helps.

Full-stack Nginx reverse proxying and PHP index

I'm trying to setup a full-stack Nginx reverse proxying server (as title says, obviously), and I'm struggling a bit when it comes to code interpretation with PHP-FPM.
Here is the so called front-end part of the proxying process (which isn't used to directly serve files, but rather to redirect the client towards the back-end servers) :
server {
listen xxx.xxx.xxx.xxx:80;
server_name localhost;
# logs...
# Here begins the reverse-proxying
# Test 2nd backend server
location /test {
proxy_pass http://127.0.0.1:82/;
}
# default main site (has to be at the end since location checks file hierarchy)
location / {
proxy_pass http://127.0.0.1:81/;
}
And then, here are my two reversed server blocks.
The first one is the main site, which should be served by default by accessing domain.com :
server {
listen 127.0.0.1:81;
server_name main;
# logs...
root /var/www/main;
gzip on;
gzip_types "*";
expires 10m;
location / {
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php-fpm.socket;
include /etc/nginx/fastcgi.conf;
}
}
And here is the second "test" one, which is should access when trying domain.com/test :
server {
listen 127.0.0.1:82;
server_name test;
root /var/www/test;
gzip on;
gzip_types "*";
expires 10m;
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php-fpm.socket;
include /etc/nginx/fastcgi.conf;
}
}
Doing so using reverse proxying would allow me to actually only use one port, and the most important, it hides which and how much virtual servers are actually running here.
So, what's the problem ?
Well, it's more about HOW are PHP and indexes managed by nginx reverse proxying than about reverse proxying itself.
When I'm using index.html files in both :81 and :82 servers, it works fine, the index directive works perfectly, and the server returns /var/www/main/index.html when accessing domain.com, and /var/www/test/index.html when accessing domain.com/test.
However, the problem happens when I'm using index.php files. In this case, only using the URLs up there leaves me with a 404 error in both cases. I need to explicitely specify index.php in the URL, eg. domain.com/test/index.php to make it work, which I don't want to have to.
I haven't found any thread or documentation dealing with such a specific case, and that's why I'm coming here to ask if anyone has more informations on indexes behavior with PHP ?
Thanks by advance for your answer(s), and I'll gladly take anything you have at this point since I've been struggling for quite a long time with this problem.
You need to set this to load index.php files by default:
location / {
index index.php index.html index.htm;
// ...other configurations
}

How to configure nginx rewrite rules for fuelphp framework?

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.

Nameserver always at the top in url bar in nginx (with no redirect)

My app has only two pages presented to the user, both in mobile or desktop. Firstly a login page and after the app page itself. When accessing www.myapp.com the user is firstly indexed towards the login page and if he is logged in he is then php redirected to the app page. Here is my server schema:
root
index.php (login page)
mobile/mobile.php
profile/profile.php
What I'd like is to avoid the user having www.myapp.com/mobile/mobile.php,www.myapp.com/profile/profile.php but instead www.myapp.com and www.myapp.com/desktop or www.myapp.com/mobile
so he can also switch between layouts. Unfortunately this is throwing a 404 error in my servers:
nginx default file:
location ~ /mobile/mobile.php$ {
rewrite $host/mobile break;
}
location ~ /index.php$ {
rewrite $host break;
}
location ~ profile/profile.php$ {
rewrite $host/desktop break;
}
Should it be something like this or should it be another complete way? I'd like to do this in my server, not in the user device... Thank you very much for your help...
The following was tested on my development server:
server {
listen 80;
root /usr/local/www/test;
index index.php;
location = /mobile { rewrite ^ /mobile/; }
location = /desktop { rewrite ^ /profile/; }
location / {
try_files $uri $uri/ =404;
}
location /mobile {
index mobile.php;
try_files $uri $uri/ =404;
}
location /profile {
index profile.php;
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php;
}
}
It uses index and try_files to find your scripts and then internally redirect to the fastcgi handler. I have upstream php { ... } defined elsewhere. You might employ rewrite rules and the internal directive to enforce the scheme of no php script on the URL bar.
The mobile rewrite is simply to maintain consistency with the desktop rewrite, so that the client doesn't see a trailing /.
This is just one example of a multitude of solutions. Typically, there are ancillary files (css, js, images) with their URLs that also need to be accommodated.

Nginx redirect all requests from subdirectory to another subdirectory root

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.

Categories