How to set the ~/ path in Asp.net core - url

This answer: https://stackoverflow.com/a/10469032/3958875 indicates that the ~/ in urls will be set to the actual root of the application if the application is in a virtual directory.
However, I can't seem to find how I can set this path/value.
For example, I have the app behind nginx reverse proxy, so that the root of the app is here: www.mywebsite.com/app1/
Therefore I want all ~/ to be expanded to app1/. How can I accomplish this?
I tried app.UsePathBase("/app1"); in the Configure method in Startup.cs, which didn't seem to do anything.
My nginx config is like:
server {
server_name: apps.mywebsite.com
location / {
...
}
location /app1/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:5000/;
}
#Https stuff ...
}
Am I missing something that I can pass to asp.net from nginx?

~ will expand to the content root. That is the effectively the path base that is configured for an incoming request.
What app.UsePathBase() does is tell the application that when the incoming request starts with the specified prefix, then that will be used as the path base. So in your case, when the incoming request starts with /app1, then /app1 will be the path base, and ~ will be expanded to /app1.
If you look at your reverse proxy configuration, you can see however that the path /app1 is not actually passed to the application:
location /app1/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:5000/;
}
So when you access the page at /app1/foo, the request path that gets passed to the application will be just /foo. So the /app1 path base isn’t seen by the application and it won’t be able to respond appropriately.
What you need to do instead is actually pass the full path to the application. You then use app.UsePathBase() to configure that path base so that it gets interpreted correctly:
location /app1/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:5000/app1/;
}
app.UsePathBase("/app1");
Now, incoming requests at /app1/foo will translate to the same path within your application, the /app1 path base will be used and ~ should expand properly to /app1.

Turns out the error is indeed in my nginx configuration.
By following the documentation on asp and nginx here: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.2
I changed my nginx config to:
...
location /app1/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
...
And ~ expanded properly.

Related

nginx reverse load assets from foo.bar/app properly

i have a webapplication running in a docker container behind nginx reverse proxy on the same container network.
the nginx is set up so that foo.bar/app redirect to the container but application seems to try load resources from foo.bar/. i have tried to do what is documented here:https://www.nginx.com/resources/wiki/start/topics/examples/likeapache/
as a result my location block looked like this:
location /app {
root /app;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://webapp/;
}
where webapp is the name of the webapp's docker container in the network
for the location block this is fine
location /app {
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://webapp/;
}
the trick is to access with a trailing slash so with foo.bar/app/ rather than with foo.bar/app
additionally adding this line will add the trailing slash automagically:
rewrite ^([^.]*[^/])$ $1/ permanent

Problem with nginx container to reverse proxy rancher container with rewrite url

