0

I have an AWS S3 bucket set up as a web site. It is using Route 53 for DNS and using AWS Certificate Manager for SSL certificates. The public site is a CloudFront distribution of the S3 website bucket using HTTPS. The distribution is set up to redirect HTTP to HTTPS. This entire AWS configuration is set up programmatically using the AWS Java SDK v2 (although this is not relevant to the issue, as I can verify all this manually via the AWS web console).

I have tried two types of redirects from foo.html to bar.html, both successful:

  • Redirect using routing rules with <ReplaceKeyWith>bar.html</ReplaceKeyWith>, making sure to add a <HostName> (see more discussion on another Stack Overflow question).
  • Redirect using redirect S3 objects, with the redirect location set to /bar.html (because object redirects apparently require absolute paths).

Everything works fine except for one oddity: regardless of which redirect approach I use, when I redirect from foo.html to bar.html, even starting at an HTTPS URL, CloudFront will initially return an insecure HTTP-based indirect URL, which then redirects to the HTTPS URL, like this:

  1. https://example.com/foo.html redirects to
  2. http://example.com/bar.html redirects to
  3. https://example.com/bar.html

This occurs for both routing-rule redirects and S3 object redirects. I tested this using the network developer tools in both Chrome and Firefox on Windows 10.

Why is CloudFront providing the intermediate HTTP redirect? As my initial URL is using HTTPS, why doesn't it directly redirect to the HTTPS form?

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272

1 Answers1

0

Why is CloudFront providing the intermediate HTTP redirect?

No, it is the S3 handles the redirect, not CloudFront.

As my initial URL is using HTTPS, why doesn't it directly redirect to the HTTPS form?

In both of the redirection methods you tried, you can set the protocol to https, which will make your website redirect to an https URL directly.

For example, I have tested that the following routing rule will work as expected.

<RoutingRules>
  <RoutingRule>
    <Redirect>
      <HostName>www.example.com</HostName>
      <Protocol>https</Protocol>
      <ReplaceKeyWith>abc</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

The routing rule above generates the following 301 response header:

Location: https://www.example.com/abc

If you are using an object to do the redirection, you can add the prefix https to the value field corresponding to the Website-Redirect-Location key.

jellycsc
  • 10,904
  • 2
  • 15
  • 32
  • "No, it is the S3 handles the redirect, not CloudFront." I see what you're saying, but that can't be completely correct, because CloudFront is giving the redirect in terms of the end domain `example.com`, which the S3 bucket doesn't know about. So CloudFront must be doing some conversion. Maybe the S3 bucket gives an HTTP redirect (because the S3 website can only be in HTTP anyway) in terms of the bucket website URL, and CloudFront translates that to the front domain, but keeps the HTTP. – Garret Wilson May 10 '20 at 01:24
  • "If you are using an object to do the redirection, you can add the prefix https to the value field corresponding to the `Website-Redirect-Location key`." I guess you're saying I would have to construct the full CloudFront user-facing URL, then, right? I don't think just adding an `https:` prefix to the redirect path would work, would it? – Garret Wilson May 10 '20 at 01:26
  • @GarretWilson Yes, I mean the full url. – jellycsc May 10 '20 at 01:45
  • 1
    @GarretWilson No, CloudFront doesn't do any protocol conversion on the response sent from the origin. – jellycsc May 10 '20 at 01:49
  • I understand everything and this is helpful. "CloudFront doesn't do any protocol conversion on the response sent from the origin." Not to belabor the point, that's probably true that CloudFront doesn't change the protocol (which is the source of my problem), but I think it's interesting that with object redirects CloudFront must be recognizing that the S3 bucket redirect points to the same S3 bucket domain, and subsequently changes the URL _domain_ to match the CloudFront domain being served. But yeah, it looks like I'll have to just provide a full URL with the correct `https:` scheme. – Garret Wilson May 10 '20 at 02:02
  • @GarretWilson you're overlooking something or have made an observational error, because CloudFront most assuredly does not perform the domain rewrite you are imputing to it. – Michael - sqlbot May 10 '20 at 03:23
  • @Michael-sqlbot, I may indeed have made some testing error, as I now can no longer reproduce the `Website-Redirect-Location` problem; on a new CloudFront deployment, `/old` redirects to `/new` staying with the same URL scheme because (importantly) the redirect target is a URI reference path, and apparently S3 just sends this back as the `Location` header with no modification, allowing CloudFront to resolve it to the user-facing URL. – Garret Wilson May 10 '20 at 18:25
  • @jellycsc, I have confirmed that adding a `https` fixes the problem of an intermediate HTTP redirect with S3+CloudFront. Interestingly S3 using routing rule redirects seems to return, not a URI reference path, but instead constructs a full URI as the `Location` header of the 301 result (as opposed to object redirects). That is apparently why both a `` and `` must be specified so that CloudFront doesn't redirect incorrectly, since it's receiving a full redirect URL (not just a path). – Garret Wilson May 10 '20 at 18:27
  • "No, it is the S3 handles the redirect, not CloudFront." So now this statement can be qualified a bit. Yes, S3 handles the redirects, but if S3 sends back a full URI as it does with redirect routing rules, CloudFront is stuck with that literal URL; but if S3 sends back a URI _reference_ (a path, not a full URI) as it does for object redirects, CloudFront resolves this to the current CloudFront URL, thus maintaining the same host and scheme ("protocol"). – Garret Wilson May 10 '20 at 18:29
  • That's the browser doing that. CloudFront doesn't interpret, rewrite, or follow redirects. It just returns whatever the origin sent, and browsers know what to do when presented with only a path in the `Location` header. – Michael - sqlbot May 10 '20 at 21:58