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.
Related
I'm working on a php web app and want the URLs to be mapped to a folder on the server like this:
https://app.com/clientOne/... --> /client/...
https://app.com/clientTwo/... --> /client/...
etc
And all folders following clientOne and clientTwo in the URL exist on my server under client E.g. clientOne/admin/ gets mapped to client/admin/, and clientTwo/app/ gets mapped to client/app/. I want all clients to share the same application, and the application will determine the client from the URL. (I don't want to deal with subdomains right now.)
My nginx config works only when directories are in the URL. When I reference specific php files, I get a 404:
https://app.com/clientOne/admin/ (works)
https://app.com/clientOne/admin/index.php (returns 404)
I've searched and haven't found anyone with this particular issue. I think I know what needs to be done, but everything I have tried has not worked. Here is my standard nginx config:
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
and this:
location ~ ^/(clientOne|clientTwo)/(.*)$ {
try_files $uri $uri/ /client/$2?$query_string;
}
I'm thinking I need to update the php location block to address my issue and then I won't need the second location block, but everything I have tried has not worked. I tried changing the try_files in the php location block to this, but it didn't work:
try_files $uri /client/ =404;
Does anyone know how to do this? Thanks
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
}
I've looked at dozens of other questions and references on the web - and by all my calculations, my setup should work, but it doesn't.
I have nginx installation with php-fpm. If I try to access a .php file, it runs correctly and I get the correct results. I got this in my config file:
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Now, I want to setup my web app so that /somedir/file automatically executes /somdir/file.php while still displaying /somdir/file in the browser's address bar. So I modified my config to contain the following:
location / {
try_files $uri $uri/ $uri.php?query_string
}
This kind of works, that is, the server does access the .php file. Yet, instead of executing it using the existing location ~ \.php$ block above, it simply spits the php source code as the download into the browser. If I append the .php manually to the requested URL, then the php is executed.
It feels as if once the server matches try_files to $uri.php, it then does not do another pass at locations to see that what it needs to do with the php files. I tried putting the php block above and below the location /, but it makes no difference.
How can I get the php to be executed?
You want file.php to be treated as an index file, so that domain.com/dir/file.php works on domain.com/dir/ ?
Why not just rename it to index.php?
You can do this by adding this param on your location block:
index index.html file.php index.php;
If not, you might want to look into writing a rewrite rule for nginx to map domain.com/dir/ to domain.com/dir/file.php (but you have to do it for each dir that you need it to work)
This question could also be: "How to modify an NGiNX variable with a RegEx?",
or: "Can RegEx backreference have gaps?"
Either of those would resolve the problem I'm having. Perhaps a really simple solution exists, and after digging the web for few hours, it's time to ask for help.
Here's the scenario:
There's a part of the request URI that is going to be present always (for a sort of a gimmicky domain name + URI combination :-). I enforce the presence of that always-present URI path component, which follows immediately after the domain name, like so:
http://somedomain.com/basepart/rest/of/the/path?q=123
In the above example the "/basepart" represents the always-present URI component.
So far so good. The problem arises when I want the base file path to be /var/www/somedomain.com/htdocs/ without the basepart, and php5_fpm proxy is used. I obviously set:
location /basepart {
alias /var/www/somedomain.com/htdocs;
try_files $uri $uri/ /index.php?$args;
}
But since the dynamic files are in PHP, I need to either use fastcgi_split_path_info or $request_uri to build/pass the SCRIPT_FILENAME to php5_fpm. How do I do that? How do I remove the /basepart from $fastcgi_script_name, or from $request_uri, as otherwise PHP will look for the file in /var/www/somedomain.com/htdocs/basepart?
I've considered named backreferences, or "collecting" or "fragmented" backreferences (which I don't think exist in regex) so that I could capture the segment in $fastcgi_script_name before and after the basepart when fastcgi_split_path_info assignment happens, but haven't got them to work. Dayo writes earlier at SO: »Nginx is a webserver and not a scripting application.», and suggests use of Lua for more complex scripting. But I have a feeling I may be overlooking some really simple, facepalm-worthy solution :-].
Any thoughts, anyone?
If someone else stumbles on this question, after some brainstorming i came up with stupidly obvious solution:
root /app/frontend/web/;
location /api/ {
alias /app/backend/web/;
index index.php index.html;
# Double /api/ because "that's how nginx alias and try_files works together"
try_files $uri /api//api/index.php$is_args$args;
location ~ ^/api(/.*\.php(?:\?.*)?)$ {
try_files $uri /api//api/index.php$is_args$args;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$1;
...
}
}
I.e. using regex capturing group.
With this rules requests will be routed following way:
/index.html -> /app/frontend/web/index.html
/test/test.php -> /app/frontend/web/test/test.php as plaintext
/api/<somepath> -> /app/backend/web/<somepath> (proxied to FPM if .php) if it exists, otherwise /app/backend/web/index.php
The alias directive is fine for static websites but not so useful when PHP is involved. My preferred solution is to internally rewrite the URI without the /basepart and then use root rather than alias.
The problem is that many PHP scripts use $request_uri in order to process the request, which is frozen with the /basepart intact. However, we can specify any value we choose for REQUEST_URI and construct a more appropriate value from $uri or captures. In the example below, I preserve the value of $uri after the first rewrite so that it can be used to pass our modified request URI to the PHP script.
root /var/www/somedomain.com/htdocs;
location ^~ /basepart {
rewrite ^/basepart/(.*)$ /$1 last;
rewrite ^ / last;
}
location / {
internal;
try_files $uri #index;
}
location #index {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param REQUEST_URI $uri;
...
}
location ~ \.php$ {
internal;
try_files $uri #index;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param REQUEST_URI $uri;
...
}
The fastcgi code block is duplicated across two locations. If it becomes unwieldy, the common code can be placed into a separate include file.
Locations are made private by using the internal directive keeping the /basepart mandatory for external access.
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).