Traefik Path Based Routing - docker

I have two backends I want to serve from one Host. One from host.domain.com and the other from host.domain.com/path. The first frontend rule is straightforward: Host:host.domain.com.
The second is giving me some trouble. Based on the documentation I believe I should be using Host:host.domain.com;PathPrefixStrip:/path. This returns a 200 on host.domain.com/path, but when I click the link to somepage.html, it sends me to host.domain.com/somepage.html, so it returns a 404. If I go directly to host.domain.com/path/somepage.html it returns a 200. The link to somepage.html behaves correctly when I go directly to host.domain.com/path/index.html.
Are my assumptions/interpretations of the documentation incorrect or is this not an issue with Traefik at all?

This isn't really specific to traefik, any virtual path based reverse proxy that doesn't rewrite the contents of the web page returned (and few do this) have problems when the contents of that web page have absolute paths. The web page needs to either know about the "/path" and modify all the links it gives you, or use relative links, without a leading "/". This should be fixed within your website, web application, or hopefully a configuration for a web application. Depending on the application, once reconfigured, you may need to adjust the traefik rule to just "PathPrefix" instead of "PathPrefixStrip".

You should use a PathPrefix instead a PathPrefixStrip . The Strip rules remove the path before presenting it to the backend.
Since the path is stripped prior to forwarding, your backend is expected to listen on /.

Related

Invalid hostname on mvc site - IIS 8

I have an mvc app that has been deployed to our production server. It works well under IIS 8.5 using an IP and an asigned port. But the moment I try to bind it to a subdomain the app starts showing the invalid hostname error.
Tried to see if there was something off in the applicationhost.config but the binding is in the correct format. IP:Port:Binding.
The redirection also works fine, it lands on the page, but it shows the error instead of the login page.
I have deployed sites before, but not MVC apps, and bind them to subdomains and its usually a 2 step process. I dont know what im missing here.
Edit. Here is the screen of the error. Does not say a lot.
I'm not familiar with MVC or IIS, but base on my experience with other products, you very likely need to tell IIS to preserve the Host header.
Eg. https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/modifying-http-response-headers
In order to be able to modify the HTTP Location header it is necessary to preserve the original value of the HTTP host header. The outbound rewrite rule will use the preserved value when modifying the response. To preserve the original value you will store it in a temporary server variable ORIGINAL_HOST.
You should also make yourself aware about the security vulnerabilities that can result with regard to Host headers. https://techcommunity.microsoft.com/t5/iis-support-blog/host-header-vulnerability/ba-p/1031958

Route 53 - Special domain for a single page on existing server

