12

I'm using an ELB (Elastic Load Balancer) on Amazon Webservices (spezifically an Application Load Balancer).

The Problem: I want to create a rule to rewrite the path, but need to insert a string within the path.

When a request is coming in to:

example.org/api/foo/*

I need it to be redirected to:

example.org/api/v1/foo/*

The rest of the request needs to stay the same. The problem is that the original value of path cannot be altered. One way of cause would be to add every possible path as a rule. But when expanding the api it would be extremly uncomfortable.

Andrei Petrenko
  • 3,922
  • 3
  • 31
  • 53
Willie
  • 352
  • 1
  • 3
  • 15
  • I am somewhat skeptical that you really want to "redirect" the path -- it sounds like you want to *rewrite* the path. A *redirect* tells the client to try again at a different URL. – Michael - sqlbot Nov 05 '18 at 18:40
  • 2
    @Michael-sqlbot Good point. I kind of mean path rewritng but i didn't know that term. I looked it up and ELB/ALB currently does not support path rewriting. – Willie Nov 05 '18 at 20:58

2 Answers2

14

Rewriting is not supported by the ELB as you already discovered.

Some options:

1) Implement a webserver e.g. nginx between the ALB and your application, which can implement rewrite rules

2) Path-based rewriting can be achieved by using Route53 -> CloudFront -> Lambda -> ALB, instead of straight up Route53 -> ALB, as demonstrated here.

Tiemen
  • 816
  • 5
  • 9
5

A good option for the time being is to leverage Lambda@Edge to achieve URL rewriting.

Lambda@Edge is a feature of Amazon CloudFront that lets you run code globally closer to your users. A Lambda@Edge function is triggered before the request is sent to the load balancer.

Here is an example of URL rewriting by a Lambda@Edge function in Node.js from this blog

'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);

};

By the way, it is normally advantageous to have CloudFront in front of an ALB or ELB in general, thanks to the AWS edge locations and the AWS optimized private network path, etc.

And for some use cases, another benefit with CloudFront in the front is that both static content (e.g., HTML, JavaScript, CSS and image files, etc.) and dynamic API can share the same domain and SSL certificate, by configuring multiple origins and multiple behaviours in the CloudFront distribution, see this question for details.

So it is worth a consideration for using Lambda@Edge for URL rewriting, with add-on benefits brought along by CloudFront.

Yuci
  • 27,235
  • 10
  • 114
  • 113