19

I am hosting a static website on Amazon S3. Some of my client-side javascript parses the query strings to control the HTML. This works fine locally, but on the S3-hosted version, the query strings seem to get dropped from the request.

My motivation for using query strings is that I want to be able to pass state between pages based on what the user did on the previous page.

Is this approach possible? Did I violate the "static" requirement for S3 static websites?

I can't seem to find any mention of general query strings in the S3 docs, aside from the authentication stuff, which I don't think solves my problem.

scott_ri
  • 488
  • 1
  • 5
  • 13
  • Is the querystring present in the link you click to go to the "next" page on your site (because the javascript is generating them), then disappears from the address bar before the page loads? And, are you using S3's index documents? – Michael - sqlbot Dec 23 '13 at 22:17
  • @Michael-sqlbot yes, that's right. I don't know what S3 index documents are, so I'm guessing I am not using them. I just followed the tutorial for building a static website on S3. – scott_ri Dec 24 '13 at 07:29
  • Index document: `http://example.com/foo` returns the html document at `http://example.com/foo/index.html`. Are you doing that? – Michael - sqlbot Dec 24 '13 at 13:56
  • Oh, yes, I am doing that. – scott_ri Dec 24 '13 at 15:03
  • Cross post... https://stackoverflow.com/questions/30775068/amazon-s3-redirect-rule-preserve-query-params – doublejosh Jan 19 '18 at 08:52

2 Answers2

41

If you are using index documents, where this...

http://bucket.example.com/foo

...actually displays the document at foo/index.html then your workaround will be to avoid the redirect that S3 does prior to displaying the index page.

For a link pointing to the page at /foo, you should actually create the link pointing to /foo/ instead (with the query string after the trailing slash; may look strange but it's quite valid). This is because when your browser requests a page that would result in an index document, but doesn't end in a trailing slash, S3 sends a redirect so that your browser has a trailing slash at the end of the URL. If not for this, relative links on that page would be referencing the wrong path.

The problem underlying the problem is that when S3 sends that redirect from /foo to /foo/, it strips the query string. They didn't have to design it that way, but that's what they did, and there does not appear to be a setting that modifies this behavior.

But if your link points directly to /foo/?some_thing=here&something_else=too instead of pointing to/foo?some_thing=here&something_else=too (no trailing slash before the ?) then the redirect is avoided and your query strings should stay intact.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • 2
    This was my experience too, but if you place CloudFront on top of S3 (which is cheap, easy, standard) you can indeed **"Forward Query Strings"** to preserve the parameters. – doublejosh Jan 19 '18 at 08:56
  • 4
    @doublejosh unless the behavior has changed, the problem is that *S3 itself* does not preserve the query string while generating the `Location` header, when you use index documents and don't include the trailing slash in the original URL... so having CloudFront forward them to S3 wouldn't change anything. (`/foo?bar=1` redirects to `/foo/` rather than `/foo/?bar=1` as might be expected, before rendering the object `foo/index.html`). – Michael - sqlbot Jan 19 '18 at 13:09
  • 1
    If you use CloudFront then the URL won't be served by S3... it will be served by CF on the edge... and the query string will remain intact. I've done this, and have found numerous posts on the web explain that as the solution. – doublejosh Jan 30 '18 at 07:05
  • 1
    @doublejosh I don't think we are talking about the same thing, here, but if you want to drop a link or two in the comments, I'll be happy to learn something new about the way these two services interact, and extend my answer if appropriate. – Michael - sqlbot Jan 30 '18 at 13:20
  • I added a cross post link to the original question previously. But now I feel like I'm stuck in a loop and losing confidence that my memory is accurate on this solution :/ – doublejosh Feb 03 '18 at 09:54
  • Indeed, regardless of CF, it still goes back to S3 and S3 will redirect to a path including the slash if not present, which does drop the query params. The only solution I've reasoned about is a CF edge lambda that rewrites any URLs missing a trailing slash, by adding one. Hacky but works. – Sean Jul 02 '21 at 00:14
6

You could switch to using an anchor/hash rather than a query string. For example, instead of

http://someS3domain.com?variable=1

you could use:

http://someS3domain.com#variable=1

The big difference between an anchor/hash versus a query string is that the query string is sent to the server and the anchor/hash is not. In your case, since you're using S3 for static hosting, you don't need the query string to be sent to the server anyways.

In Javascript, you can get the value of the anchor/hash string using:

window.location.hash
d2vid
  • 2,014
  • 1
  • 22
  • 25