How can I use an Azure Front Door Rules Engine match condition to only match requests to the root of a site? - azure-front-door

I'm trying to set up a set of rules on my Azure Front door to redirect all requests to the root of a site to a set of language based subfolders based on the location match of the incoming request.
Doing the Geo-location part is fairly straightforward, but I'm not having much success limiting the requests to only the root of the site - or at least when I try to do so, my rules don't appear to match and I don't get the redirect I'm expecting.
I've tried setting the above conditions:
IF "Request Path" EQUAL "/"
AND IF "Remote address" "Geo Match" "Switzerland, CH"
THEN "Routing Configuration" "Redirect" "307"
Host: Preserve;
Destination Path: Replace: "/de-ch/"
However I don't appear to be getting the redirect when requesting the root of the site from a browser based in Switzerland.
I can't find any actual examples for using the Rules Engine with either Path or matching, so I'm wondering if I should be using "Request URL" (and therefore I'll need to put the scheme and host in there, which is less than ideal as ruleset may be working with multiple front end hosts), or should what I'm doing work?

The "Request Path" match condition appears to match on the path after the initial /, for example given a request for:
https://www.example.com/folder/page.html
The following values are used in the match conditions:
Request Path: folder/page.html
Request URL: https://www.example.com/page.html
Request File Extension: html
Request Filename: page.html
I therefore had to use the Request URL condition and limit my rules to the specific domain in the request to ensure that we were only matching the root requests.
I have not tried specifying an operator of Not Any yet, although that could also be a solution (we needed more that 25 rules, which is a further limitation, so ended up using a different solution).

Zhaph said they have not tried the Not Any operator at the time of writing.
I've just used it and I can confirm Not Any works for matching just the root of the domain/subdomain. Definitely takes the hassle out of creating multiple match conditions on Request URL.

Related

Istio - Dynamic request routing based on header-values

Dynamic request routing based on header-values
For our QA environment we need to configure a special kind of routing for the incoming (Ingress), but also for the outgoing (Egress) requests. So for outgoing requests the rule should evaluate a header value with a regex and capture a value from the header and build with that value the URL where the request should be redirected. The value in the header is dynamically changed, so the redirect URL can not be hardcoded.
For example if the outgoing requests goes to services-master.anydomain.com, but there's a header value forwarded-for-feature with the value verbu-1234 the request should be redirected services-verbu-1234.anydomain.com.
For incoming requests it's a similar condition. If the origin points to webapp-verbu-1234.anydomain.com, but the request goes to services-master.anydomain.com the regex should extract verbu-1234 from the origin domain and replace master in the URL with the extracted value.
I know, that it's possible to use a regex to match header values, but I'm not sure, if it's possible to use captured values from a match to influence the target URL, at least I couldn't find that in the documentation.
I don't think this is possible
But if your QA system knows the features available, and you need to do that in Istio, you might try creating a VirtualService for each feature. And multiple VirtualServices would be merged by Istio...

haproxy rewrite on backend to add a path for some requests to a specific domain

I am looking to try and get haproxy to rewrite a url on the backend. For example if the end user navigates to bitechomp.domain.com they should only see this URL but the request to the backend server needs to have the request re-written to include a path. e.g. bitechomp.domain.com/bitechomp
I believe I have the regex to match it, but struggling to find the syntax to then just have it add the folder path at the end.
^([a-zA-Z0-9]/)?(bitechomp).$
I believe I have resolved this.
http-request set-path /bitechomp/ if { path_reg ^([a-zA-Z0-9]/)?(bitechomp).$ }
This works for any domain so both bitechomp.domain1.com and bitechomp.domain2.com would be re-written to bitechomp.domain1.com/bitechomp and bitechomp.domain2.com/bitechomp

Application Request Routing on local machine

I installed ARR on my local machine and setup a server farm with a single server in it (localhost). I added two redirect routing rules. However, it doesn't do the redirect. My Default Web Site has ab additional binding like this one: localhost.mycompany.com. I tried putting that in the server farm and it still didn't work. The redirect rules look like this.
Uses wildcards in the pattern
inbound pattern: */path2/*/*/*/method*
Redirect URL: /path1/path2/api/item/method
EDIT: When I use the Test Pattern and enter one of the URLs against my rule it parses it successfully
Also tried putting the full hostname (e.g. http://localhost.mycompany.com/...) in the redirect rule as well as using the alias localServerFarm (which is the name of server farm). Nothing worked.
The module is "working" in some respect because when I had a broken rule it sure told me about it when I tried to load any url on localhost. Once I fixed the rule, I no longer got the error message but it doesn't do any redirection.
This was just a matter of getting the redirect rule correct. In the rules list there is a column named Input and it's setting is URL Path. So, the only input to the pattern match is the path part of the URL not including the / at the beginning. All I had to do was change the */ at the beginning of my pattern to just *, e.g. */path2/*/*/*/method* changed to *path2/*/*/*/method*.
I don't know if there's any other setting for the Input field (it isn't settable in the rule definition screen) but for anyone creating rules remember that only the path without a leading / is what's used for evaluating the pattern match. One note is that if you're matching from the beginning of the path, as I am, you don't need the * at the beginning of the pattern. However, if you go into the test pattern screen and paste a full URL into the Input data it will not just grab the path part of that URL and feed it to the pattern match will use the entire string so it will require an * at the beginning of your pattern to work.

Redirect S3 subfolder to another domain with Cloudfront

I have a static showcase website hosted on S3 and using CloudFront, and an online shop (Prestashop) and a blog (Wordpress), both hosted on OVH servers.
I want to make a hidden redirection on two subfolders of my static website so it acts like my 3 websites are on the same host, using the following pattern :
mysite.com/ --> normal behaviour
mysite.com/blog/ --> myblog.com/
mysite.com/store/ --> mystore.com/
Of course, I need every request to be handled that way, eventually having something like that :
mysite.com/store/fr/1-myproduct.html
returns what
mystore.com/fr/1-myproduct.html
would have returned.
This seems really tricky, since I've found no real solution to my problem, and at this point I doubt it may even be possible to do such a thing.
I considered using a proxy but wouldn't that be like using a sledgehammer to get rid of a fly ?
I have searched for any possible redirection and I was only able to find subdomain/domain redirections...
So my question would be "How can I do that ?"
But right now I'm wondering "Can one do that ?"
P.S : It's my first post ever, I'm used to search for a long time before posting and I always end up finding a solution, except for now. Any suggestion is welcome.
I'll check about proxies since it's my last hope
Wait.
I have a static showcase website hosted on S3 and using CloudFront
CloudFront is a reverse proxy.
Depending on how much flexibility you have with the other two sites, CloudFront can potentially take you where you want to go, combining multiple independent sites under one hostname.
This is done by creating additional origin servers for your distributions and then creating additional cache behaviors, with path patterns matching the additonal paths, such as /blog and /blog/* that send requests to the alternate origins.
There is, however, a catch. CloudFront can't remove the matched pattern, so mainsite.example.com/blog/hello-world, matching the pattern /blog/* will be forwarded to blog.example.com/blog/hello-world -- not to blog.example.com/hello-world.¹ This will require changes to the other sites in order to integrate them in this way.
Unless...
If you already have unique path patterns, no problem, but if the extra sites' content is in the root of each individual site, you see the issue, here. Not insurmoubtable, but still an issue.
Your only alternative will be a reverse proxy behind CloudFront to rewrite those paths and send the requests on to the alternate servers. Truly not a big deal either, since HAProxy, Nginx, and Varnish all offer such functionality and can handle a large number of proxied requests on surprisingly small hardware.
The recently (2017) released Lambda#Edge service allows you to rewrite paths on the fly, as requests are processed, if necessary.
But the bottom line is that the reason you have not found a real solution other than a proxy is that there is no alternative -- every path at a given hostname must be handled in one logical place -- one group of one or more identically-configured endpoints. In the case of CloudFront, the logical place is physically distributed globally.
¹ CloudFront, natively, can actually prepend onto the path before forwarding the request, so requests for mainsite.example.com/bar/fizz can be forwarded to foosite.example.com/foo/bar/fizz by setting the origin path to /foo when you configure the origin. But it can't remove path parts or otherwise modify the path without also using Lambda#Edge. In the scenario discussed above, you would leave the origin path blank when configuring the additional origin servers.
Single S3 bucket with the following behavior :
domain.com-> serves the files from root of bucket
domain.com/blog -> serves the files from subfolder in S3 bucket (this is not default behavior)
How to :
https://aws.amazon.com/ru/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
Lambda edge code:
'use strict';
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda#Edge
var request = event.Records[0].cf.request;
// Extract the URI from the request
var olduri = request.uri;
// Match any '/' that occurs at the end of a URI. Replace it with a default index
var newuri = olduri.replace(/\/$/, '\/index.html');
// Log the URI as received by CloudFront and the new URI to be used to fetch from origin
console.log("Old URI: " + olduri);
console.log("New URI: " + newuri);
// Replace the received URI with the URI that includes the index page
request.uri = newuri;
// Return to CloudFront
return callback(null, request);
};
Summary of code higher :
lambda edge rewrites the path "/blog/" to "/blog/index.html"

Is it possible to use wildcards or catch-all paths in AWS API Gateway

I am trying to redirect all traffic for one domain to another. Rather than running a server specifically for this job I was trying to use AWS API Gateway with lambda to perform the redirect.
I have this working ok for the root path "/" but any requests for sub-paths e.g. /a are not handled. Is there a way to define a "catch all" resource or wildcard path handler?
As of last week, API Gateway now supports what they call “Catch-all Path Variables”.
Full details and a walk-through here: API Gateway Update – New Features Simplify API Development
You can create a resource with path like /{thepath+}. Plus sign is important.
Then in your lambda function you can access the value with both
event.path - always contains the full path
or event.pathParameters.thepath - contains the part defined by you. Other possible use case: define resource like /images/{imagepath+} to only match pathes with certain prefix. The variable will contain only the subpath.
You can debug all the values passed to your function with: JSON.stringify(event)
Full documentation
Update: As of last week, API Gateway now supports what they call “Catch-all Path Variables”. See API Gateway Update – New Features Simplify API Development.
You will need to create a resource for each level unfortunately. The reason for this is API Gateway allows you to access those params via an object.
For example: method.request.path.XXXX
So if you did just /{param} you could access that with: method.request.path.param but if you had a nested path (params with slashes), it wouldn't work. You'd also get a 404 for the entire request.
If method.request.path.param was an array instead...then it could get params by position when not named. For example method.request.path.param[] ...Named params could even be handled under there, but accessing them wouldn't really be easy. It would require using something some sort of JSON path mapping (think like what you can do with their mapping templates). Sadly this is not how it's handled in API Gateway.
I think it's ok though because this might make configuring API Gateway even more complex. However, it does also limit API Gateway and to handle this situation you will ultimately end up with a more confusing configuration anyway.
So, you can go the long way here. Create the same method for multiple resources and do something like: /{1}/{2}/{3}/{4}/{5}/{6}/{7} and so on. Then you can handle each path parameter level if need be.
IF the number of parameters is always the same, then you're a bit luckier and only need to set up a bunch of resources, but one method at the end.
source: https://forums.aws.amazon.com/thread.jspa?messageID=689700&#689700
Related to HTTPAPI that AWS introduced recently, $default is used a wildcard for catching all routes that don't match a defined pattern.
For more details, refer to: aws blogs
You can create a resource with path variable /{param}, and you can treat this as wildcard path handler.
Thanks,
- Ka Hou