Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-2480

Multipart Input no longer treated with transfer encoding

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Critical Critical
    • 4.5.5.Final
    • 4.4.2.Final
    • jaxrs
    • None
    • Hide

      Arbitrary multipart form action

      @Consumes(MediaType.MULTIPART_FORM_DATA)
      @Produces({ MediaType.APPLICATION_JSON, MediaType.MULTIPART_FORM_DATA })
      Response doSomething(@MultipartForm DoSomethingRequest request);
      
      static class DoSomethingRequest {
          @FormParam("myData") @PartType(MediaType.APPLICATION_OCTET_STREAM) private byte[] myData;
      }
      

      RestAssured setup required for decoding to fail

      byte[] data = "My data".getBytes(StandardCharsets.UTF_8);
      String base64data = Base64.getEncoder().encodeToString(data);
      MultiPartSpecification multipart = new MultiPartSpecBuilder(base64data)
      	.header("Content-Transfer-Encoding", "base64")
      	.header("Transfer-Encoding", "base64")
      	.controlName("myData")
      	.mimeType(MediaType.APPLICATION_OCTET_STREAM)
      	.build();
      
      Response response = given()
      	.multiPart(multipart)
      	.contentType(MediaType.MULTIPART_FORM_DATA)
      	.log()
      	.all(false)
      	.expect()
      	.statusCode(HttpStatus.SC_OK)
      	.contentType(MediaType.APPLICATION_JSON)
      	.and()
      	.log()
      	.everything()
      	.when()
      	.post("/dosomething");
      
      Show
      Arbitrary multipart form action @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces({ MediaType.APPLICATION_JSON, MediaType.MULTIPART_FORM_DATA }) Response doSomething(@MultipartForm DoSomethingRequest request); static class DoSomethingRequest { @FormParam( "myData" ) @PartType(MediaType.APPLICATION_OCTET_STREAM) private byte [] myData; } RestAssured setup required for decoding to fail byte [] data = "My data" .getBytes(StandardCharsets.UTF_8); String base64data = Base64.getEncoder().encodeToString(data); MultiPartSpecification multipart = new MultiPartSpecBuilder(base64data) .header( "Content-Transfer-Encoding" , "base64" ) .header( "Transfer-Encoding" , "base64" ) .controlName( "myData" ) .mimeType(MediaType.APPLICATION_OCTET_STREAM) .build(); Response response = given() .multiPart(multipart) .contentType(MediaType.MULTIPART_FORM_DATA) .log() .all( false ) .expect() .statusCode(HttpStatus.SC_OK) .contentType(MediaType.APPLICATION_JSON) .and() .log() .everything() .when() .post( "/dosomething" );

      We have found a regression going from Resteasy 3.x to 4.x when consuming multipart form data and base64 (Content-)Transfer-Encoding.

      MultipartInputImpl#parse(InputStream is) hands the stream to Mime4JWorkaround.parseMessage(InputStream is) which internally uses Mime4jWorkaroundBinaryEntityBuilder as its content handler. This builder class, when handling the body, with 4.x Versions contains commented out code that, in 3.x versions, did handle the Base64 content decoding. Further commentary in this method hints on MimeStreamParser#setContentDecoding(boolean b) method that should be used instead:

      NO NEED TO MANUALLY RUN DECODING. The parser has a "setContentDecoding" method. We should simply instantiate the MimeStreamParser with that method.

      However, the calling class Mime4JWorkaround, that should handle this case, sets hardcoded false value for content decoding.

      parser.setContentDecoding(false);
      

      This leads to content decoding no longer being applied at all.

      As for the moment there does not seem to be any workaround and we had to downgrade back to 3.x, I dared to set this issue as critical.

              rsearls r searls
              roland.doepke Roland Doepke (Inactive)
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: