Nginx rewrite part of URL with GeoIP variables - variables

I have a URL like this:
https://example.com/home/anything/whatever
I need to rewrite this URL and replace the /home/ part with the variables from GeoIP and http-request-language:
https://example.com/ch/de/anything/whatever
I have a location match on the root that already does this and this works:
location = / {
rewrite ^ $location_uri$lang permanent;
}
Now i need this for the case above and i used:
location ~ /home/(.*) {
rewrite ^/home/(.*)$ /$location_uri$lang/$1/ permanent;
}
The original reqeust part of the URL ($1) is not added to the end of the URL:
https://example.com/ch/de//
If I remove the 2 variables $location_uri and $lang and replace them with a fix text (/ch/de) it works.
Is it possible to have these variables in the rewrite?

I managed to do it with 2 rewrites:
location ~ ^/home(.*)$ {
rewrite ^/home(.*)$ /$location_uri$lang$request_uri permanent;
}
location ~ ^/ch/de/home(.*)$ {
rewrite ^(.*)/home(.*)$ $1$2 permanent;
}
First I rewrite /home/ with the GeoIP vars and add the whole request URI including /home/.
Then I make another location-match on the target-URI and remove the /home part.

Related

Redirect, Hide Folder Name and enabling URL access with multiple subdirectory [duplicate]

I have a URL that looks like:
url.com/picture.php?id=51
How would I go about converting that URL to:
picture.php/Some-text-goes-here/51
I think WordPress does the same.
How do I go about making friendly URLs in PHP?
You can essentially do this 2 ways:
The .htaccess route with mod_rewrite
Add a file called .htaccess in your root folder, and add something like this:
RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=$1
This will tell Apache to enable mod_rewrite for this folder, and if it gets asked a URL matching the regular expression it rewrites it internally to what you want, without the end user seeing it. Easy, but inflexible, so if you need more power:
The PHP route
Put the following in your .htaccess instead: (note the leading slash)
FallbackResource /index.php
This will tell it to run your index.php for all files it cannot normally find in your site. In there you can then for example:
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
if(empty($elements[0])) { // No path elements means home
ShowHomepage();
} else switch(array_shift($elements)) // Pop off first item and switch
{
case 'Some-text-goes-here':
ShowPicture($elements); // passes rest of parameters to internal function
break;
case 'more':
...
default:
header('HTTP/1.1 404 Not Found');
Show404Error();
}
This is how big sites and CMS-systems do it, because it allows far more flexibility in parsing URLs, config and database dependent URLs etc. For sporadic usage the hardcoded rewrite rules in .htaccess will do fine though.
If you only want to change the route for picture.php then adding rewrite rule in .htaccess will serve your needs, but, if you want the URL rewriting as in Wordpress then PHP is the way. Here is simple example to begin with.
Folder structure
There are two files that are needed in the root folder, .htaccess and index.php, and it would be good to place the rest of the .php files in separate folder, like inc/.
root/
inc/
.htaccess
index.php
.htaccess
RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
This file has four directives:
RewriteEngine - enable the rewriting engine
RewriteRule - deny access to all files in inc/ folder, redirect any call to that folder to index.php
RewriteCond - allow direct access to all other files ( like images, css or scripts )
RewriteRule - redirect anything else to index.php
index.php
Because everything is now redirected to index.php, there will be determined if the url is correct, all parameters are present, and if the type of parameters are correct.
To test the url we need to have a set of rules, and the best tool for that is a regular expression. By using regular expressions we will kill two flies with one blow. Url, to pass this test must have all the required parameters that are tested on allowed characters. Here are some examples of rules.
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
Next is to prepare the request uri.
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
Now that we have the request uri, the final step is to test uri on regular expression rules.
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
}
}
Successful match will, since we use named subpatterns in regex, fill the $params array almost the same as PHP fills the $_GET array. However, when using a dynamic url, $_GET array is populated without any checks of the parameters.
/picture/some+text/51
Array
(
[0] => /picture/some text/51
[text] => some text
[1] => some text
[id] => 51
[2] => 51
)
picture.php?text=some+text&id=51
Array
(
[text] => some text
[id] => 51
)
These few lines of code and a basic knowing of regular expressions is enough to start building a solid routing system.
Complete source
define( 'INCLUDE_DIR', dirname( __FILE__ ) . '/inc/' );
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
include( INCLUDE_DIR . $action . '.php' );
// exit to avoid the 404 message
exit();
}
}
// nothing is found so handle the 404 error
include( INCLUDE_DIR . '404.php' );
this is an .htaccess file that forward almost all to index.php
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !-l
RewriteCond %{REQUEST_FILENAME} !\.(ico|css|png|jpg|gif|js)$ [NC]
# otherwise forward it to index.php
RewriteRule . index.php
then is up to you parse $_SERVER["REQUEST_URI"] and route to picture.php or whatever
PHP is not what you are looking for, check out mod_rewrite
Although already answered, and author's intent is to create a front controller type app but I am posting literal rule for problem asked. if someone having the problem for same.
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]
Above should work for url picture.php/Some-text-goes-here/51. without using a index.php as a redirect app.