I have a complex web app at example-app.com, hosting fully on AWS using ELB and Route 53 for DNS. It's a Rails app.
I'm running an experiment that I'm using in the rails app, at example-app.com/test. I want to set up new-domain-app.com, to point at example-app.com/test, and have the URL cloacked to always be new-domain-app.com. It's a single page site, so it shouldn't require any navigation.
I'm having a lot of trouble figuring out how to set up my DNS on Route 53 to accomplish this. Does anyone have good ideas on what this Route 53 configuration should look like?
AWS offers a very simple way to implement this -- with CloudFront. Forget about the fact that it's marketed as a CDN. It's also a reverse proxy that can prepend a fixed value onto the path, and send a different hostname to the back-end server than the one typed into the browser, which sounds like what you need.
Create a CloudFront web distribution.
Configure the new domain name as an alternate domain name for the distribution.
For the origin server, put your existing hostname.
For the origin path, put /test -- or whatever string you want prefixed onto the path sent by the browser.
Configure the cache behavior as needed -- enable forwarding of the query string or cookies if needed and any headers your app wants to see, but not Host.
Point your new domain name at CloudFront... But before you do that, note that your CloudFront distribution has a dxxxexample.cloudfront.net hostname. After the distribution finishes setting up (the "In Progress" status goes away, usually in 5 to 20 minutes) your site should be accessible at the cloudfront.net hostname.
How this works: When you type http://example.com into the browser, CloudFront will add the origin path onto the path the browser sends, so GET / HTTP/1.1 becomes GET /test/ HTTP/1.1. This configuration just prefixes every request's path with the string you specified as the origin path, and sends it on to the server. The browser address bar does not change, because this is not a redirect. The host header sent by the browser is replaced with the hostname of the origin server when the request is sent to the origin.
What you are trying to do is not possible. Route53 is a DNS system, and you can not configure a hostname (e.g. new-domain-app.com) to point to URL (e.g. http://example-app.com/test) using DNS.
However, you are probably using a wrong tool for the job. If example-app.com/test is indeed a simple, static, single page site, then you do not need to host it inside Rails app. Instead, you can host it on AWS S3 bucket, and then you can point new-domain-app.com to that bucket using Route53.
See the following for details:
http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/RoutingToS3Bucket.html
DNS knows about Domains, not url's. DNS simply converts names to IP addresses.
You can't do what you are asking for just using DNS and ELB, however, what you can do is have a seperate VHOST for new-domain-app.com that points to your example-app.com site and accomplishes what you want using some sort of redirection rule that only fires for new-domain-app.com.
I'm not sure that this qualifies as an SO question, and more likely is a serverfault question. Specifics about your webserver and OS platform would be helpful in getting more specific advice.
So here's some details:
You already have example-app.com setup and working
You create a CNAME entry pointing new-domain-app.com to example-app.com or you can make an A record pointing to the same IP. If you already have example-app.com pointing to a different IP address, then use a subdomain (test.example-app.com) to isolate it.
Setup a new vhost on your server that basically duplicates the existing vhost for new-domain-app.com. The only thing you need to change is the server name configuration.
Why does this work? Because HTTP 1.1 included the HOST header that browsers send along, and web servers use in vhosting to determine which virtual host to route an incoming request to. When it sees that the client browser wanted "example-app.com" it routes the request to the appropriate vhost.
Rather than having to do some fancy proxying, which certainly can be used to get to a similar result, you can just add a redirection rule that looks for requests for the host example-app.com and redirects those to example-app.com. In apache that uses mod_rewrite which people often utilize by putting rules in the ubiquitous .htacess file, but can also be done in nginx and other common web servers. The specifics are slightly different for each.

how to add subdomain name from current url using .htacces rules

I have a URL link like,
http://domain.com/abs/def/city and,
i want to display it as http://city.domain.com/ABC/def
using .htaccess.
Can any one help me by providing .ht access rules.
I want to write .htaccess rules for each city name in URL act as sub domain name.
Also i want it to be dynamic as there are different cities are available in site.
i am using below code in .htaccess file, but not working properly.
RewriteRule ^index.php/(.)/(.)/([^/]+)$ http://$3.domain/$1/$2/$3 [R=301,L]
is there any way to get my requirement using or by modifying my above code or by some other .htaccess code.
Sorry, but what you ask is not possible. This is a typical missunderstanding about url rewriting:
Url rewriting rewrites (manipulates) incoming requests on the server side before processing them. It is not possible to alter outgoing content such that contained urls are changed by this means.
There are solutions for that though:
apaches proxy module can "map" one url into the scope of some other url
there are also modules for automatic post processing of generated html markup
more exotic or creative solutions exist, it depends on your situation in the end...
But usually the easiest is to change the application (typically just its central configuration) such that it contains final urls (pointing to the subdomain in your case). Then you can indeed use the rewriting module to "re-map" those to the previous scope when future incoming requests refer to them (they got clicked).
Ok, second step getting additional info from your comments:
Just to get this clear: you understand that it is not possible to change the link you send out by means of rewriting, but you want to change the url shown in the browser after the user has clicked on some city link? That is something different to what you wrote before, that actually is possible. Great.
If the rewriting works as you want it to (you see the desired url in the browsers address bar), then we can go on. The error message indicates a name resolution problem, that has nothing to do with rewriting. Most likely the domain "cambridge.192.168.2.107" cannot be resolved, which is actually not surprising. You cannot mix ip addresses and names, it is either or.
Also I see that you are using internal, non-routable addresses. So you also are responsible for the name resolution yourself, since no public DNS server can guess what you are setting up internally. Did you do that?
I suggest these steps:
stop using an ip addres for this, use a domain name.
since you are working internally, take care that that domain name is actually resolved to your local systems ip address. How you do this depends on your setup and system, obviously. Most likely you need some entry in the file /etc/hosts or similar.
you need to take care that also those "subdomain names" get resolved to the same address. This is not trivial, again it depends on the setting and system you locally use.
if that name resolution works, then you should see a request in your http servers access log file. Then and only then it makes sense to go on...

IIS 7 URL Rewrite config issue or MVC Route?

I have an account with Gearhost.com and when it comes to setting up sub-domains you are currently required to go in and configure an URL Rewrite entry using IIS Remote Admin.
The directory folder structure follows the pattern:
\mastersite
\mastersite\subdomain1
The Gearhost KB Article on how to do it can be found here:
https://support.gearhost.com/KB/a851/setting-a-subdomains-content-location-using-url-rewrite.aspx?KBSearchID=0
This works just fine, but I ran into a scenario that revealed the ability to access the sub-domain by using the master.com/sub-domain path.
subdomain1.site.com (works)
www.site.com/subdomain1 (displays site also --which I don't want)
I don't know if the KB article is the correct way to configure sub-domains in IIS or if I need to manage the routing in my Microsoft MVC 3 Application.
Let's say it is the correct way to setup/configure a sub-domain. Is there a way to restrict the path for the 2nd option, so it returns as page not found or access forbidden or something to this effect?
I'm developing a Microsoft MVC Application and if I use a "Request.Url" call, it actually returns the full path of the 2nd option even when I'm sitting on what looks like a perfect path to the sub-domain home page.
So I don't know if this needs to be handled a different way, if the URL Rewrite entry needs to be changed, or what the solution may be.
Looking for feedback from any engineers who may have more knowledge on the topics.
Thanks.
I ran across an article which solved my original request for help.
It involved creating Outgoing rules in IIS, to rename the path. The rule looks for the path in question and then rewrites it.
Per the article I used Outgoing rule # 2.
Pre-Condition: None
Matching Scope: Server Variable
Variable Name: RESPONSE_LOCATION
Variable Value: Matches the Pattern
Using: Regular Expressions
Pattern: ^(?:MyMasterSiteSubFolder/MySubDomain|(.*//[_a-zA-Z0-9-\.]*)?/MyMasterSiteSubFolder/MySubDomain)(.*)
[x] Ignore case
Action: Rewrite
Action Properties Value: {R:1}{R:2}
[x] Replace existing server variable value
[ ] Stop processing of subsequent rules

How do you see the client-side URL in ColdFusion?

Let's say, on a ColdFusion site, that the user has navigated to
http://www.example.com/sub1/
The server-side code typically used to tell you what URL the user is at, looks like:
http://#cgi.server_name##cgi.script_name#?#cgi.query_string#
however, "cgi.script_name" automatically includes the default cfm file for that folder- eg, that code, when parsed and expanded, is going to show us "http://www.example.com/sub1/index.cfm"
So, whether the user is visiting sub1/index.cfm or sub1/, the "cgi.script_name" var is going to include that "index.cfm".
The question is, how does one figure out which URL the user actually visited? This question is mostly for SEO-purposes- It's often preferable to 301 redirect "/index.cfm" to "/" to make sure there's only one URL for any piece of content- Since this is mostly for the benefit of spiders, javascript isn't an appropriate solution in this case. Also, assume one does not have access to isapi_rewrite or mod_rewrite- The question is how to achieve this within ColdFusion, specifically.
I suppose this won't be possible.
If the client requests "GET /", it will be translated by the web server to "GET /{whatever-default-file-exists-fist}" before ColdFusion even gets invoked. (This is necessary for the web server to know that ColdFusion has to be invoked in the first place!)
From ColdFusion's (or any application server's) perspective, the client requested "GET /index.cfm", and that's what you see in #CGI#.
As you've pointed out yourself, it would be possible to make a distinction by using a URL-rewriting tool. Since you specifically excluded that path, I can only say that you're out of luck here.
Not sure that it is possible using CF only, but you can make the trick using webserver's URL rewriting -- if you're using them, of course.
For Apache it can look this way. Say, we're using following mod_rewrite rule:
RewriteRule ^page/([0-9]+)/?$
index.cfm?page=$1&noindex=yes [L]
Now when we're trying to access URL http://website.com/page/10/ CGI shows:
QUERY_STRING page=10&noindex=yes
See the idea? Think same thing is possible when using IIS.
Hope this helps.
I do not think this is possible in CF. From my understanding, the webserver (Apache, IIS, etc) determines what default page to show, and requests it from CF. Therefore, CF does not know what the actual called page is.
Sergii is right that you could use URL rewrting to do this. If that is not available to you, you could use the fact that a specific page is given precedence in the list of default pages.
Let's assume that default.htm is the first page in the list of default pages. Write a generic default.htm that automatically forwards to index.cfm (or whatever). If you can adjust the list of defaults, you can have CF do a 301 redirect. If not, you can do a meta-refresh, or JS redirect, or somesuch in an HTML file.
I think this is possible.
Using GetHttpRequestData you will have access to all the HTTP headers.
Then the GET header in that should tell you what file the browser is requesting.
Try
<cfdump var="#GetHttpRequestData()#">
to see exactly what you have available to use.
Note - I don't have Coldfusion to hand to verify this.
Edit: Having done some more research it appears that GetHttpRequestData doesn't include the GET header. So this method probably won't work.
I am sure there is a way however - try dumping the CGI scope and see what you have.
If you are able to install ISAPI_rewrite (Assuming you're on IIS) - http://www.helicontech.com/isapi_rewrite/
It will insert a variable x-rewrite-url into the GetHttpRequestData() result structure which will either have / or /index.cfm depending on which URL was visited.
Martin

Resources