7

I'm working on a ember-cli app that I am deploying in S3. I would really like to be able to use this 'serverless' approach, as it is extremely simple to configure, and extremely affordable.

I have a problem with URLs. If I hit http://my-bucket.s3-website-us-east-1.amazonaws.com/ it works just fine. But if I try to directly load a page other than the root of the application, such as http://my-bucket.s3-website-us-east-1.amazonaws.com/elephants/5, then it gives a 403, as there is no such resource in S3. (I can navigate to such pages fine through the application, and I can hit them directly in dev mode on my machine, so the ember app is working fine.)

Looking for solutions, I find suggestions to add #! to my path. This seems better, as it doesn't return a 403, but when I hit http://my-bucket.s3-website-us-east-1.amazonaws.com/#!/elephants/5, it simply redirects to http://my-bucket.s3-website-us-east-1.amazonaws.com, losing any specific information that the path contained.

What are my options? Is there a way to use S3 and have working URLs? Do I need a server? Or is there another approach that has eluded me?

Community
  • 1
  • 1
Eric Wilson
  • 57,719
  • 77
  • 200
  • 270
  • I'm doing `ember build --environment=production` then copying the `dist` folder to S3. I'm only using the node server for dev mode locally. (How S3 serves files I don't know.) – Eric Wilson Jan 09 '15 at 14:57
  • Glad you got it working! I'll delete the previous comments. :) – Hrishi Jan 09 '15 at 15:04

3 Answers3

6

There are few problems with the approach of just having a # based redirect. I have listed them below:

  1. Mutliple redirects happen as your app's paths are resolved. For example: www.myapp.com/path/for/test gets redirected as www.myapp.com/#/path/for/test
  2. There is a flicker in the url bar as the '#' comes and goes due the action of your SPA framework.
  3. The seo is impacted because - 'Hey! Its google forcing his hand on redirects'
  4. Safari support for your app goes for a toss.

An approach mutated off the Lightening deployment approach advocated with Ember-CLI-Deploy is as follow:

  1. Make sure you have the index route configured for your website. Mostly it is index.html
  2. Remove routing rules from S3 configurations
  3. Put a Cloudfront in front of your S3 bucket.
  4. Configure error page rules for your Cloudfront instance. In the error rules specify:
    • Http error code: 404 (and 403 or other errors as per need)
    • Error Caching Minimum TTL (seconds) : 0
    • Customize response: Yes
    • Response Page Path : /index.html
    • HTTP Response Code: 200

5.For SEO needs + making sure your index.html does not cache, do the following:

  • Configure an EC2 instance and setup an nginx server.
  • Assign a public ip to your EC2 instance.
  • Create an ELB that has the EC2 instance you created as an instance
  • You should be able to assign the ELB to your DNS.
  • Now, configure your nginx server to do the following things: Proxy_pass all requests to your CDN (for index.html only, serve other assets directly from your cloudfront) and for search bots, redirect traffic as stipulated by services like Prerender.io

I can help in more details with respect to nginx setup, just leave a note. Have learnt it the hard way.

Once the cloud front distribution update. Invalidate your cloudfront cache once to be in the pristine mode. Hit the url in the browser and all should be good.

moha297
  • 1,902
  • 1
  • 16
  • 16
  • > for search bots, redirect traffic as stipulated by services like Prerender.io Are you using prerender.io or redirecting bots to some other kind of cache? I had a look at the nginx config for redirecting here https://gist.github.com/thoop/8165802 – freedrull May 25 '16 at 23:25
  • Prerender maintains its own cache unless you decide to have an on premise installation. The config you shared - I use something similar in my nginx to serve the bot requests. It is not a redirection that happens but more like a proxy request forwarding to get the response from prerender cache. – moha297 Jun 01 '16 at 16:32
  • Thanks I will try it!! – freedrull Jun 03 '16 at 04:52
  • What happens if you have a request that is legitimately a 404, won't prerender/google cache the result? :\ Not sure if there is a work around for that. – freedrull Oct 30 '16 at 05:13
4

OK, I was close. Turns out that the right approach was:

http://my-bucket.s3-website-us-east-1.amazonaws.com/#/elephants/5

I had tried various approaches, but none of them had been precisely a # with no !, and surrounded by /. Relevant reading is the documentation on location

It is worth noting that I am using:

App.Router.reopen({
  location: 'auto'
});

Also, I'm using the following RoutingRules under Static Website Hosting

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>my-bucket.s3-website-us-east-1.amazonaws.com</HostName>
            <ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>
Eric Wilson
  • 57,719
  • 77
  • 200
  • 270
  • So does that mean that it's not possible to have Ember apps in production without this "annoying" little hash at the root of the path? – cwarny Jun 10 '15 at 20:17
  • I think that I've shared all that I know here, if you have read the contents of the link. – Eric Wilson Jun 10 '15 at 20:19
  • I did read the documentation, but setting `App.Router.reopen({ location: 'history' });` or `App.Router.reopen({ location: 'auto' });` did not work for me. Only `hash` did the trick and I'm not understanding why or if there's some additional manipulation I need to do that is not specified in the linked doc. It does say though `Keep in mind that since some of your users will use HistoryLocation, your server must serve the Ember app at all the routes you define.` but that seems awkward to me. – cwarny Jun 10 '15 at 20:27
  • Ah, I misunderstood. Sorry, it worked for me. My project is just a toy, so I'm not worried about if the `#` is necessary in some browser somewhere, I was able to eliminate it from mine with the `auto` thing. I'll add one detail to my answer that could help. – Eric Wilson Jun 10 '15 at 20:34
  • This portion is completely controlled by your web server, and not Ember. Essentially your server needs to know that any portion of the request past the root portion of your application in the url needs to be ignored, and just the root portion of the url needs to be served up, in the case of `auto` you are providing a mechanism for those whose browsers don't support `history` http://caniuse.com/#feat=history – Kingpin2k Aug 13 '15 at 13:08
2

Just make Error Document map to index.html & your locationType should be set to auto. https://i.stack.imgur.com/qbAov.png

Maulik Bengali
  • 117
  • 1
  • 2
  • Based on this SO (http://stackoverflow.com/a/16979716/4533488), this solution has some red flags associated with it, i.e. it's not a great solution. – aero Feb 10 '17 at 23:00