question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Swagger for api versioning based on custom headers only

See original GitHub issue

Please take the time to search the repository, if your question has already been asked or answered.

I have a question while working on version - v2.9.2

I’ve implemented a @Version annotation for api versioning. This checks for date in “version” header of request and based on date comparison selects v1, v2, or v3 by implementing a custom RequestMappingHandlerMapping in the background

The final request mappings after version processing looks like

V1:
"Mapped"{[/api/work/{vehicleId}],methods=[GET],produces=[application/json],custom=[com.work.version.service.VersionRequestCondition@390e814c]}"
 onto public org.springframework.http.ResponseEntity<com.work.models.WorkResponse>

V2:
"Mapped"{[/api/work/{vehicleId}],methods=[GET],produces=[application/json],custom=[com.work.version.service.VersionRequestCondition@1ed0128b]}"
 onto public org.springframework.http.ResponseEntity<com.work.models.WorkV2Response>

I am facing issue while creating dockets for both v1 and v2 as routes, methods, and produces are same but custom & responseEntity are different. As per the documentation we can use ApiSelectorBuilder to navigate based on produces but how do I select route based on custom or responseEntity.

Controller.class

V2

 @ApiOperation(value = "Work V2", notes = "", response = WorkV2Response.class)
 @Version(version = "2018-06-01")
 @RequestMapping(produces = { "application/json" }, method = RequestMethod.GET)
public ResponseEntity<WorkV2Response> getWorkV2(){}


V1

@ApiOperation(value = "Work V1", notes = "", response = WorkResponse.class)
 @Version(version = "2018-01-01")
 @RequestMapping(produces = { "application/json" }, method = RequestMethod.GET)
public ResponseEntity<WorkResponse> getWork(){}

SwaggerConfig.class

In this class I wish to create docket for both V1 and V2, but not clear how to map custom in Mapping above to decide version in swagger. The below code is incorrect as instead of header I need to match as per custom or responseEntity (based on mappings above)

@Bean
    public Docket swaggerV2() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("v2").select().apis(p -> {
            if (p.headers() != null) {
                for (NameValueExpression<?> mt : p.headers()) {
                    if (mt.getName().equals("version")) {
                        if (mt.getValue() != "2018-06-01") {
                            return true;
                        }
                    }
                }
            }
            return false;
        }).build().genericModelSubstitutes(Optional.class).ignoredParameterTypes(ApiIgnore.class).apiInfo(apiInfoV2());
    }

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

8reactions
mccaffscommented, Mar 29, 2019

I’ve found I can disable the logic which groups my matching requests together simply by disabling the RequestHandlerCombiner combination logic being used:

@Bean
    public RequestHandlerCombiner disableRequestHandlerCombiner() {
        return source -> source;
    }
2reactions
volkovscommented, Jan 29, 2019

@ankool did the suggested solution work for you?

@dilipkrish I have implemented similar approach for API versioning with custom org.springframework.web.servlet.mvc.condition.RequestCondition. As a result controller may have two almost identical (request handling) methods (only method name and custom Version annotation value are different).

I used RequestHandler selectors (like you mentioned here as well). But the problem is that from springfox point of view those two methods (RequestHandlers) are identical. So ONLY ONE RequestHandler comes in the loop

.select().apis(p -> {
            if (p.findControllerAnnotation(Version.class).isPresent()) {
                    //and if version is v2...
            }
            return false;
        }).

As a result there is no possibility to select one of the handlers into specific version group.

In my understanding springfox.documentation.RequestHandlerKey is responsible for such behaviour.

So, I have a question. Do you think described scenario is valid and should be supported? And, if so, would enhancing of RequestHandlerKey would be the proper way of solving it?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Web Api Versioning using Header , How can we use it on ...
You can easily version by any method you want, including by header. To integrate with an OpenAPI/Swagger generator, such as Swashbuckle, you ...
Read more >
Asp.Net Core Web API Versioning with Swagger - Medium
NET Core is fun and easy, but versioning the API is a bit harder. ... swagger versioning using Custom Request Header.
Read more >
Versioning REST API with Spring Boot and Swagger
Through custom HTTP headers – you define a new header that contains the version number in the request; Through a content negotiation –...
Read more >
Versioning a REST API With Spring Boot and Swagger - DZone
In this article, you'll learn how to maintain multiple versions of your REST API by using the Spring Boot framework along with Swagger....
Read more >
Adding a Required HTTP Header to Your Swagger UI With ...
NET Core Web APIs, then I hope you've heard of Swashbuckle - the ... and easy way to also add fields for your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found