Удалите недопустимый символ из заголовка и тела составного запроса

#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);
    }
}