Home > OS >  Cant have RestController to accept application/octet-stream
Cant have RestController to accept application/octet-stream

Time:10-23

I have a spring boot application with rest controller that has to accept binary stream at post endpoint and do the things with it.

So i have:

    @PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
    public String parse(RequestEntity<InputStream> entity) {
        return service.parse(entity.getBody());
    }

When i try to test it with MockMvc i get org.springframework.web.HttpMediaTypeNotSupportedException. I see in log: Request:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /parse
       Parameters = {}
          Headers = [Content-Type:"application/octet-stream;charset=UTF-8", Content-Length:"2449"]
             Body = ...skipped unreadable binary data...
    Session Attrs = {}

Response:

MockHttpServletResponse:
           Status = 415
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", Accept:"application/json, application/* json", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

I tried to add explicit header:

    @PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE},
            headers = "Accept=application/octet-stream")

Does not help. The testing call is:

        mvc.perform(post("/parse")                       
                        .contentType(MediaType.APPLICATION_OCTET_STREAM)
                        .content(bytes)
                ).andDo(print())
                .andExpect(status().isOk());

How can i make it work without going to multipart-form?

CodePudding user response:

I have analysed this issue and got to know that issue is in this method.

  @PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
    public String parse(RequestEntity<InputStream> entity) {
        return service.parse(entity.getBody());
    }

Here method parameter is of type RequestEntity<InputStream> it should be HttpServletRequest

So here is the fix.

    @PostMapping(value = "/upload",
            consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public String demo(HttpServletRequest httpServletRequest) {

        ServletInputStream inputStream;

        try {
            inputStream = httpServletRequest.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        final List<String> list = new BufferedReader(new InputStreamReader(inputStream))
                .lines().toList();
        System.out.println(list);
        return "Hello World";
    }

Test Case

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldTestBinaryFileUpload() throws Exception {
        mockMvc
                .perform(MockMvcRequestBuilders
                        .post("/upload")
                        .content("Hello".getBytes())
                        .contentType(MediaType.APPLICATION_OCTET_STREAM))
                .andExpect(MockMvcResultMatchers
                        .status()
                        .isOk())
                .andExpect(MockMvcResultMatchers
                        .content()
                        .bytes("Hello World".getBytes()));
    }

  • Related