• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tomdesair / tus-java-server / 30485348532

29 Jul 2026 07:39PM UTC coverage: 96.295% (+0.04%) from 96.255%
30485348532

push

github

web-flow
Refactor RUFH 104 interim response handling and add Tomcat Valve documentation (#109)

1331 of 1438 branches covered (92.56%)

Branch coverage included in aggregate %.

79 of 80 new or added lines in 7 files covered. (98.75%)

2827 of 2880 relevant lines covered (98.16%)

6.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.78
/src/main/java/me/desair/tus/server/rufh/handler/RufhCreationPostRequestHandler.java
1
package me.desair.tus.server.rufh.handler;
2

3
import java.io.IOException;
4
import java.io.InputStream;
5
import me.desair.tus.server.HttpHeader;
6
import me.desair.tus.server.HttpMethod;
7
import me.desair.tus.server.HttpProblemDetails;
8
import me.desair.tus.server.exception.TusException;
9
import me.desair.tus.server.upload.UploadInfo;
10
import me.desair.tus.server.upload.UploadLockingService;
11
import me.desair.tus.server.upload.UploadStorageService;
12
import me.desair.tus.server.util.AbstractRequestHandler;
13
import me.desair.tus.server.util.InterruptibleInputStream;
14
import me.desair.tus.server.util.StructuredHeaderUtil;
15
import me.desair.tus.server.util.TusServletRequest;
16
import me.desair.tus.server.util.TusServletResponse;
17
import me.desair.tus.server.util.Utils;
18

19
/**
20
 * Request handler for upload creation requests via HTTP POST, PUT, or PATCH.
21
 *
22
 * <p>Handles upload initialization, payload byte streaming, lock registration via {@link
23
 * InterruptibleInputStream}, and response headers.
24
 *
25
 * <p>Reference: Section 4.2 (Upload Creation) & Section 4.2.2 (Server Behavior) of
26
 * draft-ietf-httpbis-resumable-upload-12.
27
 */
28
public class RufhCreationPostRequestHandler extends AbstractRequestHandler {
29

30
  public RufhCreationPostRequestHandler() {
4✔
31
    // Default constructor
32
  }
2✔
33

34
  @Override
35
  public boolean supports(HttpMethod method) {
36
    return HttpMethod.POST.equals(method)
14✔
37
        || HttpMethod.PUT.equals(method)
8✔
38
        || HttpMethod.PATCH.equals(method);
8✔
39
  }
40

41
  @Override
42
  public HttpProblemDetails process(
43
      HttpMethod method,
44
      TusServletRequest servletRequest,
45
      TusServletResponse servletResponse,
46
      UploadStorageService uploadStorageService,
47
      UploadLockingService uploadLockingService,
48
      String ownerKey,
49
      TusException exception)
50
      throws IOException, TusException {
51

52
    if (HttpMethod.PATCH.equals(method)
8✔
53
        && isExistingUpload(servletRequest, uploadStorageService, ownerKey)) {
2✔
54
      // Existing upload on PATCH request is handled by RufhAppendPatchRequestHandler
55
      return null;
2✔
56
    }
57

58
    UploadInfo preCreatedUploadInfo =
2✔
59
        (UploadInfo) servletRequest.getAttribute("me.desair.tus.preCreatedUploadInfo");
3✔
60

61
    String uploadLengthHeader = servletRequest.getHeader(HttpHeader.UPLOAD_LENGTH);
4✔
62
    Long uploadLength = StructuredHeaderUtil.parseInteger(uploadLengthHeader);
3✔
63

64
    String uploadCompleteHeader = servletRequest.getHeader(HttpHeader.UPLOAD_COMPLETE);
4✔
65
    Boolean uploadComplete = StructuredHeaderUtil.parseBoolean(uploadCompleteHeader);
3✔
66

67
    UploadInfo uploadInfo;
68
    if (preCreatedUploadInfo != null) {
2✔
69
      uploadInfo = preCreatedUploadInfo;
2✔
70
      if (uploadLength != null && uploadLength >= 0) {
7!
NEW
71
        uploadInfo.setLength(uploadLength);
×
72
      }
73
      uploadStorageService.update(uploadInfo);
4✔
74
    } else {
75
      uploadInfo = new UploadInfo();
4✔
76
      if (uploadLength != null && uploadLength >= 0) {
7✔
77
        uploadInfo.setLength(uploadLength);
3✔
78
      }
79
      uploadInfo = uploadStorageService.create(uploadInfo, ownerKey);
5✔
80
    }
81

82
    String uploadUri =
3✔
83
        Utils.getUploadUriOnCreation(uploadInfo, servletRequest, uploadStorageService);
2✔
84

85
    InputStream is = servletRequest.getContentInputStream();
3✔
86
    if (is != null && servletRequest.getContentLengthLong() != 0) {
7✔
87
      if (uploadLockingService != null) {
2✔
88
        InterruptibleInputStream interruptibleStream = new InterruptibleInputStream(is);
5✔
89
        uploadLockingService.registerInputStream(uploadUri, interruptibleStream);
4✔
90
        is = interruptibleStream;
2✔
91
      }
92
      UploadInfo appended = uploadStorageService.append(uploadInfo, is);
5✔
93
      if (appended != null) {
2✔
94
        uploadInfo = appended;
2✔
95
      }
96
    }
97

98
    boolean isFinished = Boolean.TRUE.equals(uploadComplete) || isUploadCompleted(uploadInfo);
12✔
99
    if (isFinished) {
2✔
100
      uploadInfo.setLength(uploadInfo.getOffset());
4✔
101
      uploadStorageService.update(uploadInfo);
3✔
102
      servletResponse.setStatus(200);
3✔
103
      servletResponse.setHeader(HttpHeader.LOCATION, uploadUri);
4✔
104
      servletResponse.setHeader(
4✔
105
          HttpHeader.UPLOAD_COMPLETE, StructuredHeaderUtil.formatBoolean(true));
1✔
106
      servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, String.valueOf(uploadInfo.getOffset()));
7✔
107
    } else {
108
      servletResponse.setStatus(201);
3✔
109
      servletResponse.setHeader(HttpHeader.LOCATION, uploadUri);
4✔
110
      servletResponse.setHeader(
4✔
111
          HttpHeader.UPLOAD_COMPLETE, StructuredHeaderUtil.formatBoolean(false));
1✔
112
      servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, String.valueOf(uploadInfo.getOffset()));
6✔
113
    }
114
    return null;
2✔
115
  }
116

117
  private boolean isExistingUpload(
118
      TusServletRequest request, UploadStorageService uploadStorageService, String ownerKey)
119
      throws IOException {
120
    String requestUri = request.getRequestURI();
3✔
121
    return uploadStorageService.getUploadInfo(requestUri, ownerKey) != null;
9✔
122
  }
123

124
  private boolean isUploadCompleted(UploadInfo uploadInfo) {
125
    return !uploadInfo.isUploadInProgress();
7✔
126
  }
127
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc