Spring's pit for processing POST content

I once debugged the interface with a third-party company, and their protocol was very strange: the Content-Type used application/x-www-form-urlencoded, but the content was directly written in the image content. Used in Spring

@RequestBody byte[] data

  When receiving the data, it was found that the content was encoded by URLEncode, and the original stream could not be obtained. Trace the source code to:

RequestResponseBodyMethodProcessor
。。。。
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
        Object arg = this.readWithMessageConverters(inputMessage, parameter, paramType);

  Spring wraps the request and passes it on, tracks it, and his getBody method

public InputStream getBody() throws IOException {
        return (InputStream)(isFormPost(this.servletRequest) ? getBodyFromServletRequestParameters(this.servletRequest) : this.servletRequest.getInputStream());
    }

  see isFormPost

private static boolean isFormPost(HttpServletRequest request) {
        String contentType = request.getContentType();
        return contentType != null && contentType.contains("application/x-www-form-urlencoded") && HttpMethod.POST.matches(request.getMethod());
    }

  See getBodyFromServletRequestParameters method

private static InputStream getBodyFromServletRequestParameters(HttpServletRequest request) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
        Writer writer = new OutputStreamWriter(bos, "UTF-8");
        Map<String, String[]> form = request.getParameterMap();
        Iterator nameIterator = form.keySet().iterator();

        while(nameIterator.hasNext()) {
            String name = (String)nameIterator.next();
            List<String> values = Arrays.asList((Object[])form.get(name));
            Iterator valueIterator = values.iterator();

            while(valueIterator.hasNext()) {
                String value = (String)valueIterator.next();
                writer.write(URLEncoder.encode(name, "UTF-8"));
                if (value != null) {
                    writer.write(61);
                    writer.write(URLEncoder.encode(value, "UTF-8"));
                    if (valueIterator.hasNext()) {
                        writer.write(38);
                    }
                }
            }

            if (nameIterator.hasNext()) {
                writer.append('&');
            }
        }

        writer.flush();
        return new ByteArrayInputStream(bos.toByteArray());
    }

  There is no solution, only let them modify the calling protocol, do not use application/x-www-form-urlencoded

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325065373&siteId=291194637