Nginx proxy use path(subpath) as url - nginx

My demand is as follows:
If I request an URL like this
http://example.com/10-10-43-3
the server gets the resource from
http://10.10.43.3
and response to me.
10-10-43-3 can be arbitrary URL that replace '.' with '-'.
How can I achieve it through nginx? Something like location and proxy_pass?

The following should help get you started.
location /10-10-43-3 {
proxy_pass http://10.10.43.3;
}
If there are other redirects that need to be accounted for, you will most likely need to add variations to the above as well as regular expression handling.

Related

Nginx reverse proxy with IP in the request

am struggling finding a solution with reverse proxy.
The goal is to be able to dynamically reroute, based on URI path, the incoming requests, e.g :
https://a.b.c/23432/IP.IP.IP.IP.IP/Path should be proxied to https://IP.IP.IP.IP:23432/Path
While it is working at first sight with
location ~ ^/(?<targetport>([0-9]+)?)/(?<targethost>[^/]+) {
proxy_pass http://$targethost:$targetport;
[...]
in the end, only the first element (index.html) is served correctly. The requests made by this page (let's say js/my.js) obviously forget the return path, and are generated to access https://a.b.c/js/my.js, and fail to be served.
I tried setting http_referer (even reverse_proxying the request to it) but it doesn't help as am unable to reparse it correctly
What am I missing here ?
Thanks for your help
Problem solved, the proxied site was prefixing all the resources with /, killing the initial path

Nginx forwarding to different app's different path using `#` symbol

Quick question. We have two apps. Ports 3001 and 3002. Our domain is www.domain.com.
What we want to have it once person enters www.domain.com/pathname we want them to be redirected into another app's specific path.
How to do it?
We already came up to this in my nginx
location /pathname/ {
proxy_pass http://127.0.0.1:3002/;
}
It nearly works. However, our app under 3002 works on path /#/pathname.
We can access it by typing www.domain.com/pathname/#/pathname. We want to access same link by typing www.domain.com/pathname.
How to shorten it? What do I miss?
(upd) Just redirect /pathname to /pathname/#/pathname
According to your comment, you want just redirect from /pathname to /pathname/#/pathname
Try these combined directives:
rewrite to append # and fragment identifier
and proxy_pass to reverse proxy to the app.
E.g.:
location /short_path_name/ {
rewrite ^ /pathname/#/$uri permanent;
break;
}
location /pathname/ {
proxy_pass http://127.0.0.1:3002/;
}
And use www.domain.com/short_path_name/ link for your app.
Unfortunately, nginx can't see the fragment identifier
Unfortunately, you can't. Because server never get the fragment identifier from browser.
The fragment identifier functions differently to the rest of the URI: its processing is exclusively client-sided with no participation from the web server
Naming a bit amusing, but it has a long history. See TBL (1997): Fragment Identifiers on URIs:
The URI reference is a thing you build by taking a URI for an information object, adding a "#" sign and then a Fragement identifier. (The last term is historical, so try not to thinl of it necessarily identifying a fragment).
Workarounds
There are workarounds, e.g. encode hashtag symbol into %23 but I'm not sure is it your way.
Handle request arguments with nginx
Note: rewriting url, nginx can preserve request arguments if you add ? at the end of rewrite directive.
See Nginx rewrite manual:
If a replacement string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended, for example:
rewrite ^/users/(.*)$ /show?user=$1? last;

How to create a dynamic root in Nginx based on a route value?

What I'm trying to accomplish is to be able to pass in a route such as this:
mysite.com/abc123/file.mp3
In Nginx I want it to read the abc123 and then call a piece of code (don't care what language: php, python, golang, fortran...) and then return the actual key that is needed to load the file.
In my config I have this:
server{
#lots of basic stuff here
location / {
mp4;
mp4_buffer_size 1m;
mp4_max_buffer_size 5m;
root /my_path/;
}
}
This works when I pass in my abc123/file.mp3. It will find the file and play it if that file exists in /my_path/abc123/file.mp3.
What I want is to translate (from a database) abc123 to myKey123 which would live at /my_path/myKey123/file.mp3
So, first, is this even possible?
If so, I'm not sure how to approach this. I know this question could have multiple solutions, but any direction will be appreciated.
The PHP script can issue a redirection using the X-Accel-Redirect header. This is treated by nginx as an internal redirect, so the rewritten URI is not exposed to the user. The documentation is a bit thin on details, hopefully you can find an example using PHP.
If you can ring-fence the rewritten URIs with a unique prefix, e.g. /download/myKey123/file.mp3, you can protect the files from direct access by using the internal directive. See this document for details. In which case, you will not need to obfuscate myKey123.
location /download/ {
internal;
...
}

how to write dynamic route in nginx location proxy config

for example I want anyone hits localhost/api to be redirected to a proxy of 127.0.0.1/api and whatever after it, for example, if I got localhost/api/getMyName then the config redirect it to 127.0.0.1/api/getMyName. or if someone hits localhost/api/getSomeone/1, it will proxy to 127.0.0.1/api/getSomeone/1
I tried something like
location /api {
proxy_pass http://127.0.0.1/api;
}
But the nginx just not responding at or, and adding /* or * after them just do not do the work... what should it actually be written to match the scenario I want above?

NGinx : How to test if a cookie is set or not without using 'if'?

I am using the following configuration for NGinx currently to test my app :
location / {
# see if the 'id' cookie is set, if yes, pass to that server.
if ($cookie_id){
proxy_pass http://${cookie_id}/$request_uri;
break;
}
# if the cookie isn't set, then send him to somewhere else
proxy_pass http://localhost:99/index.php/setUserCookie;
}
But they say "IFisEvil". Can anyone show me a way how to do the same job without using "if"?
And also, is my usage of "if" is buggy?
There are two reasons why 'if is evil' as far as nginx is concerned. One is that many howtos found on the internet will directly translate htaccess rewrite rules into a series of ifs, when separate servers or locations would be a better choice. Secondly, nginx's if statement doesn't behave the way most people expect it to. It acts more like a nested location, and some settings don't inherit as you would expect. Its behavior is explained here.
That said, checking things like cookies must be done with ifs. Just be sure you read and understand how ifs work (especially regarding directive inheritance) and you should be ok.
You may want to rethink blindly proxying to whatever host is set in the cookie. Perhaps combine the cookie with a map to limit the backends.
EDIT: If you use names instead of ip addresses in the id cookie, you'll also need a resolver defined so nginx can look up the address of the backend. Also, your default proxy_pass will append the request onto the end of the setUserCookie. If you want to proxy to exactly that url, you replace that default proxy_pass with:
rewrite ^ /index.php/setUserCookie break;
proxy_pass http://localhost:99;

Resources