Nginx rewrite rule for specific request - nginx

I'm trying to rewrite a specific request url using nginx, but I've only gotten so far as either a permanent redirect loop or no rewrite at all.
The rewrite rule I'm trying to achieve is the following:
FROM https://localhost/api/economic/grantaccess?id=123&token=foobar
TO https://localhost/customer-api/api/economic/grantaccess?id=123&token=foobar
I'm just looking to add /customer-api/ to this specific request, any other requests should be picked up by the /customer-api/ location. Meaning that after the redirect is made to https://localhost/customer-api/api/economic/grantaccess?id=123&token=foobar the location that should be used to serve that request should be /customer-api/ so that the proxy_pass kicks in and connects to the backend.
Here is my simplified nginx config:
http {
default_type application/octet-stream;
server_tokens off;
upstream customerapi {
zone customerapi 64k;
server 127.0.0.1:6564;
}
server {
listen 80;
server_name localhost;
root /apps;
index index.html;
location ~ /api/economic/grantaccess(.*)$ {ยด
rewrite ^ /customer-api/api/economic/grantaccess$1$is_args$args break;
}
location /customer-api/ {
rewrite ^ $request_uri;
rewrite ^/customer-api/(.*) $1 break;
return 400;
proxy_pass http://customerapi/$uri;
proxy_set_header Host $host;
}
}
}
When using break flag the rewrite does not work at all because nginx tries to open the new path as a file in the filesystem instead of picking up the request via the /customer-api/ location, and if I use permanent flag I get stuck in a permanent redirect loop.
Any help is very much appreciated.

Related

How to correctly change the location directive in nginx?

I implemented a simple REST API using Falcon and running it with Gunicorn. An example call looks like this
curl "http://localhost:5000/articles?limit=100"
Now I'm trying to make the API accessible using nginx, and I actually got it working using the following config file for nginx
server {
listen 80;
server_name xxx.xxx.xxx.xxx;
location / {
include proxy_params;
proxy_pass http://localhost:5000;
}
}
With this I can go to http://xxx.xxx.xxx.xxx/articles?limit=100 to get the respective response. The only thing I would like to do now is to change the location directive. When I change the config file to
server {
listen 80;
server_name xxx.xxx.xxx.xxx;
location /test/ {
include proxy_params;
proxy_pass http://localhost:5000;
}
}
I would assume that http://xxx.xxx.xxx.xxx/test/articles?limit=100 will again give me the correct response, but I get an 404. Using /test instead of /test/ doesn't help either. What am I missing?

nginx: why no access log for rediect location

My nginx config file goes following:
server {
location /mysite {
auth_request /authVerify;
proxy_pass http://localhost:4200;
error_page 401 = /login;
}
location /authVerify {
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_pass http://localhost:3000;
}
location /login {
proxy_cookie_path / "/; HttpOnly";
proxy_pass http://localhost:3000;
}
location / {
root html;
index index.html index.htm;
}
}
log related configs use the default settings.
the auth_request configration works. But when I send request to /mysite, there is only logging of it in access log, there is no logging of /authVerify although it actually proxy through this locatoin. If I send request to /authVerify directly, there will be loggings as well.
So in the redirect cases how to produce logs for all the locations the request running through?
Update
Based on the comment, I set log_subrequest as on in http block level. After this change, the logs of internal rediect was produced, but the log of original mysite location disappear.
Currently after I send one request to /mysite, the log is as following:
I found the following explanation on nginx doc:
Requests are logged in the context of a location where processing ends. It may be different from the original location, if an internal redirect happens during request processing.
http://nginx.org/en/docs/http/ngx_http_log_module.html
Is that because of that? Any more methods to log the request's entire flow?
Have you tried enabling log_subrequest?
log_subrequest
Context: http, server, and location
Enables or disables logging of sub-requests triggered by internal redirects or SSI requests.
Syntax: on or off
Default value: off

NGINX Not Loading Resources for Second Server

