6 ms·
The irony in this is that with CloudFront at least, it can't strip the "/api" prefix before sending it to your backend, so you have to have your backend server
by herpderperator 5y ago
The irony in this is that with CloudFront at least, it can't strip the "/api" prefix before sending it to your backend, so you have to have your backend server understand /api/xyz rather than just /xyz calls like when it was on a dedicated api subdomain.
But don't worry! AWS thought of this! They invented Another Cloud Thing, namely Lambda@Edge, to solve this. Now you can run a JS function for every single request that hits your CloudFront Distribution so that you can run logic in there to strip the prefix before it gets passed to your origin. You read that right! Execute code every time a request hits your proxy! But wait, doesn't executing code for every single request sound insane AND doesn't it also add latency which this was trying to remove? Yes! Isn't cloud just lovely?
- Cthulhu_ 5y agoCloudFront is a CDN, it should cache static resources, not so much manipulate incoming requests - that's more a job for a load balancer / proxy like Elastic Load Balancer.
- youngtaff 5y agoCloudFront is CDN with limited features, other CDNs (Akamai, Fastly etc) are more than capable of manipulating incoming requests
- Tea418 5y agoFully agree here: I don’t expect anything else but reliable and performant HTTP caching from a CDN like CloudFront. Request manipulation is not the duty of a cache - even though other CDN providers mix request manipulation functionality with caching. In my opinion, they don’t need to be in the same product. If you still need request manipulation, because you don’t control the origin or you don’t want to introduce another service between CloudFront and the origin, you would use CloudFront Functions, which is cheaper than Lambda@Edge and easy to set up.
- herpderperator 5y agoCloudFront Distributions cannot pass the request to CloudFront Functions before sending to the origin. In other words, they cannot be used to modify origin request/responses. They can only modify the viewer request/responses. [0] Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1] [0] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope... [1] https://aws.amazon.com/blogs/architecture/serving-content-using-fully-managed-reverse-proxy-architecture/ https://aws.amazon.com/blogs/architecture/serving-content-us...
- antihero 5y agoWhich is why CloudFront and Lambda are separate products. Lambda@Edge simply combines them.
- QuiiBz 5y agoSimilar to Lambda@Edge, Cloudflare also offers Workers (https://workers.cloudflare.com/ https://workers.cloudflare.com/) which is the same thing, but only with a JavaScript runtime (no nodejs, they use V8), so I believe that it's significantly faster.
- jhugo 5y agoCloudFront has CloudFront Functions now which is similar; a very stripped-down JS environment that runs at the edge locations.
- herpderperator 5y agoCloudFront Distributions cannot pass the request to CloudFront Functions before sending to the origin. In other words, they cannot be used to modify origin request/responses. They can only modify the viewer request/responses. [0] Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1] [0] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope... [1] https://aws.amazon.com/blogs/architecture/serving-content-using-fully-managed-reverse-proxy-architecture/ https://aws.amazon.com/blogs/architecture/serving-content-us...
- jhugo 5y agoA viewer request function can, of course, be used to modify the request before it is sent to the origin. The difference is only related to caching — viewer request happens before the cache lookup, origin request happens after the cache lookup when CF has decided to make an origin request. For the stated purpose, either function is fine: With Lambda@Edge you'd use origin request if you were caching these paths, because your function would be called less often so your costs would be lower. With CF Functions you can only do the pre-cache-lookup modification, so it will be called for every request, but the cost is much lower than Lambda@Edge so it may not matter, and maybe you were not caching these paths anyway in which case it's virtually identical.
- forty 5y agoI don't want to argue that the feature should be built in (and most importantly free, because that's something you forgot to mention, those lamdba functions are paid for each run) but > doesn't executing code for every single request sound insane How would you strip some url path without executing code for every single request? It could be code you did not write, but some code is always needed to do something. If latency of lamdba@edge is an issue, you can try CloudFront functions, which should be better for small tasks like this (though I don't have any experience with them as we switched to a similar competitor)
- 9dev 5y agoI don't know. This doesn't feel like something that should require edge logic. nginx handles this with a single rewrite directive, so I'd expect some part of the AWS routing layer to have a setting to rewrite the URL accordingly. OTOH, AWS can't and shouldn't account for every edge case, probably.
- spullara 5y agoA rewrite directive is just writing code.
- 9dev 5y agoRewrite directives handled by low-level routing logic of the web server are definitely different to a container image that gets spun up in a distributed network and queried for each request, don't you think?
- scubbo 5y agoNot really, no. In fact the only significant difference (that the Lambda@Edge function is run at the closest geolocation to the client, rather than on the origin server) is an advantage to Lambda@Edge. What difference are you alluding to?
- 5y ago
- CSDude 5y agoNot sure why you cannot strip in your backend, and it's a huge deal. Code needs to be run somewhere though. While Lambda@Edge sucks, Cloudfront runs functions now which is not Lambda@Edge, and faster because it executes on the PoP location. https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/ https://aws.amazon.com/blogs/aws/introducing-cloudfront-func...
- herpderperator 5y agoCloudFront Distributions cannot pass the request to CloudFront Functions before sending to the origin. In other words, they cannot be used to modify origin request/responses. They can only modify the viewer request/responses. [0] Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1] [0] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope... [1] https://aws.amazon.com/blogs/architecture/serving-content-using-fully-managed-reverse-proxy-architecture/ https://aws.amazon.com/blogs/architecture/serving-content-us...
- CSDude 5y agoI've just tried it. The following function works exactly as-is when the function is configured as Viewer request. I changed it to append some text to URL. See: https://github.com/aws-samples/amazon-cloudfront-functions/blob/main/url-rewrite-single-page-apps/index.js https://github.com/aws-samples/amazon-cloudfront-functions/b...
- herpderperator 5y agoThat MODIFIES a viewer request, resulting in a viewer redirect. We want to keep the viewer request the same, i.e. with /api, and strip it only from the backend origin request. The viewer request is the one you make from the client, with /api. The origin request is the one CloudFront sends to your backend, which, without using Lambda@Edge via the origin request, will get sent as-is with the /api prefix. You have to strip it from the origin request. If you strip /api from the viewer request, your `domain.com/api/users` request becomes a redirect to `domain.com/users` which results in a call to your frontend instead of your backend. The example you referenced solves a completely different issue, not the one we are talking about.
- Jenk 5y agoCrafty alternative: just.. don't strip it? It seems like a perfectly reasonable and simple route that avoids complexity and cost to just keep /api.
- miyuru 5y agoWe ran into the same issue and we had to use API gateway to rewrite urls. but it had the added benefit of handling CORS there and the preflight requests never hits the application servers. Additionally preflight requests are cached at cloudfront and at browser with "Access-Control-Max-Age" and for the first request we do pre connect during the main domain load so the users never notice the small latency it may have. I agree that AWS products are all over the place.
- datavirtue 5y ago"AWS products are all over the place." It's the customers. They run into issues using something against all advice in the docs and then request features and services or AWS sees all the clamor around a perceived issue and they create a "solution." Developers are really averse to reading and understanding documentation. It's why they all jumped on the cloud. But it turns out it isn't all just magical infinite performance. Is your lambda awake?
- rndgermandude 5y ago>But don't worry! I don't, I can just teach my backend to process /api. The backend is running code under my control anyway. This seems like one of the least difficult "problems" to solve in any non-trivial codebase.
- 867-5309 5y ago>doesn't executing code for every single request sound insane AND doesn't it also add latency which this was trying to remove? Yes! but surely executing code at the source of your web app is more efficient than having the client and server attempt to perform it? faster than 40-90ms per request at least
- philliphaydon 5y agoIn asp.net we just use: app.UsePathBase("/api"); And we have 0 issues.
- fivea 5y ago> They invented Another Cloud Thing, namely Lambda@Edge, to solve this. Yes, designed for usecases like those handled by Cloudflare Workers, which boil down to updating data cached in edge servers without requiring global redeployments or pinging a central server. We're talking about stuff like adding timestamps to images or adding headers to HTTP responses or pre-rendering some HTML or emit CDN-aware metrics. > Now you can run a JS function for every single request that hits your CloudFront Distribution Not exactly. Lambda@Edge are event handlers from CDN events. You use them when they suit your needs. > so that you can run logic in there to strip the prefix before it gets passed to your origin. Your strawman example doesn't even feature among the dozen examples provided by AWS regarding how to use Lambda@Edge. Everyone is free to come up with silly ideas and absurd examples, but if you design systems around braindead ideas then that says a lot about you and nothing about the tools you chose to abuse > You read that right! Execute code every time a request hits your proxy! Yes, that's what web servers do. What exactly is your point? > But wait, doesn't executing code for every single request sound insane It doesn't. That's what a web server does. Moreso, Lambda@Edge (and Cloudflare Workers too) only do it if you explicitly decide to make them do it, to match precisely what you tell them to do. What point are you trying to make, exactly? > AND doesn't it also add latency which this was trying to remove? It does. It adds tens of milliseconds when the alternatives can add hundreds of milliseconds. You're also expected to do basic engineering work and do basic performance work when seeking performance improvements, such as measuring things instead of mindlessly jumping on bandwagons without caring for the outcome. > Isn't cloud just lovely? I feel your comment manifests too much cinicism to cover too much ignorance on a topic you are not familiar nor understand the basic premise.
- herpderperator 5y agoYou shouldn't be so stern. The use case I provided is AWS's recommended way to solve this problem[0]. :) > Yes, designed for usecases like those handled by Cloudflare Workers, which boil down to updating data cached in edge servers without requiring global redeployments or pinging a central server. We're talking about stuff like adding timestamps to images or adding headers to HTTP responses or pre-rendering some HTML or emit CDN-aware metrics. > Not exactly. Lambda@Edge are event handlers from CDN events. You use them when they suit your needs > Your strawman example doesn't even feature among the dozen examples provided by AWS regarding how to use Lambda@Edge. For all of these counterpoints, see [0]. > Everyone is free to come up with silly ideas and absurd examples, but if you design systems around braindead ideas then that says a lot about you and nothing about the tools you chose to abuse I take it you are directing this particular comment at AWS considering they are recommending this solution? [0] > Yes, that's what web servers do. What exactly is your point? Don't be daft. You know what I mean. Obviously web servers execute code. In this case the web server (CloudFront Distribution) is passing the request to yet another "thing" which happens to be a JS function that is invoked specifically to handle something web servers like nginx were built to do extremely efficiently on their own. CloudFront could easily support this without additional dependencies that add complexity to your system design and introduce additional failure modes. In this case, I am making your point for you: using Lambda@Edge for this IS ridiculous, but that's the AWS way. > It doesn't. That's what a web server does. Moreso, Lambda@Edge (and Cloudflare Workers too) only do it if you explicitly decide to make them do it, to match precisely what you tell them to do. > It does. It adds tens of milliseconds when the alternatives can add hundreds of milliseconds. You're also expected to do basic engineering work and do basic performance work when seeking performance improvements, such as measuring things instead of mindlessly jumping on bandwagons without caring for the outcome. Sorry for not writing a detailed blog post to describe all of my findings. FYI, the latency added with Lambda@Edge caused my request time to double and added much more variance. I'm surprised a lot of your counterpoints are just blaming me for doing the wrong thing, when this is actually what is recommended by AWS. Invoking a custom function to process the request. See [0]. Of course the right solution is to use nginx (but then you lose out on AWS scaling) or completely redesign your system to fit another solution like API Gateway. From AWS's blog: > In this scenario we can use Lambda@Edge to change the path pattern before forwarding a request to the origin and thus removing the context. For details on see this detailed re:Invent session. [0] [0] https://aws.amazon.com/blogs/architecture/serving-content-using-fully-managed-reverse-proxy-architecture/ https://aws.amazon.com/blogs/architecture/serving-content-us...
- dragonwriter 5y ago> But don't worry! AWS thought of this! They invented Another Cloud Thing, namely Lambda@Edge, to solve this. No, CloudFront Functions is the Another Cloud Thing AWS invented more specifically for this use case. Lambda@Edge is the older and more general purpose edge computing facility. > You read that right! Execute code every time a request hits your proxy! Any rewrite rule in any platform, and heck, any other functionality provided by the distribution, is executing code every time it gets a request (whether or not you are writing code for the purpose.)
- herpderperator 5y agoCloudFront Distributions cannot pass the request to CloudFront Functions before sending to the origin. In other words, they cannot be used to modify origin request/responses. They can only modify the viewer request/responses. [0] Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1] [0] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope... [1] https://aws.amazon.com/blogs/architecture/serving-content-using-fully-managed-reverse-proxy-architecture/ https://aws.amazon.com/blogs/architecture/serving-content-us...