Skip to content
New issue

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

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

Already on GitHub? # to your account

Springdoc does not work with Spring's "capture the rest" PathPattern syntax #2383

Closed
quinncaster opened this issue Sep 20, 2023 · 4 comments
Closed
Labels
wontfix This will not be worked on

Comments

@quinncaster
Copy link

Describe the bug

Also on stackoverflow.com here:
https://stackoverflow.com/questions/77129312/springdoc-2-2-0-latest-does-not-work-with-springs-capture-the-rest-pathpatt

Since 5.0, Spring supports a path parser known as "PathPattern", it's recommended for many reasons
https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc

There is a "capture the rest" syntax to capture an entire path (all segments) as documented here:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/pattern/PathPattern.html

We can see how this is used/tested here:
https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java

The following Spring Boot MVC snippet shows the situation. Unfortunately, I am required to support this endpoint as defined (for legacy reasons), so changing the "protocol" is not an option. My goal is to enable OpenDoc/Swagger.

...
	@GetMapping("context/{*pathVar}")
	@Operation(summary ="operate on the data passed in the path")
	public String operate(@PathVariable String pathVar) { 
	... 
	}
...

Here are my observations:

Spring Doc Failing / App Working:

  • If I leave the '*' in "{*pathVar}" so it is like "{*pathVar}", then SpringDoc appears to generate working doc, but execution of the swagger fails.
  • GOOD: My application can accept any input with slashes (ex: a longer url, like /context/part1/part2/part3)
  • BAD: In this case, when I paste-in a string into the swagger page, it is not sent to the server, instead I see: https://server.com/context/%7B*pathVar%7D
  • So, I can not use springdoc/swagger to call/demo this endpoint.

Spring Doc Working / App Failing:

  • If I remove the '*' from "{*pathVar}" so it is like "{pathVar}", then SpringDoc generates working doc.
  • GOOD: In this case, I can paste-in any string into the swagger page, and it is properly sent to the server, like: https://server.com/context/part1/part2
  • BAD: My application is not invoked, because Spring will not accept any input with slashes.

Summary:

It seems that SpringDoc is somehow stumbling on the so-called "capture the rest" syntax, and building the URL from the exact syntax instead of building the URL from what was captured by the "capture the rest" syntax.

I've tried many variations of the syntax options, and likewise tried reviewing springdoc configuration options but so far I have not found a solution that both allows my application to work, and also be demoed via SpringDoc/Swagger.

@bnasslahsen
Copy link
Collaborator

@quinncaster,

Please provide

@bnasslahsen bnasslahsen added the incomplete incomplete description: Make sure you Provide a Minimal, Reproducible Example - with HelloController label Oct 15, 2023
@quinncaster
Copy link
Author

@bnasslahsen Many thanks in advance! I have attached a working demo here:
demo.zip

The Controller class is like:

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;

@RestController
public class HelloController {

	@GetMapping("hello/{*input}")
	@Operation(summary = "Get the the input, and echo it to output")
	public String getString(
			@Parameter(description = "Any string, which can include slashes", example = "abc/123/zyx/789") 
			@PathVariable String input) {

		return input;
	}
}

Actual Result:
When I invoke the endpoint via swagger output is like:
image

Expected Result:
When I invoke the endpoint via a browser URL, the output is like:
image

To be clear - from the above usage with a real browser URL, we see this is working great in my controller. The problem is that springdoc can not be used to demonstrate a functioning API.

This is using the "capture the rest" syntax to capture an entire path (all segments) as documented here:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/pattern/PathPattern.html

The spring team maintains unit test supporting this syntax here
https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java#L420

Let me know if there is anything else I can do to help!

@bnasslahsen
Copy link
Collaborator

bnasslahsen commented Dec 2, 2023

@quinncaster,

This is not supported by the OpenApi spec for now: OAI/OpenAPI-Specification#892

@bnasslahsen bnasslahsen added wontfix This will not be worked on and removed incomplete incomplete description: Make sure you Provide a Minimal, Reproducible Example - with HelloController labels Dec 2, 2023
@quinncaster
Copy link
Author

@bnasslahsen - thanks for the link. From reading that, I understand the decision. Thanks for consideration.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants