swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.6k stars 8.96k forks source link

Spring WebFlux PathPatternParser syntax in mapping annotation is passed verbatim to the PathVariable #8466

Open dsbecker opened 1 year ago

dsbecker commented 1 year ago

Q&A (please complete the following information)

Content & configuration

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
  <version>2.7.8</version>
</dependency>
<dependency>
  <groupId>org.springdoc</groupId>
  <artifactId>springdoc-openapi-webflux-ui</artifactId>
  <version>1.6.14</version>
</dependency>

Example Swagger/OpenAPI definition: n/a

Swagger-UI configuration options:

springdoc.packages-to-scan=com.example.foobar.rest
springdoc.swagger-ui.operationsSorter=alpha
springdoc.swagger-ui.tagsSorter=alpha
springdoc.swagger-ui.doc-expansion=none
springdoc.webjars.prefix=

Describe the bug you're encountering

When using the Spring 5 PathPatternParser multiple segment matching syntax (/{*path}) in a WebFlux app (maybe a regular Spring Web too if configured to use it) with a @GetMapping or @RequestMapping, the literal path variable ({*path}) is sent to the @PathVariable when invoked through Swagger UI. It works as expected from the browser address bar via a simple URL GET.

The path pattern parser syntax is defined here and more examples shown here.

Create a simple @RestController with the following method:

@GetMapping(path = "/{*path}", produces = MediaType.TEXT_PLAIN_VALUE)
public Mono<String> pathMatching(@PathVariable String path) {
    return Mono.just("path value: " + path);
}

To reproduce...

Steps to reproduce the behavior:

  1. Go to the Swagger UI GET /example/{*path} endpoint and click Try it out
  2. Click in the path variable and enter foo/bar
  3. Click the Execute button
  4. Observe that all of the Curl, Request URL & Response body sections show the value {*path} instead of foo/bar
  5. Open a new browser tab
  6. Enter the following url (mody as needed for your project): http://localhost:8454/example/foo/bar
  7. Observe that the value foo/bar is shown as expected

Expected behavior

The value foo/bar should be shown in Swagger UI.

Screenshots

image image

Additional context or thoughts

There is a workaround, of sorts. This workaround seems to point to a problem with the expected variable name.

But it's not 100% because Swagger UI insists on escaping the multiple segment path entered into the path variable, which is undesirable for this style of multiple segment path variable. See screenshots. I would expect it to be substituted verbatim without escaping in this scenario.

Though, in the end, this works because Spring unescapes the value for you, but it looks ugly in Swagger UI.

@GetMapping(path = "/{*path}", produces = MediaType.TEXT_PLAIN_VALUE)
public Mono<String> pathMatching(@Parameter(name = "*path") @PathVariable String path) {
    return Mono.just("path value: " + path);
}

Additional Screenshots

image

iPave commented 1 year ago

Faced the same issue in Spring MVC.