Skip to content
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

rust-server-codegen: add support for @httpPayload in requests #1060

Merged
merged 7 commits into from
Jan 17, 2022

Conversation

david-perez
Copy link
Contributor

This commit adds support for the httpPayload Smithy trait when applied
to operation input members (request deserialization).

The code to deserialize HTTP-bound data from HTTP responses in
ResponseBindingGenerator.kt has been moved into a common class,
HttpBindingGenerator.kt, since it's useful for both clients and
servers in deserializing data from HTTP requests and responses,
respectively.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

This commit adds support for the `httpPayload` Smithy trait when applied
to operation input members (request deserialization).

The code to deserialize HTTP-bound data from HTTP responses in
`ResponseBindingGenerator.kt` has been moved into a common class,
`HttpBindingGenerator.kt`, since it's useful for both clients and
servers in deserializing data from HTTP requests and responses,
respectively.
@david-perez david-perez requested review from a team as code owners January 11, 2022 16:57
@github-actions
Copy link

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

Copy link
Contributor

@crisidev crisidev left a comment

Choose a reason for hiding this comment

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

Minor comments. LGTM.

Comment on lines +566 to +574
val docShapeHandler: RustWriter.(String) -> Unit = { body ->
rust(
"#T($body)",
structuredDataParser.documentParser(operationShape),
)
}
val structureShapeHandler: RustWriter.(String) -> Unit = { body ->
rust("#T($body)", structuredDataParser.payloadParser(binding.member))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, do you really need to explicitly set the types here? We don't really do it anywhere..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You mean the type of the function RustWriter.(String) -> Unit? Type inference fails if I omit the signature.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, that's what I meant. Thanks for thee clarification.

/**
* This class generates Rust functions that deserialize data from an HTTP message.
* They are useful for *both*:
* - servers (that deserialize HTTP requests); and
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* - servers (that deserialize HTTP requests); and
* - servers (that deserialize HTTP requests).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All these are sentences split across bullet points. The style is:

* item 1,
* item 2,
* ...
* item n-1; and
* item n.

where and can of course be any other grammatical conjunction.

Or:

* item 1,
* item 2,
* ...
* item n-1; and
* item n

if the sentence continues past the bullet points and ends in the next line.

I don't think there's an agreed upon standard, but some formal / technical writing does use this style.

I don't have strong opinions on this, I just try to be consistent.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have no strong opinions as well. It just feels weird to me, but not a blocker. Same for the rest below.

/**
* The type of HTTP message from which we are deserializing the HTTP-bound data.
* We are either:
* - deserializing data from an HTTP request (we are a server); or
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* - deserializing data from an HTTP request (we are a server); or
* - deserializing data from an HTTP request (we are a server).

Comment on lines +67 to +69
* For deserialization logic that is wholly different among clients and servers, use the classes:
* - [ServerRequestBindingGenerator] from the `codegen-server` project for servers; and
* - [ResponseBindingGenerator] from this project for clients
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* For deserialization logic that is wholly different among clients and servers, use the classes:
* - [ServerRequestBindingGenerator] from the `codegen-server` project for servers; and
* - [ResponseBindingGenerator] from this project for clients
* For deserialization logic that is wholly different among clients and servers, use the classes:
* - [ServerRequestBindingGenerator] from the `codegen-server` project for servers.
* - [ResponseBindingGenerator] from this project for clients.

Comment on lines 89 to 91
* Generate a function to deserialize [binding] from HTTP headers
*
* The name of the resulting function is returned as a String
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* Generate a function to deserialize [binding] from HTTP headers
*
* The name of the resulting function is returned as a String
* Generates a function to deserialize [binding] from HTTP headers.
*
* The name of the resulting function is returned as a String.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved ResponseBindingGenerator.kt to HttpBindingGenerator.kt; all the existing comments use the imperative. I'll add the full stops though.

// of an empty instance of the response type.
withBlock("(!body.is_empty()).then(||{", "}).transpose()") {
when (targetShape) {
// TODO What if targetShape is set/map/list ?
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, was reading the code and forgot to test that.

Turns out that if you try to target a set/map/list, you get:

ERROR: com.amazonaws.simple#HealthcheckInputRequest$payload (ProtocolHttpPayload)
     @ /local/home/davidpz/workplace/smithy-ws/src/SmithyRsSource/codegen-server-test/model/simple.smithy
     |
  36 |     payload: StringList
     |     ^
     = AWS Protocols do not support applying the httpPayload trait to members that target sets, lists, or maps.

Which I didn't know, but it's called out in the protocol e.g. restJson1. We only offer support for AWS protocols:

Projection simple failed: software.amazon.smithy.codegen.core.CodegenException: No matching protocol ? service offers: []. We offer: [aws.protocols#awsJson1_0, aws.protocols#awsJson1_1, aws.protocols#awsQuery, aws.protocols#ec2Query, aws.protocols#restJson1, aws.protocols#restXml]

So I'll just leave a comment documenting this fact.

@github-actions
Copy link

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

@github-actions
Copy link

A new doc preview is ready to view.

Copy link
Contributor

@crisidev crisidev left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions
Copy link

A new generated diff is ready to view.

@github-actions
Copy link

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

@github-actions
Copy link

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

Copy link
Collaborator

@rcoh rcoh left a comment

Choose a reason for hiding this comment

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

httpbinding refactoring lgtm

@david-perez david-perez added the server Rust server SDK label Jan 12, 2022
@guymguym
Copy link
Contributor

guymguym commented Jan 16, 2022

Hi @david-perez
Is there any overlap with my PR #1023?
Should I change anything? Thanks

@david-perez
Copy link
Contributor Author

@guymguym Ah yes, the logic for setting headers that you copied over in your PR should be moved to the class HttpBindingGenerator.kt this PR introduces, since it's useful for both clients and servers. That would resolve my comment here #1023 (comment)

I also need to set headers in responses, to resolve #1071 and #1075, so I'll merge this PR and work on moving header-setting to HttpBindingGenerator.kt so that you'd only have to rebase your PR. I'll start today.

@github-actions
Copy link

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

@david-perez david-perez merged commit 8524446 into main Jan 17, 2022
@david-perez david-perez deleted the davidpz-http-payload-requests branch January 17, 2022 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
server Rust server SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants