Question

Is it possible to put a redirect header on a s3-object? Like a 301 redirect.

For example:

mybucket.amazon-aws.com/myobject --> example.com/test

Preferably by setting a header like this on the object:

HTTP/1.1 301 Moved Permanently
Location: http://example.com/test
Content-Type: text/html
Content-Length: 0
Was it helpful?

Solution

Within the last month, this functionality has just been added.

You can find the API documentation here:

http://docs.amazonwebservices.com/AmazonS3/latest/dev/how-to-page-redirect.html

When you PUT your object, you need to set the x-amz-website-redirect-location key against that object to the 301 redirect that you wish to use.

You can also use the console.

enter image description here

OTHER TIPS

In case if website hosting is enabled for the bucket, there is an alternative way to add 301 redirect. According to it redirection rules are described on the bucket level in XML-format, and can be specified in bucket's properties via AWS S3 Console (Static Website Hosting section). Full documentation about its syntax currently can be found here.

This approach is convenient when you have massive URL movements as far as it's easier to manage all redirections in one place. For instance it's possible to define redirection rules

<RoutingRule>
    <Condition>
        <KeyPrefixEquals>index.php</KeyPrefixEquals>
    </Condition>
    <Redirect>
        <ReplaceKeyWith>index.html</ReplaceKeyWith>
    </Redirect>
</RoutingRule>
<RoutingRule>
    <Condition>
        <KeyPrefixEquals>blog.php?id=21</KeyPrefixEquals>
    </Condition>
    <Redirect>
        <ReplaceKeyWith>mysql-utf-8-database-creation-snippet.html</ReplaceKeyWith>
    </Redirect>
</RoutingRule>

It looks like it's the same as creating fake objects and specifying x-amz-website-redirect-location metadata for them. The bad news are that there are could be not more than 50 such rules in XML for one bucket. And yes, it's not convenient to manage XML. But for me this way is easier at present. Again, because it's easier to manage all files in one place.

This XML-approach is extremely useful when you, say, renamed a directory with a lot of pages. In this case it's necessary to create a single redirection rule for directory, instead of separate rule for each page inside it. For instance

<RoutingRule>
    <Condition>
        <KeyPrefixEquals>blog/</KeyPrefixEquals>
    </Condition>
    <Redirect>
        <ReplaceKeyPrefixWith>it-blog/</ReplaceKeyPrefixWith>
    </Redirect>
</RoutingRule>

According to this rule example.com/blog/whatever will be redirected to example.com/it-blog/whatever.

Another useful feature of such approach is that it replaces only prefixes. In the same way as with directories it's possible to redirect page, but save query parameters. It could be suitable if there is some JS processing of these query parameters. With x-amz-website-redirect-location metadata you'll probably loose them.

As I mentioned writing and reading XML might be inconvenient. To overcome this I wrote a simple online tool in GWT to convert plain text with former and new URLs to XML format. It uses the KeyPrefixEquals predicate and execute ReplaceKeyPrefixWith redirect.

Finally, according to documentation, if website hosting is disabled, redirection support is not applicable for this bucket.

Edit: See answer above as this functionality is now native in AWS

Not really no. There isn't an inbuilt feature which allows this, however, what you can do is to create your object and even if you don't save it as HTML, you can apply it as an HTML file.

For example:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="Refresh" content="0; URL=http://www.example.com/target/">
    <title>Redirect</title>
</head>

<body>
    <a href="http://www.example.com/target/">http://www.example.com/target/</a>
</body>
</html>

Look at this page here: View the source on it quickly.

view-source:http://carltonbale.com.s3.amazonaws.com/distance_chart.png

You can see an explanation here:

Point 8: http://carltonbale.com/9-hidden-features-of-amazon-s3

htaccess 301 to Amazon S3 redirect translation


htaccess style:

Redirect 301 /old/old.html http://www.new.com/new/new.html

translates to:

<RoutingRule>
    <Condition>
        <KeyPrefixEquals>old/old.html</KeyPrefixEquals>
    </Condition>
    <Redirect>
        <HostName>www.new.com</HostName>
        <Protocol>http</Protocol>
        <HttpRedirectCode>301</HttpRedirectCode>
        <ReplaceKeyWith>new/new.html</ReplaceKeyWith>
    </Redirect>
</RoutingRule>

You could probably write a little script along the lines of:

// -----------------
// Javascript
// htaccess to amazon s3 redirect for static s3 websites.
// (XML goes into S3 Bucket Properties Editor > [x] Enable website hosting > Edit Redirection Rules box.)
// -----------------

var list = [
    "Redirect 301 /old/old-1.html http://www.new.com/new/new-1.html",
    "Redirect 301 /old/old-2.html http://www.new.com/new/new-2.html",
    "Redirect 301 /old/old-3.html http://www.new.com/new/new-3.html"
];

var output = [];

output.push('<?xml version="1.0"?>');
output.push('<RoutingRules>');

for(var i=0; i<list.length; i++){

    var item = list[i].replace("Redirect 301 /", "").split(" ");
    var oldLoc = item[0];
    var newLoc = item[1];

    output.push("   <RoutingRule>");
    output.push("       <Condition>");
    output.push("           <KeyPrefixEquals>" + oldLoc + "/KeyPrefixEquals>");
    output.push("       </Condition>");

    output.push("       <Redirect>");
    if(newLoc.substr(0, 1) == "/"){

        output.push("           <ReplaceKeyWith>" + newLoc + "</ReplaceKeyWith>");

    } else {

        var splitNewLoc = newLoc.replace("http://", "").split("/");
        var host = splitNewLoc.shift();
        var path = splitNewLoc.join("/");

        output.push("           <HostName>" + host + "</HostName>");
        output.push("           <Protocol>http</Protocol>");
        output.push("           <HttpRedirectCode>301</HttpRedirectCode>");

        if(path){
            output.push("           <ReplaceKeyWith>" + path + "</ReplaceKeyWith>");
        }

    }

    output.push("       </Redirect>");
    output.push("   </RoutingRule>");

}

output.push('</RoutingRules>');

print(output.join("\n"));

WARNING: Amazon limits the number of redirect rules to 50.

AWSCLI lets you do this easily now (sort of)

  1. Make sure bucket is 100% public
  2. Make sure bucket is in Website Hosting mode
  3. Only refer to site using it's full URL https://<bucket_name>.s3-website-<region>.amazonaws.com
  4. Use the s3api call to set the redirect

    aws s3api put-object --acl public-read --website-redirect-location "http://other-location.com" --bucket foo-bucket --key somewhere/blah

Note: You don't post any object to S3, because it will only serve a 301 and redirect Location header.

Test with

curl -v 2 -L https://<bucket_name>.s3-website-<region>.amazonaws.com/somewhere/blah

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top