0

I am currently configuring Swagger UI/OpenAPI 3 for my project, which uses Spring Boot and Kotlin. The update endpoints in my controllers include the ETag argument, which I send it to backend as If-Matcher.

I have added the ETag argument as an If-Match header to my request using the io.swagger.v3.oas.annotations.Parameter annotation, as shown below:

@Parameter(`in` = ParameterIn.HEADER, name = "If-Match") eTag: ETag

And my endpoint looks like this:

  @PutMapping("/books/{bookId}")
  open fun updateBook(
      projectId: BookId,
      @RequestBody body: @Valid UpdateBookResource,
      @Parameter(`in` = ParameterIn.HEADER, name = "If-Match") eTag: ETag
  ): ResponseEntity<BookResource> {
     //
  }

And this solution here works fine.

However, my issue is that I do not want to manually add the @Parameter() annotation to each update endpoint.

So I have an ETagArgumentResolver class to configure this Etag globally. My idea was to add the @Parameter() annotation to this class for global application. However, I have been unable to do so, and I would appreciate any assistance in this matter.

The following code snippet is my ETagArgumentResolver class:

import java.io.InputStream
import java.nio.charset.StandardCharsets.UTF_8
import org.springframework.core.MethodParameter
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpHeaders.IF_MATCH
import org.springframework.http.HttpInputMessage
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.lang.Nullable
import org.springframework.web.bind.support.WebDataBinderFactory
import org.springframework.web.context.request.NativeWebRequest
import org.springframework.web.method.support.HandlerMethodArgumentResolver
import org.springframework.web.method.support.ModelAndViewContainer

class ETagArgumentResolver : HandlerMethodArgumentResolver {

  override fun supportsParameter(parameter: MethodParameter) =
      parameter.parameterType == ETag::class.java

  override fun resolveArgument(
      parameter: MethodParameter,
      mavContainer: ModelAndViewContainer,
      webRequest: NativeWebRequest,
      binderFactory: WebDataBinderFactory
  ): ETag? {
    val ifMatchHeader = webRequest.getHeader(IF_MATCH)
    return if (ifMatchHeader.isNullOrBlank()) {
      return if (parameter.hasParameterAnnotation(Nullable::class.java)) {
        null
      } else {
        throw HttpMessageNotReadableException(
            "Value for request header field '$IF_MATCH' is missing.", MyHttpInputMessage())
      }
    } else {
      ETag.from(ifMatchHeader)
    }
  }

  private class MyHttpInputMessage : HttpInputMessage {
    override fun getBody(): InputStream = "".byteInputStream(UTF_8)
    override fun getHeaders() = HttpHeaders()
  }
}

0 Answers0