Skip to content

support both apigw and alb events as http::{Request,Response} #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 2, 2019

Conversation

softprops
Copy link
Contributor

@softprops softprops commented Dec 28, 2018

Issue #, if available:

Description of changes:

This is a follow up to some commentary from the initial lambda-http pull about supporting alb events. Below are some notes and some potential changes I considered

There's a great series of posts I lifted my knowledge of the differences between the two ( there are a few ) here. I'd give that a quick read before looking at this.

There is one case where knowledge needs transfered about the request in order to serialize the response for alb requestsstatusDescription.

stage variables and path parameters are features specific to apigateway so these request ext methods will be empty for alb requests ( have some thoughts about this below ).

the request context is uber rich for api gateway but slim for alb. Im supporting both as an enumeration but not sure about this as a design choice ( have some thoughts on this below )

as a user of lambda I want the flexibility to switch between both alb and api gateway with minimal fuss. as a general goal here, if lambdas tag line is "write code without thinking about servers" I want this crate to represent "write (correct) http code without thinking about the inconsistencies between http lambda triggers ". I have some ideas for potential amendments made to choices made in this pull.

One may argue that is awkward to to work with the request_context if you know your application will always be triggered by an alb or always by an api gateway. Similarly it may feel awkward to have stage_variables and path_parameters as available methods in an alb only context. One possible solution is to amend some of these choices with cargo feature flags, One for apigw support and one for alb support. When provided in combination you get the interfaces in this pull. When provided separately you get just the features specific to that type of http event.

@davidbarsky let me know what you think.

By submitting this pull request

  • I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • I confirm that I've made a best effort attempt to update all relevant documentation.

@sapessi
Copy link
Contributor

sapessi commented Dec 28, 2018

I'm not sure I'd worry too much about portability between API Gateway and ALB. The reason is that if I choose API Gateway, I'll likely offload AuthN/AuthZ tasks to the Gateway and my Lambda function will rely on the context object to validate this. Especially if I use AWS_IAM as the auth strategy. On the other hand, with ALB I will only support bearer tokens. My point is, if they have decided to only rely on properties of the request and bearer tokens for auth, then their code is easily portable. If they have chosen API Gateway and rely on its context, they probably expect the migration to take some time and require code changes.

Having said that, I think the most important feature to abstract is the auth state. I just went through this in my serverless-java-container library and implemented Java's standard SecurityContext to support both API Gateway and ALB depending on the event (I look at the context to decide what's the source). You could create a similar abstraction here.

@softprops
Copy link
Contributor Author

Thanks for the feedback @sapessi.

I don't want to make this any more opinionated that it needs to be for now. For now we have an abstraction that let's rust developers that know the http crate be immediately familiar and productive but to also not restrict access to some of the decorations that come along with the request context/{querystring/path} parameters ect.

In practice I've used two methods for auth with lambda custom authorizer and auth0. I don't want to restrict what folks can and can't do. I think higher level abstractions could come from the http crate ecosystem and "just work" here.

I think for Meetup and potentially others the interest is more in the ability to flexibility experiment with one of the other for potential cost savings an integration needs. I'm really excited to see the potential for those with existing albs to have lambdas that can simply "plug into" exciting albs to help more easily break down legacy applications into smaller parts. We've being experimenting with api gateway for that with api gateway previously being the only option but some use cases may benefit more from the alb since we're already paying for that. Ideally we could switch back and forth with minimal code changes to facilitate experimentation.

I'm mainly looking for feedback on on the suggestion about the cargo feature to trim off the bits you know you'll likely not need if you're heavily invested in one or the other. I could do that in a followup but I think it'd also be straight forward to do in this pull. I wanted to wait on some feedback before I took a stab at that.

@davidbarsky
Copy link
Contributor

I’m not entirely sure that I agree with you, @sapessi. ALBs and API Gateway have been getting closer to one another over the years (i.e., both support OAuth authentication) and I’ve had two separate conversations inside of Amazon where folks wanted to swap out API Gateway with an ALB (and vice versa). I look forward to the day that we have a single story for L7 load balancing at Amazon.

@softprops Personally, I like the idea of a feature flag toggling between an ALB and API Gateway, as it allows—like you said—incremental migration of legacy applications and potential cost savings for higher-traffic applications.

@sapessi
Copy link
Contributor

sapessi commented Dec 28, 2018

