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

feat(spec): allow defining custom media type of responses + fix(koa): dont overwrite content-type of response #1129

Merged
merged 3 commits into from
Nov 15, 2021

Conversation

mrl5
Copy link
Contributor

@mrl5 mrl5 commented Nov 8, 2021

problem description: currently application/json is hardcoded into generated spec

proposed solution: allow specifying custom media type in generated spec
on both controller level by:

  • using new @Produces decorator

and on method level by:

  • using new @Produces decorator
  • introducing new optional arg for @SuccessResponse decorator
  • introducing new optional arg for @Response decorator
  • setting Content-Type header in @Res decorator

impact:

  • cli: controller generator
  • cli: method generator
  • cli: parameter generator
  • cli: spec2 generator
  • cli: spec3 generator
  • runtime: response decorators

Closes #1126
Related #968

All Submissions:

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?
  • Have you written unit tests?
  • Have you written unit tests that cover the negative cases (i.e.: if bad data is submitted, does the library respond properly)?
  • This PR is associated with an existing issue?

Closing issues

  • Put closes #XXXX (where XXXX is the issue number) in your comment to auto-close the issue that your PR fixes.

If this is a new feature submission:

  • Has the issue had a maintainer respond to the issue and clarify that the feature is something that aligns with the goals and philosophy of the project?

Potential Problems With The Approach

  1. Someone could think that defining custom media type will also override content-type of actual response (which is not a case). However I don't think it's a problem -> if you check the issues from the past you will see that writing custom methods was encouraged - for example Send file / return raw binary "application/octect-stream" or "image/jpeg" ... #44 Return HTML from controller #224
  2. OAS2 is not affected by this changes
  3. I wasn't able to introduce new arg for setting custom media type for @Res decorator

Test plan

  1. I've tried to show that it is possible to set @Produces on controller level
  2. I've tried to show that even when @Produces is set on controller level it is possible to set it also for specific method
  3. I've tried to show that OAS3 media type of responses is possible to be changed by passing new optional arg in @Response and @SuccessResponse decorators
  4. I've tried to show that OAS3 media type of responses is possible to be changed by defining headers for @Res decorator

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Hello there mrl5 👋

Thank you and congrats 🎉 for opening your first PR on this project.✨

We will review the following PR soon! 👀

@dderevjanik
Copy link
Contributor

dderevjanik commented Nov 9, 2021

@mrl5 very nice PR!
I'm just curious, what's the reason behind @MediaType decorator? I mean, most frameworks (jersey, spring, asp.net, nestjs, etc.) are using @Produces or @ProducesSomething wording - so you can distinguish between @Consumes.

In case that TSOA will support @Consumes in future, IMHO it could be confusing to have something like this in controller:

 @Get('process')
 @Consumes('image/png')  // Consumes MediaType
 @MediaType('text/plain') // Produces MediaType
  public async processImage(@Request() request: ExRequest): Promise<string> {
    // code
    return '';
  }

Instead of this

 @Get('process')
 @Consumes('image/png')  // Consumes MediaType
 @Produces('text/plain') // Produces MediaType
  public async processImage(@Request() request: ExRequest): Promise<string> {
    // code
    return '';
  }

@mrl5
Copy link
Contributor Author

mrl5 commented Nov 10, 2021

thanks for code review @dderevjanik - I agree that @Produces and @Consumes are more accurate. I will change that

I'm just curious, what's the reason behind @MediaType decorator?

I was inspired by the code snippets from #968

@WoH is it ok to git commit --amend not to produce commit flood on every improvement or you prefer to keep it separated?

@WoH
Copy link
Collaborator

WoH commented Nov 10, 2021

Amending and rebasing is fine

@mrl5
Copy link
Contributor Author

mrl5 commented Nov 11, 2021

  1. pushed improvements suggested by @WoH and @dderevjanik
  2. updated PR description
  3. added possibility to define @Produces on controller level

@mrl5 mrl5 changed the title feat(swagger): allow defining custom media type of responses feat(swagger3): new Produces decorator that allows defining custom media type of responses Nov 11, 2021
@mrl5
Copy link
Contributor Author

mrl5 commented Nov 12, 2021

pushed additional commit that:

  1. fixes issue koa integration overwrites content-type of response #1134
  2. introduces integration tests checking content-type

@mrl5 mrl5 changed the title feat(swagger3): new Produces decorator that allows defining custom media type of responses feat(swagger3): allow defining custom media type of responses + fix(koa): dont overwrite content-type of response Nov 12, 2021
definitions: this.buildDefinitions(),
info: {
title: '',
},
paths: this.buildPaths(),
produces: ['application/json'],
produces: [DEFAULT_RESPONSE_MEDIA_TYPE], // todo: Tsoa.Response.produces
Copy link
Collaborator

Choose a reason for hiding this comment

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

A list of MIME types the APIs can produce.
This is global to all APIs but can be overridden on specific API calls.
Value MUST be as described under Mime Types.

Maybe I'm interpreting too much, but we should be able to leave this as is, remove the todo and override on path.method.produces?

packages/cli/src/swagger/specGenerator2.ts Outdated Show resolved Hide resolved
mrl5 added 2 commits November 14, 2021 17:48
problem description: currently `application/json` is hardcoded into generated
spec

proposed solution: allow specifying custom media type in generated spec
on both controller level by:
  - using new `@Produces` decorator

and on method level by:
  - using new `@Produces` decorator
  - introducing new optional arg for `@SuccessResponse` decorator
  - introducing new optional arg for `@Response` decorator
  - setting `Content-Type` header in `@Res` decorator

impact:
  - cli: controller generator
  - cli: method generator
  - cli: parameter generator
  - cli: spec2 generator
  - cli: spec3 generator
  - runtime: response decorators

Closes #1126
Related #968
problem description: as described in
koajs/koa#1120 currently `koa` always
overwrites `Content-Type` for JSON responses.

proposed solution: workaround discovered by @brunoabreu is to set
headers after setting the body.

Closes #1134
Related #1129
@mrl5
Copy link
Contributor Author

mrl5 commented Nov 14, 2021

  1. amended with changes from code review
  2. updated PR description

thanks @WoH for detailed CR :) I hope we're good to go now

@mrl5 mrl5 changed the title feat(swagger3): allow defining custom media type of responses + fix(koa): dont overwrite content-type of response feat(spec): allow defining custom media type of responses + fix(koa): dont overwrite content-type of response Nov 14, 2021
suggested by @WoH during code review

Co-authored-by: Wolfgang Hobmaier <[email protected]>
@WoH WoH merged commit b0cd953 into lukeautry:master Nov 15, 2021
@WoH
Copy link
Collaborator

WoH commented Nov 15, 2021

Thanks for this PR and your patience during the review, much appreciated. Great Work!

@mrl5 mrl5 deleted the issue-1126 branch November 21, 2021 16:54
@alberto-rubio
Copy link

Please, @mrl5 and @WoH, is this working in version 4.0.0-alpha.2? I'm adding the decorator:
@Produces('text/event-stream')
at method level, but it continues producing "application/json" in the generated openapi yaml definition.

Should I do any additional thing to see "text/event-stream" in the generate openapi?

Thanks and best regards!!

@mrl5
Copy link
Contributor Author

mrl5 commented Jan 21, 2022

hi @alberto-rubio - I think that this changes are already included in this version. It's hard to help you w/o seeing any example code that is producing unexpected results

if you need example you can study this file that is used in unit tests to ensure that feature introduced in this PR works:

@Get('Custom/security.txt')
@Produces('text/plain')
public async getCustomProduces(): Promise<string> {

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.

support: how to set correct content type in generated oas3
4 participants