on my docker host. With nginx container, i try to reverse proxy multiple services by using url name to identify the right service (portainer, rancher).
trafic from https://host1/rancher => https/rancher-container
trafic from https://host1/portainer => http://portainer-container:9000
I configure nginx to use url rewrite for transform the url before send it to the good service.
It works for service portainer. But it's don't work for rancher 2 service.
Here is my configuration:
location /rancher/ {
rewrite ^/rancher^/ /$1 break;
proxy_pass https://rancher-container;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
location /portainer/ {
rewrite ^/portainer^/ /$1 break;
proxy_pass http://portainer-container:9000/;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
When I look from my chromeDevTools, I see:
GET https://host1/rancher/ 200 OK (and return index page like this) :
<!DOCTYPE html>
<html>
...
<link id="vendor" rel="stylesheet" href="/assets/vendor.css">
...
<script src="/assets/vendor-ebb1f9e6b4381d69a55448a2a5d7e4c9.js"></script>
<script src="/assets/ui-72ee502ee50a84d0f416c3164137307d.js"></script>
...
GET https://host1/assets/vendor.css net::ERR_ABORTED 404
GET https://host1/assets/vendor-ebb1f9e6b4381d69a55448a2a5d7e4c9.js net::ERR_ABORTED 404
GET https://host1/assets/ui-72ee502ee50a84d0f416c3164137307d.js
I think my web browser try to get ressources (css, js, img ..etc) define on html page with relative url like '/assets/' to 'https://host1/assets'. Or the good url is 'https://host1/racher/assets'.
Is there some solution for this?
Check the website. Probably in the HTML code your website has no idea that it's running not on extra path but assumes it's on root. Perhaps there's some switch that you can setup a base path for the website to know where it is.
Unfortunately this is a quite common problem. Default proxy headers does not send original path so services hidden behind usually are unaware that request is for something other than /.
If the service behind proxy is yours, you can pass some additional header like x-proxy-urlpath and inform service that it should render links including that path.
If not and you cannot setup base url in the website - the best solution would be to use subdomains and host-based proxy.

Why is my Nginx reverse proxy doing a 301 redirect instead of proxying?

I have an Nginx reverse proxy inside a docker container, which listens to port 3000 and is exposed to 3002: docker run -p "3002:3000" ....
The idea is that this reverse proxy will proxy /my-app to the instance running in my laptop on port 8080; and /my-app/api to the cloud instance, in https://my-domain.
Here's the configuration:
upstream my-laptop {
server host.docker.internal:8080; # this is a magic hostname for the laptop's IP address.
keepalive 64;
}
upstream cloud {
server my-domain.com:443;
keepalive 64;
}
server {
listen 3000;
include ssl/ssl-certs.conf;
include ssl/ssl-params.conf;
location /my-app {
proxy_pass http://my-laptop;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /my-app/api {
proxy_pass https://cloud;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...
}
The issues are:
when I hit https://localhost:3002/my-app I get a 301 response to /my-app/ (trailing slash). I don't know why is that. The local app instance is shown in the browser, so I guess I can let it slide for the moment?
when I hit https://localhost:3002/my-app/api/students, I get a 301 response to https://cloud/my-app/api/students. This causes CORS issues, of course, and the endpoint doesn't return data.
Now, I have configured reverse proxies a couple of times, so I am completely shocked that I'm not seeing what's wrong, this is not my first time.
I have tried tweaking with the upstreams, the proxy_set_headers, compared with another reverse proxy that I have for a different app; I'm out of ideas.
What am I doing wrong?
Although the questioner's config doesn't have this particular issue, a redirect instead of proxying can also be caused by trailing slash issues, as described in the docs:
If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass, then the special processing is performed. In response to a request with URI equal to this string, but without the trailing slash, a permanent redirect with the code 301 will be returned to the requested URI with the slash appended. If this is not desired, an exact match of the URI and location could be defined like this:
location /user/ {
proxy_pass http://user.example.com;
}
location = /user {
proxy_pass http://login.example.com;
}
The problem was my Host header in the cloud upstream, I had
proxy_set_header Host $http_host;
But it needed to be
proxy_set_header Host my-domain.com;
here is an example config for nginx as a reverse proxy which works for me,
I simplified it and removed unnecessary parts.
I hope it helps.
upstream OAUTH {
server remote_oauth;
}
server {
listen 80;
server_name example.com;
client_header_timeout 300;
location = /servies/oauth {
return 301 /services/oauth/;
}
location /services/oauth/ {
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://OAUTH/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-ROOT-URI /services/oauth;
proxy_set_header Accept-Encoding "gzip";
proxy_buffering off;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_intercept_errors on;
proxy_redirect default;
client_max_body_size 4M;
}
}
I think you missed this part :
proxy_pass_request_headers on

Dynamic Nginx proxy with Docker

I'm stucking with configuring a Nginx instance embedded in a Docker container which should implement a dynamic reverse proxy for not-enabled CORS web sites.
I was expecting it was an easy task, but it doesn't work under some conditions. This is a working location block:
location ~* ^/proxy/(.*) {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_pass https://google.com;
}
This configuration works. The google page appears. So it seems Docker is able to resolve google name.
This configuration (which I'm more interested to) doesn't work:
location ~* ^/proxy/(.*) {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_pass http://$1$is_args$args;
}
It seems that Docker is not able to resolve the name extracted by the first regex group.
If I add in the location block the resolver directive it starts working.
location ~* ^/proxy/(.*) {
resolver 192.168.31.2;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_pass http://$1$is_args$args;
}
So, where's the difference? Why the resolver directive is needed? Why in the first case (if the proxy path name is hardcoded) everything's working while not in the other case? Is the host resolv.conf file should be used inside the container itself?
I also tried to create the container passing the --dns option but still not working.
Ideas?
Thanks,
Fb
Nginx try to resolve domain_name with upstream directive: if it fail it will try to use resolver to solve your name as DNS. So, in the end, you need to set resolver directive.

Nginx proxy_pass without get / post parameters

I'm doing proxy_pass when url of my domain looks like this:
http://evil.corp/v666/this/is/my/url
and everything works fine.
location ~^/v666/ {
proxy_pass http://evil.corp.lan;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
evil.corp.lan has second nginx and I'm proxing the request.
But I wish to CUT the part "/v666" after the domain, and proxy only this part of my url:
http://evil.corp/this/is/my/url
without "/v666"
could you give me hint how to do this?
Changing:
location /v666/ {
and
proxy_pass http://evil.corp.lan:80/;
helped.
https://serverfault.com/a/725433/331458
It is very important to use
location /v666/
otherwise, using location ~^/v666/ you will end up with:
"proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block.
Now it works! :)

Resources