Htaccess to Nginx Rewrite Conversion

htaccess to nginx rewrite conversion help
RewriteEngine On
RewriteCond %{REQUEST_URI} apiv01
RewriteRule ^(.*)$ api.php?params=$1 [NC]
--- edit
I want when access uri GET http://localhost/hospital_project/apiv01/listHospital/3211 can display
{"header":{"code":"401","message":"wrong token"}}
I've used the configuration of anilcetin like this:
location /hospital_project {
if ($uri ~ "apiv01"){
set $rule_0 1$rule_0;
}
if ($rule_0 = "1"){
rewrite ^/(.*)$ /hospital_project/api.php?params=$1;
}
}
Also i've used the configuration of https://winginx.com/en/htaccess like this:
location / {
rewrite apiv01 /hospital_project/api.php?params=$1;
}
But when i access http://localhost/hospital_project/apiv01/listHospital/3211 the output is equal to http://localhost/hospital_project/apiv01 (no effect)
--- edit
Normal if i using http://localhost/hospital_project/api.php?params=apiv01/listHospital/3211

nginx rewrite rules /about to index.html?page=about

I had some htaccess rules for my server and now I am using nginx instead of apache.
I tried to translate those rules and I came up with:
location /about {
rewrite ^/about\.html$ /index.html?page=about;
}
location /archive {
rewrite ^/archive\.html$ /index.html?page=archiveindex;
}
location /sonic1 {
rewrite ^/sonic1/index\.html$ /index.html?page=archivegame&game=s1;
}
location /sonic2 {
rewrite ^/sonic2/index\.html$ /index.html?page=archivegame&game=s2;
}
location /sonic3 {
rewrite ^/sonic3/index\.html$ /index.html?page=archivegame&game=s3;
}
For some reason these rules do not work
Long story short when someone acceses my website and writes:
/about or /about.html i want it to be redirected to this page /index.html?page=about
These applies to all the other rules, if the about one will work I will figure out how to do the rest of them.
Any help would be really appreciated!
Original apache rules:
RewriteRule ^about\.html$ index.html?page=about
RewriteRule ^archive\.html$ index.html?page=archiveindex
RewriteRule ^sonic1/index\.html$ index.html?page=archivegame&game=s1
RewriteRule ^sonic2/index\.html$ index.html?page=archivegame&game=s2
RewriteRule ^sonic3/index\.html$ index.html?page=archivegame&game=s3
RewriteRule ^sonicandknuckles/index\.html$ index.html?page=archivegame&game=sk
As promised, I am publishing the nginx rules that I came up in the end for my previous apache rules (htaccess).
location = /about {
rewrite ^/about$ /index.html?page=about permanent;
}
location = /archive {
rewrite ^/archive$ /index.html?page=archiveindex permanent;
}
location = /sonic1 {
rewrite ^/sonic1$ /index.html?page=archivegame&game=s1 permanent;
}
location = /sonic2 {
rewrite ^/sonic2$ /index.html?page=archivegame&game=s2 permanent;
}
location = /sonic3 {
rewrite ^/sonic3$ /index.html?page=archivegame&game=s3 permanent;
}
location = /sonicandknuckles {
rewrite ^/sonicandknuckles$ /index.html?page=archivegame&game=sk permanent;
}

