Skip to content

[WIP] Consistently resolve binary aliases in requests and responses#99

Closed
pkoenig10 wants to merge 2 commits into
palantir:developfrom
pkoenig10:voidAccept
Closed

[WIP] Consistently resolve binary aliases in requests and responses#99
pkoenig10 wants to merge 2 commits into
palantir:developfrom
pkoenig10:voidAccept

Conversation

@pkoenig10

Copy link
Copy Markdown
Member

Follow up to #92 to correctly implement the conjure spec:

Accept header - Clients MUST send an Accept: application/json header for all requests UNLESS the endpoint returns binary, in which case the client MUST send Accept: application/octet-stream. This ensures changes can be made to the wire format in a non-breaking way.

This is consistent with the behavior of other generated clients:

TypeMapper returnTypeMapper,
TypeMapper methodTypeMapper) {
boolean returnsBinary = endpointDef.getReturns()
.map(type -> type.accept(TypeVisitor.IS_BINARY))

@iamdanfox iamdanfox Nov 6, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we make sure this still works if the endpoint returns an alias of binary? Might be able to use the DealiasingTypeVisitor

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is the same behavior as the Jersey service generator:

if (endpointDef.getReturns().map(type -> type.accept(TypeVisitor.IS_BINARY)).orElse(false)) {
methodBuilder.addAnnotation(AnnotationSpec.builder(ClassName.get("javax.ws.rs", "Produces"))
.addMember("value", "$T.APPLICATION_OCTET_STREAM", ClassName.get("javax.ws.rs.core", "MediaType"))
.build());
}

Correctly resolving aliases when settings the response media type is separate from this PR. But I'm not sure it is the correct thing to do. Aliases are completely separate types that wrap the type they are aliasing. You can't stream an alias of a binary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As a general rule of thumb, we try to make sure that aliases are pretty transparent so an alias of X should behave as much as possible like X.

We rely on this assumption in the conjure backcompat checker, where introducing an alias is generally considered to be backwards compatible.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We currently resolve aliases for binary return types, but not for binary body parameters. It seems to me that we would want be handle both cases identically. Should we also be resolving aliases for binary body parameters?

@pkoenig10 pkoenig10 requested a review from a team as a code owner November 17, 2018 01:46
@pkoenig10

Copy link
Copy Markdown
Member Author

I've updated this PR to include the following fixes:

  • Correctly set the Accept header for retrofit clients (see PR description)
  • Add the @Streaming annotation to retrofit endpoints returning a binary alias
  • Resolve binary alias body parameters for jersey and retrofit clients (do we want this?)

@Path("catalog/datasets/upload-raw-aliased")
void uploadAliasedRawData(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@NotNull InputStream input);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Before this change, this would be generated as NestedAliasedBinary

@ferozco

ferozco commented Nov 29, 2018

Copy link
Copy Markdown
Contributor

Historically, we have treated binary and alias of binary differently. Long term, we want to aliases be completely transparent but I don't think this PR is the place to make that change

@pkoenig10

Copy link
Copy Markdown
Member Author

Currently they are treated differently for input types but not for returned types. I made this change in response to @dfox's comment above.

I just want clarification on the desired outcome here:

  • Resolve neither returned nor parameter binary types
  • Resolve only returned binary types (the current behavior)
  • Resolve both returned and parameter binary types (the current impl of this PR)

@ferozco

ferozco commented Nov 29, 2018

Copy link
Copy Markdown
Contributor

Aliases of binary are currently treated differently from raw binary, even for return types since it is not dealiased: jersey, retrofit.

I'm advocating for keeping the current behaviour with the intention of fixing the the inconsistency later

@pkoenig10

pkoenig10 commented Nov 29, 2018

Copy link
Copy Markdown
Member Author

Aliases of binary are currently treated differently from raw binary, even for return types

This is not entirely true:
https://github.com/palantir/conjure-java/blob/2.5.0/conjure-java-core/src/test/resources/test/api/TestService.java.jersey#L58-L69

The check you linked is only used to decide whether or not to add the @Produces annotation. This is a correctness issue. We claim to return an application/json type but actually return an application/octet-stream.

For aliased types we should either do both or neither of:

  • Change the return type to StreamingOutput
  • Add a @Produces annotation with application/octet-stream

@pkoenig10 pkoenig10 changed the title [fix] Always set Accept header for Retrofit clients [WIP] Consistently resolve binary aliases in requests and responses Dec 4, 2018
@pkoenig10

Copy link
Copy Markdown
Member Author

This should be rebased on #127

@pkoenig10

Copy link
Copy Markdown
Member Author

Closing for now

@pkoenig10 pkoenig10 closed this Dec 4, 2018
bulldozer-bot Bot pushed a commit that referenced this pull request Dec 4, 2018
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