I have a single-page app that lives in S3, fronted by Cloudfront. There's also a backend that the SPA talks to via AJAX requests. I'm trying to both:
/api/*
to the server (like https://stackoverflow.com/a/42883221/1586229).Is it possible to accomplish both of these? The problem is that cloudfront will change even 403s and 404s that come from the api into 200 index.html
responses.
If this can't be done, can you recommend another way to accomplish what I'm trying to do?
This behavior can be accomplished with Lambda@Edge. Here's the plan:
Create a Lambda function that will be triggered on Origin Request (see diagram for where in the lifecycle that lands). Be sure to create it in us-east-1
, as that's the only region where Lambdas to be used in Lambda@Edge can be defined.
The function has the following job: rewrite requests to paths like /login
, /profile
, /anything_other_than_assets
into /index.html
. For me, I was able to make the rule:
Something is an asset if it has an extension. Otherwise, it's a path
Hopefully, you can do the same, or similar. Here's how my function body looked (I used node 8)
const path = require('path')
exports.handler = (evt, ctx, cb) => {
const {request} = evt.Records[0].cf
if (!path.extname(request.uri)) {
request.uri = '/index.html'
}
cb(null, request)
}
Make sure you "Publish a new version", and then copy the arn (found at the top of the page)
paste it in the "Lambda function associations" section of your S3 Origin's Behavior.
Because Lambda@Edge function associates are scoped to the Origin level, this redirect behavior won't affect your /api/*
behavior.
Make sure to remove the custom error handlers. You won't need them anymore for your S3 behavior, and you don't want them for your api behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With