1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.impl;
29
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.hc.core5.annotation.Contract;
33 import org.apache.hc.core5.annotation.ThreadingBehavior;
34 import org.apache.hc.core5.http.ContentLengthStrategy;
35 import org.apache.hc.core5.http.Header;
36 import org.apache.hc.core5.http.HeaderElements;
37 import org.apache.hc.core5.http.HttpException;
38 import org.apache.hc.core5.http.HttpHeaders;
39 import org.apache.hc.core5.http.HttpMessage;
40 import org.apache.hc.core5.http.NotImplementedException;
41 import org.apache.hc.core5.http.ProtocolException;
42 import org.apache.hc.core5.http.message.MessageSupport;
43 import org.apache.hc.core5.util.Args;
44 import org.apache.hc.core5.util.TextUtils;
45
46
47
48
49
50
51
52
53
54
55
56 @Contract(threading = ThreadingBehavior.IMMUTABLE)
57 public class DefaultContentLengthStrategy implements ContentLengthStrategy {
58
59 public static final DefaultContentLengthStrategy INSTANCE = new DefaultContentLengthStrategy();
60
61
62
63
64
65 public DefaultContentLengthStrategy() {
66 }
67
68 enum Coding { UNKNOWN, CHUNK }
69
70 @Override
71 public long determineLength(final HttpMessage message) throws HttpException {
72 Args.notNull(message, "HTTP message");
73 final Header teh = message.getFirstHeader(HttpHeaders.TRANSFER_ENCODING);
74 if (teh != null) {
75 final AtomicReference<Coding> codingRef = new AtomicReference<>();
76 MessageSupport.parseTokens(message, HttpHeaders.TRANSFER_ENCODING, e -> {
77 if (!TextUtils.isBlank(e)) {
78 if (e.equalsIgnoreCase(HeaderElements.CHUNKED_ENCODING)) {
79 if (!codingRef.compareAndSet(null, Coding.CHUNK)) {
80 codingRef.set(Coding.UNKNOWN);
81 }
82 } else {
83 codingRef.set(Coding.UNKNOWN);
84 }
85 }
86 });
87 if (codingRef.get() == Coding.CHUNK) {
88 return CHUNKED;
89 }
90 throw new NotImplementedException("Unsupported transfer encoding: " + teh.getValue());
91 }
92 if (message.countHeaders(HttpHeaders.CONTENT_LENGTH) > 1) {
93 throw new ProtocolException("Multiple Content-Length headers");
94 }
95 final Header contentLengthHeader = message.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
96 if (contentLengthHeader != null) {
97 final String s = contentLengthHeader.getValue();
98 try {
99 final long len = Long.parseLong(s);
100 if (len < 0) {
101 throw new ProtocolException("Negative content length: " + s);
102 }
103 return len;
104 } catch (final NumberFormatException e) {
105 throw new ProtocolException("Invalid content length: " + s);
106 }
107 }
108 return UNDEFINED;
109 }
110
111 }