How to serve specific static files with nginx? - nginx

I have queries like /api/lang?lang=en which I want to serve with nginx as /server/i18n-angular/en.json. How can I do that?
I have the following directory structure:
/public/
/server/i18n-angular/en.json
I have the following configuration, but nginx says it is wrong to use index directive at that point.
server {
root /public
...
location /api/lang {
if ($args ~* "\?lang=(.+)") {
set $language $1;
index ../server/i18n-angular/$language.json;
}
}
}
What directive should I use instead of index?

location /api/lang {
alias /server/i18n-angular;
rewrite ^ /$arg_lang.json;
}

"index" specifies index file for displaying a folder, so it's not what you need.
You require "rewrite" instead:
location /api/lang {
alias /server/i18n-angular;
if ($args ~* "\?lang=(.+)") {
set $language $1;
rewrite ^/(.*)$ /$language.json;
}
}

Related

NginX redirect /service to /service/

I have two servicesr accessible via NginX. The web server configuration looks like this:
location /service1/ {
# process php files
}
location /service2/ {
proxy_pass http://127.0.0.1:9999/;
}
However, if one clicks on https://example.com/service1 (or 2) he gets a 404 error. There is no folder called "service1" (or 2) in the website root.
I would like links to "https://example.com/service1" to point to "https://example.com/service1/" (with trailing slash), possibly without specyfing a redirect for every service I have, i.e
location = /service1 {
return 301 https://$host/service1/;
}
location /service1/ {
# process php files
}
location = /service2 {
return 301 https://$host/service2/;
}
location /service2/ {
proxy_pass http://127.0.0.1:9999/;
}
I have already tried try_files $uri $uri/ =404;, but it seems to only work for real files and folders in the website root, no "virtual" subdirectories.
I am avoiding configurations like location /service { ... } because they seem more vulnerable.
Inside your location = blocks you need to generate an internal redirect to $uri/. You can achieve this using try_files or rewrite...last.
For example:
location = /service1 {
try_files nonexistent $uri/$is_args$args;
}
Notice that the internal redirection must be the last parameter. See this document for details.
Or:
location = /service1 {
rewrite ^(.*)$ $1/ last;
}
See this document for details.

Static files getting 404 with nginx proxy

I have configured nginx to serve static page as below.
location /home {
alias /home/username/files/home;
try_files $uri /home/index.html;
}
Only index.html loads on http://example.com/home. All other css, js and image files are getting 404 as request is still going for http://example.com/css/style.css instead of http://example.com/home/css/style.css. Is there any way I can configure /home prefix to all the static file without manually adding to all static files?
You can try to use variable root depending on HTTP Referer header (although it is a dirty hack):
map $http_referer $root {
~example\.com/home/ /home/username/files/home;
default <your default root here>;
}
server {
...
root $root;
location /home {
root /home/username/files;
try_files $uri /home/index.html;
}
}
Note that if any of your web pages under /home/ have a links to the main site, those links won't work correctly because of example.com/home/... HTTP Referer header value.
Why root /home/username/files; instead of alias /home/username/files/home;, you ask? Because as nginx documentation states:
When location matches the last part of the directive’s value:
location /images/ {
alias /data/w3/images/;
}
it is better to use the root directive instead:
location /images/ {
root /data/w3;
}

NGINX rewrite args without an IF?

I would like to rewrite legacy links using a query parameter type of URL to a new style of URL.
Ex.
example.com/page?id=1 -> example.com/page/1
example.com/otherpage?id=1 -> example.com/otherpage/1
Currently I have the following configuration using the evil if.
if ($args ~* "id=(.*)") {
set $w1 $1;
rewrite .* $scheme://$host/page/$w1? permanent;
}
Note: I am using CloudFront, and relying on the host header above.
If the above is in a server block, with no other location block - would this qualify as a non-evil use of if in NGINX config? Also, the above only supported /page/. Any better ideas for making that portion work for otherpage and other pages?
I have seen a few other ideas discussing using a map, but I'm not quite sure how to bring it all together? I was thinking something along the lines of:
map $args_id ?? {
default ?
??
}
...
server {
...
???
}
UPDATE:
Based on the Answer from #Ivan, this was my final solution:
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm;
# Handle legacy requests
if ($args ~* "id=(.*)") {
set $w1 $1;
rewrite ^ $scheme://$host$uri/$w1? permanent;
}
}
Your if construction isn't evil. You can use something like
rewrite ^ $scheme://$host$uri/$w1? permanent;
for any page. More complex example if you want to process both example.com/page?id=1 and example.com/page/?id=1:
map $uri $maybe_slash {
~/$ "";
default "/";
}
...
server {
...
rewrite ^ $scheme://$host$uri$maybe_slash$w1? permanent;
...
}

convert url get parameters to url segment in nginx

I have this URL https://example.com/user?param1=value1&param2=value2&param3=value3
and have it to go to https://example.com/user/value1/value2/value3 on the Nginx server.
Just FYI it is WordPress site and I have added the following rule in the Nginx config file.
location ~ /user/ {
if ($args ~* "^param1=(\d+)&param3=(\d+)&param3=(\d+)") {
set $param1 $1;
set $param2 $1;
set $param3 $1;
set $args '';
rewrite ^.*$ /user/$param1/$param2/$param3 permanent;
}
}
Your solution has two errors, 1) the location does not match /user, and 2) the rewrite is also appending the original arguments.
This could be fixed by using an exact match location and a trailing ? on the rewrite. For example:
location = /user {
...
rewrite ^ /user/$param1/$param2/$param3? permanent;
}
However, the map statement is a cleaner and extensible solution, for example:
map $request_uri $redirect {
default 0;
~*^/user?param1=(?<p1>\d+)&param2=(?<p2>\d+)&param3=(?<p3>\d+)$ /user/$p1/$p2/$p3;
}
server {
...
if ($redirect) { return 301 $redirect; }
...
}
See this document for details.

Nginx rewrite location path

Is there a way I can add a rewrite which will dynamically set the location/path of the file?
The following is from the nginx config:
server {
root /media;
server_name media.domain.com;
location / {
autoindex off;
}
I have images with names like "e9m7L4_1.jpg" that are stored in a directory according to the first 6 letters/numbers of the filename, for example:
e9m7L4_1.jpg (stored in)-> e/9/m/7/L/4/e9m7L4_1.jpg
km40lj_1.jpg (stored in)-> k/m/4/0/l/j/km40lj_1.jpg
Currently I can access it like this:
http://media.domain.com/e/9/m/7/L/4/e9m7L4_1.jpg
Is there a way to rewrite the location using filename passed to nginx so it could be accessed like this, without the long directory path/prefix:
http://media.domain.com/e9m7L4_1.jpg
Thanks
You could try this:
server {
server_name media.domain.com;
root /media;
location / {
rewrite ^/((.)(.)(.)(.)(.)(.).+)$ /$2/$3/$4/$5/$6/$7/$1 break;
}
}

Resources