#spring-mvc #multipart
Вопрос:
Мне нужно предоставить API, который использует составной запрос. К сожалению, клиент (вне моего контроля) отправляет недопустимый символ (‘=’) как часть граничной части заголовка типа содержимого. Я думал о написании фильтра сервлета для исправления заголовка типа содержимого, а также границ внутри запроса. Часть заголовка уже выполнена, но я борюсь с заменой границы в теле запроса, которое содержит несколько частей, состоящих из приложения/json, а также приложения/октетного потока (поэтому, если возможно, я хотел бы исправить границы на лету, не обязательно читая все тело). Я был бы очень признателен за некоторые указания здесь, чтобы направить меня в правильном направлении.
Вот этот фильтр:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class FixBoundaryFilter implements Filter {
//Actual header value example: "multipart/form-data; boundary=WhooHooZeerOoonie="
Pattern headerValuePattern = Pattern.compile("multipart/form-data; boundary=([a-zA-Z0-9\ \-=] )");
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
LOGGER.info("########## Initiating custom {} ##########", FixBoundaryFilter.class.getSimpleName());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
FixBoundaryRequestWrapper wrappedRequest = new FixBoundaryRequestWrapper(request);
String contentTypeHeaderValue = wrappedRequest.getHeader(HttpHeaders.CONTENT_TYPE);
if (StringUtils.isNotBlank(contentTypeHeaderValue)) {
Matcher matcher = headerValuePattern.matcher(contentTypeHeaderValue);
if (matcher.matches()) {
String updatedHeader = String.format("multipart/form-data; boundary="%s"", matcher.group(1));
wrappedRequest.removeHeader(HttpHeaders.CONTENT_TYPE);
wrappedRequest.addHeader(HttpHeaders.CONTENT_TYPE, updatedHeader);
}
}
//call next filter in the filter chain
chain.doFilter(wrappedRequest, response);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Вот обертка:
public class FixBoundaryRequestWrapper extends HttpServletRequestWrapper {
public FixBoundaryRequestWrapper(HttpServletRequest request) {
super(request);
}
private final Map<String, String> headerMap = new HashMap<>();
public void addHeader(String name, String value) {
headerMap.put(name, value);
}
public void removeHeader(String name) {
headerMap.remove(name);
}
@Override
public String getHeader(String name) {
String headerValue = super.getHeader(name);
if (headerMap.containsKey(name)) {
headerValue = headerMap.get(name);
}
return headerValue;
}
@Override
public Enumeration<String> getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
names.addAll(headerMap.keySet());
return Collections.enumeration(names);
}
@Override
public Enumeration<String> getHeaders(String name) {
List<String> values = Collections.list(super.getHeaders(name));
if (headerMap.containsKey(name)) {
values.add(headerMap.get(name));
}
return Collections.enumeration(values);
}
}