spring-cloud-gateway icon indicating copy to clipboard operation
spring-cloud-gateway copied to clipboard

Multipart body is missing

Open smdka opened this issue 3 months ago • 2 comments

Hi, everyone! I'm using Spring Cloud Gateway MVC 4.1.2 I need to validate incoming file in multipart request by checking his magic bytes. Straight approach doesn't work because after opening a stream from a file it becomes unavailable for further filters. I tried to use caching but it doesn't work either, request body is missing downstream. Is there a workaround or maybe a right approach to do this kind of validation with Spring Cloud Gateway MVC?

Here's my code snippet:

@Bean
    public RouterFunction<ServerResponse> myRoute() {
        return route("gateway").POST(path("/upload"), http("http://localhost:8081")).before(request -> {
            var clonedInputStream = cacheBody(request);
            var clonedRequest = adaptCachedBody().apply(request);
            clonedInputStream.reset();

            try {
                byte[] pdfSignature = {0x25, 0x50, 0x44, 0x46, 0x2D};
                byte[] actualSignature = new byte[pdfSignature.length];
                HttpServletRequest httpServletRequest = request.servletRequest();
                Part file = httpServletRequest.getPart("file");
                file.getInputStream().read(actualSignature);
                if (!Arrays.equals(pdfSignature, actualSignature)) {
                    throw new RuntimeException("Not PDF");
                }
            } catch (IOException | ServletException e) {
                throw new RuntimeException(e);
            }
            return clonedRequest;
        }).build();
    }

smdka avatar Oct 22 '25 08:10 smdka

How about reading the first 5 bytes, applying the filter, and then restoring the same 5 bytes by wrapping the filtered stream with a SequenceInputStream — i.e., concatenating ByteArrayInputStream(header5) + filteredBody?

ririnto avatar Oct 23 '25 00:10 ririnto

How about reading the first 5 bytes, applying the filter, and then restoring the same 5 bytes by wrapping the filtered stream with a SequenceInputStream — i.e., concatenating ByteArrayInputStream(header5) + filteredBody?

I tried that. Didn't work. Actually what really worked was a servlet filter with ContentCachingRequestWrapper but that doesn't seem like a native Gateway MVC solution

smdka avatar Oct 24 '25 10:10 smdka