I'm new to NGINX (well hosting in general), so please excuse my ignorance. I have a Phoenix web app running on localhost:4000 and an ASP.NET web app running on localhost:5123. I'm trying to utilize NGINX to create a reverse proxy so that either web app can be accessed from the same domain. My NGINX config file contains the following:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:4000;
}
location /test {
rewrite /test(.*) /$1 break;
proxy_pass http://localhost:5123;
}
}
I'm able to access server 1 on example.com/ and server 2 on example.com/test, however, server 2 is not able to load its own css, javascript and image files. Is there a way to ensure server 1 and server 2 utilize their own resources via the NGINX config setup?
You are on the right way. There are some lines missing on your second service:
Replace...
location /test {
rewrite /test(.*) /$1 break;
proxy_pass http://localhost:5123;
}
with...
location /test {
rewrite /test/(.*) /$1 break;
rewrite ^/test$ /test/ permanent;
proxy_pass http://localhost:5123/;
proxy_redirect / /test/;
proxy_set_header Host $host;
proxy_buffering off;
}
I don't know if this is the best way to achieve this. Long time ago I used this configuration to implement an etherpad-service on my server. That time I had not the option to use a subdomain. Anyway - using a subdomain for your second service would be better.

How do I rewrite URLs in a proxy response in NGINX

I'm used to using Apache with mod_proxy_html, and am trying to achieve something similar with NGINX. The specific use case is that I have an admin UI running in Tomcat on port 8080 on a server at the root context:
http://localhost:8080/
I need to surface this on port 80, but I have other contexts on the NGINX server running on this host, so want to try and access this at:
http://localhost:80/admin/
I was hoping that the following super simple server block would do it, but it doesn't quite:
server {
listen 80;
server_name screenly.local.akana.com;
location /admin/ {
proxy_pass http://localhost:8080/;
}
}
The problem is that the returned content (html) contains URLs to scripts and style info that is all accessed at the root context, so I need to get these URLs rewritten to start with /admin/ instead of /.
How do I do this in NGINX?
We should first read the documentation on proxy_pass carefully and fully.
The URI passed to upstream server is determined based on whether "proxy_pass" directive is used with URI or not. Trailing slash in proxy_pass directive means that URI is present and equal to /. Absense of trailing slash means hat URI is absent.
Proxy_pass with URI:
location /some_dir/ {
proxy_pass http://some_server/;
}
With the above, there's the following proxy:
http:// your_server/some_dir/ some_subdir/some_file ->
http:// some_server/ some_subdir/some_file
Basically, /some_dir/ gets replaced by / to change the request path from /some_dir/some_subdir/some_file to /some_subdir/some_file.
Proxy_pass without URI:
location /some_dir/ {
proxy_pass http://some_server;
}
With the second (no trailing slash): the proxy goes like this:
http:// your_server /some_dir/some_subdir/some_file ->
http:// some_server /some_dir/some_subdir/some_file
Basically, the full original request path gets passed on without changes.
So, in your case, it seems you should just drop the trailing slash to get what you want.
Caveat
Note that automatic rewrite only works if you don't use variables in proxy_pass. If you use variables, you should do rewrite yourself:
location /some_dir/ {
rewrite /some_dir/(.*) /$1 break;
proxy_pass $upstream_server;
}
There are other cases where rewrite wouldn't work, that's why reading documentation is a must.
Edit
Reading your question again, it seems I may have missed that you just want to edit the html output.
For that, you can use the sub_filter directive. Something like ...
location /admin/ {
proxy_pass http://localhost:8080/;
sub_filter "http://your_server/" "http://your_server/admin/";
sub_filter_once off;
}
Basically, the string you want to replace and the replacement string
You may also need the following directive to be set before the first "sub_filter" for backend-servers with data compression:
proxy_set_header Accept-Encoding "";
Otherwise it may not work.
For your example it will look like:
location /admin/ {
proxy_pass http://localhost:8080/;
proxy_set_header Accept-Encoding "";
sub_filter "http://your_server/" "http://your_server/admin/";
sub_filter_once off;
}
You can use the following nginx configuration example:
upstream adminhost {
server adminhostname:8080;
}
server {
listen 80;
location ~ ^/admin/(.*)$ {
proxy_pass http://adminhost/$1$is_args$args;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
If there are no hyperlinks which need to be rewritten with sub_filter,
you might just use the proxy_redirect directive:
location /admin/ {
proxy_pass http://localhost:8080/;
proxy_redirect / /admin/
}
It changes the Location-Header of the response according to the given 'match-rewrite' rule.

Nginx. If Empty URI. If Empty Domain. Location. Regex

I'm using the upstream module for balancing my site. For some reason i have to redirect some requests to a specified server.
So in short: i want to redirect domain.com to a specified server, domain.com/anything can be served by the upstream module. So if theres only the domain in the request and nothing else.
location [here_something_i_dont_know]/ {
proxy_pass http://0.0.0.0:9000/;
access_log off;
}
Thanks for ur help!
location = / {
proxy_pass http://0.0.0.0:9000/;
access_log off;
}
location / {
proxy_pass http://another_upstream;
access_log off;
}

Resources