Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multipart messages with empty parts are not correctly parsed in WebFlux #30953

Closed
hopefulwalker opened this issue Jul 26, 2023 · 2 comments
Closed
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: backported An issue that has been backported to maintenance branches type: regression A bug that is also a regression
Milestone

Comments

@hopefulwalker
Copy link

hopefulwalker commented Jul 26, 2023

I create a demo project using https://start.spring.io/, when upgrading to springboot3.1.2(springframework6.0.11), , the unit test failed. I'm not sure it's a bug or I need to change the code?

It seems the uploading source code by zip is not support, the Github library address is: https://github.com/hopefulwalker/learning.git
The controller code:

@Slf4j
@RestController
@RequestMapping("/api/v1alpha1/files")
public class FileController {
    @PostMapping("/")
    @ResponseStatus(HttpStatus.CREATED)
    public Flux<FileInfo> uploadFile(@RequestPart("files") Flux<FilePart> files) {
        return files.log().filter(part -> StringUtils.isNotBlank(part.filename()))
                .flatMap(part -> Mono.just(new FileInfo(part.filename())))
                .doOnNext(fileInfo -> log.debug(fileInfo.toString()));
    }
}

The unit test code :

    @Test
    void uploadFile() throws IOException {
        MultipartBodyBuilder builder = new MultipartBodyBuilder();
        List<Path> paths = addTempFiles(builder, "files", 2);
        webTestClient.post()
                .uri("/api/v1alpha1/files/")
                .body(BodyInserters.fromMultipartData(builder.build()))
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isCreated()
                .expectBodyList(FileInfo.class)
                .hasSize(paths.size());
        deleteTempFiles(paths);
    }

when running with 3.1.2, It seems only send the fist FilePart

2023-07-26T12:31:42.080+08:00  INFO 56104 --- [     parallel-1] reactor.Flux.MonoFlattenIterable.1       : | onSubscribe([Fuseable] FluxFlattenIterable.FlattenIterableSubscriber)
2023-07-26T12:31:42.081+08:00  INFO 56104 --- [     parallel-1] reactor.Flux.MonoFlattenIterable.1       : | request(256)
2023-07-26T12:31:42.133+08:00  INFO 56104 --- [      Thread-13] reactor.Flux.MonoFlattenIterable.1       : | onNext(DefaultFilePart{files (file13136779453907688947.tmp)})
2023-07-26T12:31:42.144+08:00  INFO 56104 --- [      Thread-13] reactor.Flux.MonoFlattenIterable.1       : | onComplete()
2023-07-26T12:31:42.185+08:00 ERROR 56104 --- [    Test worker] o.s.t.w.reactive.server.ExchangeResult   : Request details for assertion failure:
> POST /api/v1alpha1/files/
> WebTestClient-Request-Id: [1]
> Accept: [application/json]
> Content-Type: [multipart/form-data;boundary=oZMAASAjMOjgus2_uZdRe-B3I3rKkw22-]
412 bytes of content.
< 201 CREATED Created
< Content-Type: [application/json]
[{"name":"file13136779453907688947.tmp"}]
Response body does not contain 2 elements expected:<2> but was:<1>

when running with 2.7.14, it send 2 FilePart

2023-07-26 12:32:49.910  INFO 33252 --- [     parallel-1] reactor.Flux.MonoFlattenIterable.1       : | onSubscribe([Fuseable] FluxFlattenIterable.FlattenIterableSubscriber)
2023-07-26 12:32:49.912  INFO 33252 --- [     parallel-1] reactor.Flux.MonoFlattenIterable.1       : | request(256)
2023-07-26 12:32:49.959  INFO 33252 --- [      Thread-15] reactor.Flux.MonoFlattenIterable.1       : | onNext(DefaultFilePart{files (file5549318982591335212.tmp)})
[learning.zip](https://github.com/spring-projects/spring-boot/files/12167963/learning.zip)

2023-07-26 12:32:49.964  INFO 33252 --- [      Thread-15] reactor.Flux.MonoFlattenIterable.1       : | onNext(DefaultFilePart{files (file4020380138397462466.tmp)})
2023-07-26 12:32:49.964  INFO 33252 --- [      Thread-15] reactor.Flux.MonoFlattenIterable.1       : | onComplete()
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jul 26, 2023
@wilkinsona wilkinsona self-assigned this Jul 26, 2023
@wilkinsona
Copy link
Member

Thanks for the sample. I've reproduced the problem. It doesn't appear to have anything to do with Spring Boot as it fails when Spring Boot is only used for dependency management as shown by the changes in my fork. We'll transfer this to the Framework team so that they can take a look.

@wilkinsona wilkinsona removed their assignment Jul 26, 2023
@snicoll snicoll transferred this issue from spring-projects/spring-boot Jul 26, 2023
@poutsma poutsma self-assigned this Dec 5, 2023
@poutsma poutsma added in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Dec 6, 2023
@poutsma poutsma added this to the 6.1.2 milestone Dec 6, 2023
@poutsma
Copy link
Contributor

poutsma commented Dec 6, 2023

Thanks again for the sample. The problem is due to the fact that the added parts are empty, which is an uncommon scenario that was not supported by our multipart parser.

Preparing a fix now.

@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.0.x labels Dec 6, 2023
@poutsma poutsma changed the title Unit test using WebTestClient (POST with multiple files) fails with 3.1.2 but ok with 2.7.14 Multipart messages with empty parts are not correctly parsed in WebFlux Dec 6, 2023
@poutsma poutsma closed this as completed in ef4ffa0 Dec 6, 2023
poutsma added a commit that referenced this issue Dec 6, 2023
This commit fixes a bug in DefaultPartHttpMessageReader's
MultipartParser, due to which the last token in a part window was not
properly indicated.

See gh-30953
Closes gh-31766
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: backported An issue that has been backported to maintenance branches type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

4 participants