Nginx: how to do rewrite?

My website have three different pages:
www.abc.com/
www.abc.com/node
www.abc.com/memeber
If I type www.abc.com in the browser,it goes to www.abc.com/, how can I change it to www.abc.com/node when I type www.abc.com and keep the www.abc.com/memeber normal as usual?
Just adding a small note, use return instead of rewrite for redirects, check nginx pitfalls
location = / {
return 301 $scheme://$server_name/node
}
location / {
# normal location handling, using try_files for example
}
Following worked for me provided I was only serving static files.
server {
listen 80;
server_name www.abc.com;
root /var/www/abc;
if ($request_uri = '/') {
rewrite ^ /node break;
}
}
location = / {
rewrite ^ /node;
}

Need help translating this htaccess rewrite rule to Nginx

Hi – I've been struggling with this for days. It seems simple but I just can't get it done.
I have a site developed in CakePHP. There's a script that responds to /css/profiles/g/whatever.css ("whatever" being whatever, it is actually a parameter that gets passed to the action), it echoes a generated CSS and saves it to /css/profiles/whatever.css.
I have a rule in Apache that takes requests to /css/profiles/whatever.css and, if it doesn't exist, rewrites the request to /css/profiles/g/whatever.css without redirecting, so the client never notices it was responded by a script and that the file didn't exist.
This is what I have in Apache:
# Profile CSS rules
RewriteCond %{REQUEST_URI} ^/css/profiles/
RewriteCond %{REQUEST_URI} !/css/profiles/g/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^css/profiles/(.*)$ /css/profiles/g/$1 [L]
# CakePHP's default rules
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
Now I'm moving the site to a server with Nginx, and so far I've got this:
# Profile CSS rules
location ~ ^/css/profiles/(?!g/)(.*)$ {
   if (!-f $request_filename) {
     rewrite ^/css/profiles/(.*)$ /css/profiles/g/$1 last;
     break;
   }
 }
# CakePHP's default rules
location / {
    try_files $uri $uri/ /index.php?$uri&$args;
}
The conditions seem to be working, because if I go to /css/profiles/whatever.css and print out PHP's $_SERVER variable it gives me
[QUERY_STRING] => /css/profiles/g/whatever.css&
Notice the &. It means it got to the try_files part and added the $uri to the query string, and it has the correct $uri.
But...
[REQUEST_URI] => /css/profiles/whatever.css
That's the glitch. It seems it's not really changing the $request_uri which is what CakePHP needs to control what controller attends what.
Update: The REQUEST_URI value is right... the issue here is that Cake looks for the value of different server variables to decide which controller will respond. In this order: $_SERVER['PATH_INFO'], $_SERVER['REQUEST_URI'], a combination of $_SERVER['PHP_SELF'] and $_SERVER['SCRIPT_NAME'] and finally $_SERVER['HTTP_X_REWRITE_URL']. That's why it's failing.
Any help will be appreciated.
Thanks.
Note: I posted this question on Serverfult yesterday because I think it fits better there but didn't get an answer, that's why I'm posting it here too.
So I finally got it working:
location ~ ^/css/profiles/(?!g/)(.*)$ {
  set $new_uri /css/profiles/g/$1;
  if (!-f $request_filename) {
    rewrite ^/css/profiles/(.*)$ /css/profiles/g/$1 last;
}
}
...and at the end:
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
... some other stuff were here related to fastcgi
fastcgi_param PATH_INFO $new_uri; # <--- I added this
}