Spring Boot + фильтр типа "Джерси" - неверный запрос 400 на обслуживание. Расходует MULTIPART_FORM_DATA. - PullRequest
0 голосов
/ 17 мая 2018

Я использую Spring boot v1.5.10 + Jersey v2.25.1, настроил джерси в качестве фильтра для доступа к файлам статических папок.Я получаю HTTP-ответ 400 Bad Request для службы, потребляющей MULTIPART_FORM_DATA.

Пропадает настроить Джерси в качестве фильтра.

spring.jersey.type=filter

Если удалить указанное выше свойство, т. Е. Использовать Джерси в качестве сервлетаслужба работает, но я не могу получить доступ к статической папке.

Вот контроллер,

@POST
@Path("/save")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public ResponseBean save(
        @FormDataParam("fileToUpload") InputStream file,
        @FormDataParam("fileToUpload") FormDataContentDisposition fileDisposition,
        @FormDataParam("fromData") FormDataDto data) {
    // stuff
}

РЕДАКТИРОВАТЬ:

Ссылка на GitHub https://github.com/sundarabalajijk/boot-jersey

При запуске приложения spring.jersey.type=filter

http://localhost:8080/ (работает)

http://localhost:8080/hello.html (работает)

http://localhost:8080/save (не работает) - используется почтальон.

Когда spring.jersey.type=servlet

http://localhost:8080/ (работает)

http://localhost:8080/hello.html (не работает)

http://localhost:8080/save (работает)

Postman request

1 Ответ

0 голосов
/ 19 мая 2018

После некоторых исследований и поиска связанных с этим проблем 1 кажется, что Spring * HiddenHttpMethodFilter считывает входной поток, что оставляет его пустым для любых других фильтров далее по цепочке фильтров. Вот почему мы получаем плохой запрос в фильтре Джерси; потому что поток сущностей пуст. Вот записка от Javadoc

ПРИМЕЧАНИЕ. Этот фильтр необходимо запустить после многоэтапной обработки в случае многоэлементного POST-запроса из-за присущей ему необходимости проверки параметра тела POST.

Итак, нам нужно настроить фильтр Джерси, который будет вызываться до этого фильтра Spring 2 . Основываясь на Spring Boot docs , есть свойство, которое мы можем использовать, чтобы легко настроить порядок этого фильтра.

spring.jersey.filter.order

Выполняя поиск Github в репозитории Spring Boot для HiddenHttpMethodFilter, мы видим подкласс, который используется OrderedHiddenHttpMethodFilter , где порядок установлен на -10000. Поэтому мы хотим установить порядок нашего фильтра Джерси меньше, чем это (более высокий приоритет). Таким образом, мы можем установить следующее значение

spring.jersey.filter.order=-100000

Если вы проверите это сейчас, оно должно теперь работать.

Еще одна вещь, которую нам нужно исправить, это порядок пружины RequestContextFilter. Первоначально он был настроен для вызова прямо перед фильтром Джерси. Когда мы устанавливаем конфигурацию заказа выше для фильтра Джерси, RequestContextFilter остается там, где он был изначально. Таким образом, мы должны изменить это. Мы можем сделать это, просто добавив bean-компонент для переопределения исходного и установки порядка.

@Bean
public RequestContextFilter requestContextFilter() {
    OrderedRequestContextFilter filter = new OrderedRequestContextFilter();
    filter.setOrder(-100001);
    return filter;
}

Теперь, если мы проверяем журналы при запуске, мы должны увидеть порядок сортировки файлов, который мы хотим.

Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'requestContextFilter' to: [/*]
Mapping filter: 'jerseyFilter' to urls: [/*]
Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
Mapping filter: 'httpPutFormContentFilter' to: [/*]

Помимо

Причина, по которой вам нужно настроить Джерси в качестве фильтра в вашем случае, заключается в статическом содержимом. Если вы не настроите корневой путь для приложения Jersey, по умолчанию оно будет равно /*, что приведет к загрузке всех запросов, включая запросы к статическому содержимому. Таким образом, Джерси выдаст 404 ошибки, когда будут сделаны запросы на статический контент. Мы настраиваем Джерси как фильтр и сообщаем ему переадресовать запрос, который он не может найти.

Если бы мы просто настроили корневой путь для Джерси, нам не пришлось бы беспокоиться об этой проблеме со статическим контентом, и мы могли бы просто оставить Джерси настроенным в качестве сервлета по умолчанию.

Чтобы изменить базовый путь для приложения Джерси, мы можем либо добавить аннотацию @ApplicatuonPath к нашему ResourceConfig, либо использовать свойство spring.jersey.application-path

@Component
@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
    ...
}

или в вашем application.properties

spring.jersey.application-path=/api

Смотри также


Сноска

1. Некоторые вопросы, на которые следует обратить внимание [ 1 , 2 ]
2. См. Изменение порядка RequestContextFilter в цепочке фильтров

...