Переопределение типа содержимого заголовка запроса в ServletFilter отличается от прямой отправки типа содержимого - PullRequest
0 голосов
/ 28 июня 2019

Я конвертирую существующее PHP-приложение в Spring Boot 2.1.x.

Один запрос, который отправляют клиенты (и, следовательно, должен поддерживаться для обратной совместимости), - это запрос POST с Content-Type: application/x-www-form-urlencoded некоторые параметры запроса и полезная нагрузка в кодировке Base64.Запрос curl выглядит следующим образом: curl -H "Content-Type: application/x-www-form-urlencoded" -d "abc+123/XYZ=" http://localhost:8080/testing\?x\=\&Z\=U

Наше PHP-приложение не очень строгое и с радостью принимает этот запрос, и я легко могу декодировать заданную полезную нагрузку base64.

С помощью Spring Boot, однако,проблема в том, что он очищает входные данные, потому что они считаются входными данными из формы.Это делается в

  • org.springframework.http.server.ServletServerHttpRequest#getBody
  • -> org.springframework.http.server.ServletServerHttpRequest#isFormPost
  • -> org.springframework.http.server.ServletServerHttpRequest#getBodyFromServletRequestParameters

Теперь, еслиЯ отправляю запрос с Content-Type: text/plain, весной он работает безупречно: curl -H "Content-Type: text/plain" -d "abc+123/XYZ=" http://localhost:8080/testing\?x\=\&Z\=U

Поэтому я хотел просто создать Filter, обернуть запрос и вернуть text/plain как Content-Type:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class MyFilter : Filter {
    override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) {
        if (request is HttpServletRequest && "application/x-www-form-urlencoded" == request.contentType && HttpMethod.POST.matches(request.method)) {
            chain?.doFilter(PlainHeadersRequest(request), response)
        } else {
            chain?.doFilter(request, response)
        }
    }

}

class PlainHeadersRequest(request: HttpServletRequest?) : HttpServletRequestWrapper(request) {
    override fun getContentType(): String {
        return "text/plain"
    }
}

Это первый фильтр в цепочке, и он работает в отношении типа контента, который теперь всегда принимается как text/plain.

Я ожидал, что с этимфильтр, обе команды curl сверху будут работать взаимозаменяемо.

Но это не так.С фильтром я получаю:

$> curl -i -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "abc+123/XYZ=" http://localhost:8080/testing\?x\=\&Z\=U
HTTP/1.1 400 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 27 Jun 2019 21:57:35 GMT
Connection: close

{"timestamp":"2019-06-27T21:57:35.516+0000","status":400,"error":"Bad Request","message":"Required request body is missing: public java.lang.String com.example.demo.stuff.MyController.myMapping(java.lang.String)","path":"/testing"}% 

Мои вопросы сейчас:

  • Где тип контента имеет значение до первого фильтра?
  • (Как это исправить без какого-либо дополнительного программного обеспечения, такого как прокси nginx, перед приложением Spring Boot? -> решено, см. Комментарий)
...