I am trying to set a set a difficult proxy pass within Nginx. The URL itself requires a bunch id's and then has a query string at the end.
location /api/v1/schools/(.*)/courses/(.*)/years/(.*)/api_end_point/(.*) {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host some-cool-api.test.io;
proxy_pass https://10.0.0.2/$1$is_args$args;
}
I tried the above but it's not matching the route
here is an example of what the URL will look like:
"/api/v1/schools/51/courses/231/years/3595/api_end_point?thing_1=0&thing2=0&thing_3=0&thing_4=0&thing_5=0&thing_6=0&thig_7=11250&thing_8=0"
Any idea's on how to do the above?
Related
I have 2 docker containers running. 1 is FLASK and 2 is Nginx.
This is the configuration of the Nginx location
location /search/?(.*) {
proxy_pass http://backend:8080/search/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_headers on;
}
The FLASK is running on port 8080 and the route #app.route('/search', methods=['GET']) and running with app.config['SERVER_NAME'] = 'mydomain.com'
When I try to send a GET request to "mydomain.com" (going through the NGINX) from external I get
Cannot GET /search
When I remove app.config['SERVER_NAME'] = 'mydomain.com' from the FLASK I can send GET to EXTERNAL_IP:8080 (Directly to the backend not though the NGINX).
But when I leave the app.config['SERVER_NAME'] = 'mydomain.com' and try to GET mydomain.com:8080 I get 404 Not Found
What am I missing here?
I want all requests to go though the NGINX and I want to use mydomain.com
I think your main mistake is that you trying to match the whole request URI including the query part while location directive (as well as the rewrite one) works with the normalized URI which doesn't include the query part at all (check the location directive documentation to find out what URI normalization is). Looks like you are also trying to use a regex while regex location should be declared using a ~ (or ~*) modifier. Nevertheless you don't need any regex locations at all for your particular case. To proxy a single API endpoint preservig the Host HTTP header value, you can try this one:
location = /search {
proxy_pass http://backend:8080;
proxy_set_header Host $http_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-Proto $scheme;
}
You don't need to specify an URI with the proxy_pass directive since you are not changing your request URI. If your API endpoint is /search/ rather than /search, change the location accordingly. If it is an URI path prefix rather than a single API endpoint, use a prefix location /search/ { ... } instead of exact match location.
I have the following nginx rule
location /api {
proxy_pass http://flask:5000/api;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
It will match the following path, which is what I'm expecting
http://localhost/api
http://localhost/api/
http://localhost/api/a
http://localhost/api?
http://localhost/api?name=value
However, it will also match the following, which I'm not expecting
http://localhost/apii
http://localhost/apiX
May I know how can I avoid from matching unwanted http://localhost/apii and http://localhost/apiX and http://localhost/apiXX and ...
This requires two location blocks - one matching specifically /api and one for everything in the path /api/. In this way urls like /apio will not be captured.
Example:
location = /api {
proxy_pass http://flask:5000/api;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#Querystrings and /api, matches the first, any /api/* matches this one
location /api/ {
proxy_pass http://flask:5000/api;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Reference http://nginx.org/en/docs/http/ngx_http_core_module.html#location
One possibility is to use a regular expression. As the proxy_pass is not actually transforming the URI, the uri element can be safely removed.
location ~ ^/api($|/) {
proxy_pass http://flask:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Note that regular expression location blocks are evaluated in order. See this document for details.
It's actually really simple.
Just change location /api { to location /api/ {
Nginx will add a trailing slash to any request ending /api so there is no need to add a separate block for them. This block will behave as you expected your original one to.
I am trying to set my root(/) location to be passed to a google bucket.
Here is my configuration:
listen 80;
location / {
rewrite /(.*) /$1 break;
proxy_pass https://storage.googleapis.com/my-google-bucket-name/$1$is_args$args;
proxy_redirect off;
index my_main.html;
proxy_set_header Host "storage.googleapis.com";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
This seems to work but the index directive does not set the default page (to my_main.html)
e.g. when i go to http://my_enginx_url/ instead of reaching "my_main.html" i reach the google bucket root page that shows an XML file with all the files in that bucket.
P.S
Both
http://my_enginx_url/another_page.html,
http://my_enginx_url/yet_another_page.html
are working fine.
Any ideas?
Because the index directive tells Nginx the names of files to look for within your file system which are appropriate for serving a request ending with a /
You are proxying the request to another server, so it's not applicable here.
To achieve your desired result create another location directive above your current one and use = to tell Nginx this is to handle only requests for an exact match with http://my_enginx_url/
Something like this:
location = / {
proxy_pass https://storage.googleapis.com/my-google-bucket-name/my_main.html;
......
}
I am trying to forward specific uri if matched to backend in nginx. For example
forward https://www.hostname.com/*/a/b/c to https://int.hostname.com/*/a/b/c (Where * is a variable auto populated from regex)
Current configuration looks like below and have no idea how to proceed on above
location /a/b/c/ {
proxy_set_header Host $proxy_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 180m;
proxy_pass http://int.hostname.com/v2/e/t/a/b/c;
proxy_redirect default;
}
If you want your location to match any URI that ends with /a/b/c/, you will need to use regular expression syntax. See this document for details.
The URI suffix of the proxy_pass statement is optional. In the absence of a URI suffix, the original URI will be passed unmodified. See this document for details.
For example:
location ~ /a/b/c/$ {
...
proxy_pass http://int.hostname.com;
...
}
I've got an AXIS camera sitting behind my firewall.
If you cURL to the camera's IP, it wants to redirect you to /view/index.shtml via a meta refresh.
I'm trying to access the camera via webserver-IP/camera. My nginx config is simple - it looks like this:
location /camera {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://192.168.0.205:80/;
proxy_redirect default;
}
This however is not working - the redirect isn't happening. When I access webserver-IP/camera, it redirects me to webserver-IP/view instead of webserver-IP/camera/view.
Any ideas?
Thanks!
Try replacing your proxy_redirect with this line
proxy_redirect http://192.168.0.205:80/; http://192.168.0.205:80/camera/;
I don't know what your Location header says exactly, but you should get the idea, replace the IP with a hostname or whatever the redirect is trying to take you, you're simply telling nginx to append /camera to whatever redirect the website asks you to do
The problem is that the html, js, and css returned by the axis camera all assumes that you are accessing it from a URL like http://192.168.0.205/ (Just the scheme and host, no additional /camera/ path)
If you look at the html you'll see stuff like:
<script src="/incl/prototypes.js?ver=5.80.1" language="javascript" type="text/javascript"></script>
In short, you need to re-write the content you are serving to reflect the new URL you'll be requesting it from: http://192.168.0.205/camera/
You can do that using a sub filter:
location /camera {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://192.168.0.205:80/;
proxy_redirect default;
# nevuh fuhget where you from
sub_filter_once off;
sub_filter_types *;
sub_filter '"/' '"/camera/';
sub_filter '=/' '=/camera/';
}
Depending on your camera, you may have to play around with and add more sub_filter lines to catch all of the places where the base path is incorrectly pointing to /. Also, this is basically parsing html/js/cs with REGEX so beware.