Perhaps I wasn't clear - late night writing... I agree that feature flags are a good idea to make it easy to switch between versions of the crate. For AuthN/AuthZ, it may be a good idea to start thinking about a standard that could be included in the http crate. In Java this is the servlet specs and Jax-RS. If you can create a generic object such as the security context linked above, then you can implement it for both API Gateway and ALB as well as include it in regular http servers. The difference is that http servers will parse the bearer tokens and create it from scratch, with ALB/API GW you can populate it using the context. The only "unusual" case there is when API Gateway is configured with IAM auth, where it might be helpful to include more AWS-specific properties.

@softprops
Copy link
Contributor Author

awesome 👍 let me know if that's enough to be a blocker for this or could be a follow up. I'd be happy to do either. Im into fast iteration.

@softprops
Copy link
Contributor Author

Im actually starting to convince myself that conditional compilation may not be worth it for the added maintainability. I'll post another pull shortly to demonstrate for comparison and keep this branch clean

@sapessi
Copy link
Contributor

sapessi commented Dec 29, 2018

awesome 👍 let me know if that's enough to be a blocker for this or could be a follow up. I'd be happy to do either. Im into fast iteration.

No, don't think it's a blocker - just food for thought. I find the servlet and jax rs specification to be very good at what they do but even better at giving the community a set of common tools to build around.

@softprops
Copy link
Contributor Author

example with feature flags #65 ( just for comparison )

@softprops
Copy link
Contributor Author

. I find the servlet and jax rs specification to be very good at what they do but even better at giving the community a set of common tools to build around.

agreed. that's essentially what the http crate in the rust ecosystem today, a least common denominator for rust ecosystem libraries to build on top of

@softprops
Copy link
Contributor Author

@davidbarsky / @sapessi can you two take a peek over #65. I wanted to drop up a picture of what a cargo feature flag impl might look like before making more changes in this branch. #65 just builds on this an makes a best effort attempt at feature flagging the two http-like triggers

Copy link
Contributor

@davidbarsky davidbarsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look pretty good to me, tbh.

#[serde(default, deserialize_with = "nullable_default")]
pub(crate) multi_value_query_string_parameters: StrMap,
#[serde(deserialize_with = "nullable_default")]
/// alb events do not have path parameters
#[serde(default, deserialize_with = "nullable_default")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a nit and a thought:

  • in doc comments, can we use sentence casing? I'm not sure how to programmatically enforce this...
  • Situations like these—“ALB events don't have path parameters.“—make me think compile-time feature flags are the correct option, but I also don't see why API Gateway and ALBs can't converge on supported values. I don't have a good answer for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix. Note: this is a internal crate so its more like doc for maintainers than it is for users

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for programatic enforcement, there's nothing that can enforce that today but it would be an interesting thought experiment to sent the rustdoc team's way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix. Note: this is a internal crate so its more like doc for maintainers than it is for users

Fair point!

pub authorizer: HashMap<String, Value>,
pub api_id: String,
pub identity: Identity,
pub struct Elb {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit, and I know this is what Amazon calls it, maybe we shouldn't propagate that mistake here. Do you think this struct be called something LoadBalancerContext with a #[serde(rename = "elb")] attribute plopped on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidbarsky Do you mean the type of the field name?

Aside from letter casing rustc warnings, I'm a bit hesitant to rename these provided fields because these are what I users will find in documentation that comes from aws (across runtimes) in examples and other forms of documentation. My empathy here goes out to engineers that work across aws projects (and runtimes). I have the feeling renaming fields would require an extra overhead of how these map back to the source in developer heads.

I'm open to renaming types here but I'm going to try to debate the value of keeping the field names that represent the "shape" of data as close to the source as Rust will allow. Rustc will warn on not rusty letter casings so that I'm open to at least that much wiggle room.

Thoughts? If you mean the type. I'm down with that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from letter casing rustc warnings, I'm a bit hesitant to rename these provided fields because these are what I users will find in documentation that comes from aws (across runtimes) in examples and other forms of documentation. My empathy here goes out to engineers that work across aws projects (and runtimes). I have the feeling renaming fields would require an extra overhead of how these map back to the source in developer heads.

That's a good point to be honest. I don't have very strong opinions on that front. I think it's fine as is!

@davidbarsky
Copy link
Contributor

@softprops this looks good to me. Do you want to push any additional changes?

@softprops
Copy link
Contributor Author

Let's go! I'm all for iterations

@davidbarsky davidbarsky merged commit 6f693fb into awslabs:master Jan 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants