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

tomdesair / tus-java-server / 28898324220

07 Jul 2026 09:00PM UTC coverage: 95.729% (+0.9%) from 94.813%
28898324220

Pull #105

github

web-flow
Merge 287f920bd into 4b2f45149
Pull Request #105: WIP feat: Implement IETF Resumable Uploads for HTTP (RUFH) Protocol

1103 of 1206 branches covered (91.46%)

Branch coverage included in aggregate %.

766 of 777 new or added lines in 42 files covered. (98.58%)

2573 of 2634 relevant lines covered (97.68%)

6.33 hits per line

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

86.96
/src/main/java/me/desair/tus/server/digest/validation/HttpDigestsValidator.java
1
package me.desair.tus.server.digest.validation;
2

3
import jakarta.servlet.http.HttpServletRequest;
4
import jakarta.servlet.http.HttpServletResponse;
5
import java.io.IOException;
6
import java.util.Map;
7
import me.desair.tus.server.HttpHeader;
8
import me.desair.tus.server.HttpMethod;
9
import me.desair.tus.server.RequestValidator;
10
import me.desair.tus.server.checksum.ChecksumAlgorithm;
11
import me.desair.tus.server.exception.ChecksumAlgorithmNotSupportedException;
12
import me.desair.tus.server.exception.TusException;
13
import me.desair.tus.server.upload.UploadStorageService;
14
import me.desair.tus.server.util.StructuredHeaderUtil;
15
import org.apache.commons.lang3.StringUtils;
16

17
/** Validates HTTP Digest headers (Content-Digest, Repr-Digest, Want-Repr-Digest) structure. */
18
public class HttpDigestsValidator implements RequestValidator {
6✔
19

20
  @Override
21
  public void validate(
22
      HttpMethod method,
23
      HttpServletRequest request,
24
      UploadStorageService uploadStorageService,
25
      String ownerKey)
26
      throws TusException, IOException {
27

28
    try {
29
      String contentDigest = request.getHeader(HttpHeader.CONTENT_DIGEST);
4✔
30
      if (StringUtils.isNotBlank(contentDigest)) {
3✔
31
        Map<String, Object> digestDict = StructuredHeaderUtil.parseDictionary(contentDigest);
3✔
32
        if (digestDict.isEmpty()) {
3!
NEW
33
          throw new TusException(
×
34
              HttpServletResponse.SC_BAD_REQUEST, "Content-Digest cannot be empty");
35
        }
36
        for (String key : digestDict.keySet()) {
11✔
37
          if (ChecksumAlgorithm.forHttpDigestName(key) == null) {
3✔
38
            throw new ChecksumAlgorithmNotSupportedException(
6✔
39
                "The "
40
                    + HttpHeader.CONTENT_DIGEST
41
                    + " header value contains unsupported algorithm: "
42
                    + key);
43
          }
44
        }
1✔
45
      }
46

47
      String reprDigest = request.getHeader(HttpHeader.REPR_DIGEST);
4✔
48
      if (StringUtils.isNotBlank(reprDigest)) {
3✔
49
        Map<String, Object> digestDict = StructuredHeaderUtil.parseDictionary(reprDigest);
3✔
50
        if (digestDict.isEmpty()) {
3!
NEW
51
          throw new TusException(HttpServletResponse.SC_BAD_REQUEST, "Repr-Digest cannot be empty");
×
52
        }
53
        for (String key : digestDict.keySet()) {
11✔
54
          if (ChecksumAlgorithm.forHttpDigestName(key) == null) {
3✔
55
            throw new ChecksumAlgorithmNotSupportedException(
6✔
56
                "The "
57
                    + HttpHeader.REPR_DIGEST
58
                    + " header value contains unsupported algorithm: "
59
                    + key);
60
          }
61
        }
1✔
62
      }
63

64
      String wantReprDigest = request.getHeader(HttpHeader.WANT_REPR_DIGEST);
4✔
65
      if (StringUtils.isNotBlank(wantReprDigest)) {
3✔
66
        java.util.List<String> items = StructuredHeaderUtil.parseList(wantReprDigest);
3✔
67
        if (items.isEmpty()) {
3!
NEW
68
          throw new TusException(
×
69
              HttpServletResponse.SC_BAD_REQUEST, "Want-Repr-Digest cannot be empty");
70
        }
71
        for (String item : items) {
10✔
72
          String token = StringUtils.substringBefore(item, ";").trim();
5✔
73
          if (!token.matches("^[a-zA-Z0-9_*./-]+$")) {
4✔
74
            throw new TusException(
7✔
75
                HttpServletResponse.SC_BAD_REQUEST,
76
                "Invalid token format in Want-Repr-Digest: " + token);
77
          }
78
        }
1✔
79
      }
80
    } catch (TusException te) {
1✔
81
      throw te;
2✔
NEW
82
    } catch (Exception e) {
×
NEW
83
      throw new TusException(
×
84
          HttpServletResponse.SC_BAD_REQUEST,
NEW
85
          "Invalid structured header format: " + e.getMessage());
×
86
    }
1✔
87
  }
1✔
88

89
  @Override
90
  public boolean supports(HttpMethod method) {
91
    return HttpMethod.POST.equals(method)
14✔
92
        || HttpMethod.PUT.equals(method)
8✔
93
        || HttpMethod.PATCH.equals(method);
8✔
94
  }
95
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc