jruby-http-kit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +1 -0
- data/example/config.ru +9 -0
- data/example/hello_world.rb +17 -0
- data/example/rack.rb +11 -0
- data/example/ring.rb +31 -0
- data/example/sinatra/app.rb +9 -0
- data/example/sinatra/config.ru +8 -0
- data/example/webmachine/Gemfile +4 -0
- data/example/webmachine/Gemfile.lock +16 -0
- data/example/webmachine/app.rb +37 -0
- data/jruby-http-kit.gemspec +25 -0
- data/lib/http_kit/rack_handler.rb +139 -0
- data/lib/http_kit/server.rb +62 -0
- data/lib/http_kit/version.rb +3 -0
- data/lib/http_kit.rb +6 -0
- data/lib/java/clojure-1.5.1.jar +0 -0
- data/lib/java/http-kit.jar +0 -0
- data/lib/rack/handler/http_kit.rb +3 -0
- data/lib/rack/http_kit.rb +3 -0
- data/lib/webmachine/adapters/ring.rb +135 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/test_resource.rb +75 -0
- data/spec/webmachine/ring_adapter_spec.rb +127 -0
- data/src/.classpath +7 -0
- data/src/.project +17 -0
- data/src/org/httpkit/BytesInputStream.class +0 -0
- data/src/org/httpkit/BytesInputStream.java +83 -0
- data/src/org/httpkit/DateFormatter.class +0 -0
- data/src/org/httpkit/DynamicBytes.class +0 -0
- data/src/org/httpkit/DynamicBytes.java +76 -0
- data/src/org/httpkit/HTTPException.class +0 -0
- data/src/org/httpkit/HTTPException.java +10 -0
- data/src/org/httpkit/HeaderMap.class +0 -0
- data/src/org/httpkit/HeaderMap.java +98 -0
- data/src/org/httpkit/HttpMethod.class +0 -0
- data/src/org/httpkit/HttpMethod.java +28 -0
- data/src/org/httpkit/HttpStatus.class +0 -0
- data/src/org/httpkit/HttpStatus.java +416 -0
- data/src/org/httpkit/HttpUtils.class +0 -0
- data/src/org/httpkit/HttpUtils.java +484 -0
- data/src/org/httpkit/HttpVersion.class +0 -0
- data/src/org/httpkit/HttpVersion.java +5 -0
- data/src/org/httpkit/LineReader.class +0 -0
- data/src/org/httpkit/LineReader.java +52 -0
- data/src/org/httpkit/LineTooLargeException.class +0 -0
- data/src/org/httpkit/LineTooLargeException.java +13 -0
- data/src/org/httpkit/PrefixThreadFactory.class +0 -0
- data/src/org/httpkit/PrefixThreadFactory.java +20 -0
- data/src/org/httpkit/PriorityQueue.class +0 -0
- data/src/org/httpkit/PriorityQueue.java +235 -0
- data/src/org/httpkit/ProtocolException.class +0 -0
- data/src/org/httpkit/ProtocolException.java +10 -0
- data/src/org/httpkit/RequestTooLargeException.class +0 -0
- data/src/org/httpkit/RequestTooLargeException.java +10 -0
- data/src/org/httpkit/client/AbortException.class +0 -0
- data/src/org/httpkit/client/AbortException.java +13 -0
- data/src/org/httpkit/client/Decoder.class +0 -0
- data/src/org/httpkit/client/Decoder.java +182 -0
- data/src/org/httpkit/client/Handler.class +0 -0
- data/src/org/httpkit/client/HttpClient.class +0 -0
- data/src/org/httpkit/client/HttpClient.java +393 -0
- data/src/org/httpkit/client/HttpsRequest.class +0 -0
- data/src/org/httpkit/client/HttpsRequest.java +141 -0
- data/src/org/httpkit/client/IFilter$1.class +0 -0
- data/src/org/httpkit/client/IFilter$MaxBodyFilter.class +0 -0
- data/src/org/httpkit/client/IFilter.class +0 -0
- data/src/org/httpkit/client/IFilter.java +53 -0
- data/src/org/httpkit/client/IRespListener.class +0 -0
- data/src/org/httpkit/client/IRespListener.java +30 -0
- data/src/org/httpkit/client/IResponseHandler.class +0 -0
- data/src/org/httpkit/client/IResponseHandler.java +18 -0
- data/src/org/httpkit/client/PersistentConn.class +0 -0
- data/src/org/httpkit/client/PersistentConn.java +33 -0
- data/src/org/httpkit/client/Request.class +0 -0
- data/src/org/httpkit/client/Request.java +74 -0
- data/src/org/httpkit/client/RequestConfig.class +0 -0
- data/src/org/httpkit/client/RequestConfig.java +28 -0
- data/src/org/httpkit/client/RespListener.class +0 -0
- data/src/org/httpkit/client/RespListener.java +160 -0
- data/src/org/httpkit/client/SslContextFactory.class +0 -0
- data/src/org/httpkit/client/SslContextFactory.java +79 -0
- data/src/org/httpkit/client/State.class +0 -0
- data/src/org/httpkit/client/TimeoutException.class +0 -0
- data/src/org/httpkit/client/TimeoutException.java +12 -0
- data/src/org/httpkit/client/TrustManagerFactory$1.class +0 -0
- data/src/org/httpkit/client/TrustManagerFactory.class +0 -0
- data/src/org/httpkit/server/AsyncChannel.class +0 -0
- data/src/org/httpkit/server/AsyncChannel.java +286 -0
- data/src/org/httpkit/server/ClojureRing.class +0 -0
- data/src/org/httpkit/server/Frame$BinaryFrame.class +0 -0
- data/src/org/httpkit/server/Frame$CloseFrame.class +0 -0
- data/src/org/httpkit/server/Frame$PingFrame.class +0 -0
- data/src/org/httpkit/server/Frame$TextFrame.class +0 -0
- data/src/org/httpkit/server/Frame.class +0 -0
- data/src/org/httpkit/server/Frame.java +73 -0
- data/src/org/httpkit/server/HttpAtta.class +0 -0
- data/src/org/httpkit/server/HttpAtta.java +10 -0
- data/src/org/httpkit/server/HttpDecoder$State.class +0 -0
- data/src/org/httpkit/server/HttpDecoder.class +0 -0
- data/src/org/httpkit/server/HttpDecoder.java +202 -0
- data/src/org/httpkit/server/HttpHandler.class +0 -0
- data/src/org/httpkit/server/HttpRequest.class +0 -0
- data/src/org/httpkit/server/HttpRequest.java +109 -0
- data/src/org/httpkit/server/HttpServer.class +0 -0
- data/src/org/httpkit/server/HttpServer.java +281 -0
- data/src/org/httpkit/server/IHandler.class +0 -0
- data/src/org/httpkit/server/IHandler.java +12 -0
- data/src/org/httpkit/server/LinkingRunnable.class +0 -0
- data/src/org/httpkit/server/Rack.class +0 -0
- data/src/org/httpkit/server/RackApplication.class +0 -0
- data/src/org/httpkit/server/RackApplication.java +10 -0
- data/src/org/httpkit/server/RackHandler$1.class +0 -0
- data/src/org/httpkit/server/RackHandler.class +0 -0
- data/src/org/httpkit/server/RackHandler.java +259 -0
- data/src/org/httpkit/server/RackHttpHandler.class +0 -0
- data/src/org/httpkit/server/RackHttpHandler.java +20 -0
- data/src/org/httpkit/server/RespCallback.class +0 -0
- data/src/org/httpkit/server/RespCallback.java +19 -0
- data/src/org/httpkit/server/RingHandler$1.class +0 -0
- data/src/org/httpkit/server/RingHandler.class +0 -0
- data/src/org/httpkit/server/RingHandler.java +222 -0
- data/src/org/httpkit/server/ServerAtta.class +0 -0
- data/src/org/httpkit/server/ServerAtta.java +22 -0
- data/src/org/httpkit/server/WSDecoder$State.class +0 -0
- data/src/org/httpkit/server/WSDecoder.class +0 -0
- data/src/org/httpkit/server/WSDecoder.java +181 -0
- data/src/org/httpkit/server/WSHandler.class +0 -0
- data/src/org/httpkit/server/WsAtta.class +0 -0
- data/src/org/httpkit/server/WsAtta.java +11 -0
- data/src/org/httpkit/timer/CancelableFutureTask.class +0 -0
- data/src/org/httpkit/timer/CancelableFutureTask.java +52 -0
- data/src/org/httpkit/timer/TimerService.class +0 -0
- data/src/org/httpkit/timer/TimerService.java +89 -0
- metadata +241 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
package org.httpkit;
|
2
|
+
|
3
|
+
import java.util.Arrays;
|
4
|
+
import java.util.Queue;
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Copy and modified from java.util.PriorityQueue. Remove unused method. Modify
|
8
|
+
* {@code remove} to return the removed element
|
9
|
+
* <p/>
|
10
|
+
* used by timer and the client
|
11
|
+
*
|
12
|
+
* @param <E>
|
13
|
+
*/
|
14
|
+
@SuppressWarnings("unchecked")
|
15
|
+
public class PriorityQueue<E> {
|
16
|
+
|
17
|
+
private static final int DEFAULT_INITIAL_CAPACITY = 11;
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Priority queue represented as a balanced binary heap: the two children of
|
21
|
+
* queue[n] are queue[2*n+1] and queue[2*(n+1)]. The priority queue is
|
22
|
+
* ordered by comparator, or by the elements' natural ordering, if
|
23
|
+
* comparator is null: For each node n in the heap and each descendant d of
|
24
|
+
* n, n <= d. The element with the lowest value is in queue[0], assuming the
|
25
|
+
* queue is nonempty.
|
26
|
+
*/
|
27
|
+
private transient Object[] queue;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* The number of elements in the priority queue.
|
31
|
+
*/
|
32
|
+
private int size = 0;
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Creates a {@code PriorityQueue} with the specified initial capacity that
|
36
|
+
* orders its elements according to their {@linkplain Comparable natural
|
37
|
+
* ordering}.
|
38
|
+
* <p/>
|
39
|
+
* the initial capacity for this priority queue
|
40
|
+
*
|
41
|
+
* @throws IllegalArgumentException if {@code initialCapacity} is less than 1
|
42
|
+
*/
|
43
|
+
public PriorityQueue() {
|
44
|
+
this.queue = new Object[DEFAULT_INITIAL_CAPACITY];
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* The maximum size of array to allocate. Some VMs reserve some header words
|
49
|
+
* in an array. Attempts to allocate larger arrays may result in
|
50
|
+
* OutOfMemoryError: Requested array size exceeds VM limit
|
51
|
+
*/
|
52
|
+
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Increases the capacity of the array.
|
56
|
+
*
|
57
|
+
* @param minCapacity the desired minimum capacity
|
58
|
+
*/
|
59
|
+
private void grow(int minCapacity) {
|
60
|
+
int oldCapacity = queue.length;
|
61
|
+
// Double size if small; else grow by 50%
|
62
|
+
int newCapacity = oldCapacity
|
63
|
+
+ ((oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1));
|
64
|
+
// overflow-conscious code
|
65
|
+
if (newCapacity - MAX_ARRAY_SIZE > 0)
|
66
|
+
newCapacity = hugeCapacity(minCapacity);
|
67
|
+
queue = Arrays.copyOf(queue, newCapacity);
|
68
|
+
}
|
69
|
+
|
70
|
+
private static int hugeCapacity(int minCapacity) {
|
71
|
+
if (minCapacity < 0) // overflow
|
72
|
+
throw new OutOfMemoryError();
|
73
|
+
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Inserts the specified element into this priority queue.
|
78
|
+
*
|
79
|
+
* @return {@code true} (as specified by {@link Queue#offer})
|
80
|
+
* @throws ClassCastException if the specified element cannot be compared with elements
|
81
|
+
* currently in this priority queue according to the priority
|
82
|
+
* queue's ordering
|
83
|
+
* @throws NullPointerException if the specified element is null
|
84
|
+
*/
|
85
|
+
public boolean offer(E e) {
|
86
|
+
if (e == null)
|
87
|
+
throw new NullPointerException();
|
88
|
+
int i = size;
|
89
|
+
if (i >= queue.length)
|
90
|
+
grow(i + 1);
|
91
|
+
size = i + 1;
|
92
|
+
if (i == 0)
|
93
|
+
queue[0] = e;
|
94
|
+
else
|
95
|
+
siftUp(i, e);
|
96
|
+
return true;
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Retrieves, but does not remove, the head of this queue, or returns null
|
101
|
+
* if this queue is empty.
|
102
|
+
*
|
103
|
+
* @return
|
104
|
+
*/
|
105
|
+
public E peek() {
|
106
|
+
if (size == 0)
|
107
|
+
return null;
|
108
|
+
return (E) queue[0];
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Removes a single instance of the specified element from this queue, if it
|
113
|
+
* is present. More formally, removes an element {@code e} such that
|
114
|
+
* {@code o.equals(e)}, if this queue contains one or more such elements.
|
115
|
+
* Returns {@code true} if and only if this queue contained the specified
|
116
|
+
* element (or equivalently, if this queue changed as a result of the call).
|
117
|
+
*
|
118
|
+
* @param o element to be removed from this queue, if present
|
119
|
+
* @return Element removed
|
120
|
+
*/
|
121
|
+
public E remove(Object o) {
|
122
|
+
for (int i = 0; i < size; i++) {
|
123
|
+
if (queue[i].equals(o)) {
|
124
|
+
E e = (E) queue[i];
|
125
|
+
removeAt(i);
|
126
|
+
return e;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return null;
|
130
|
+
}
|
131
|
+
|
132
|
+
public int size() {
|
133
|
+
return size;
|
134
|
+
}
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Retrieves and removes the head of this queue, or returns null if this
|
138
|
+
* queue is empty.
|
139
|
+
*/
|
140
|
+
public E poll() {
|
141
|
+
if (size == 0)
|
142
|
+
return null;
|
143
|
+
int s = --size;
|
144
|
+
E result = (E) queue[0];
|
145
|
+
E x = (E) queue[s];
|
146
|
+
queue[s] = null;
|
147
|
+
if (s != 0)
|
148
|
+
siftDown(0, x);
|
149
|
+
return result;
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Removes the ith element from queue.
|
154
|
+
* <p/>
|
155
|
+
* Normally this method leaves the elements at up to i-1, inclusive,
|
156
|
+
* untouched. Under these circumstances, it returns null. Occasionally, in
|
157
|
+
* order to maintain the heap invariant, it must swap a later element of the
|
158
|
+
* list with one earlier than i. Under these circumstances, this method
|
159
|
+
* returns the element that was previously at the end of the list and is now
|
160
|
+
* at some position before i. This fact is used by iterator.remove so as to
|
161
|
+
* avoid missing traversing elements.
|
162
|
+
*/
|
163
|
+
private E removeAt(int i) {
|
164
|
+
assert i >= 0 && i < size;
|
165
|
+
int s = --size;
|
166
|
+
if (s == i) // removed last element
|
167
|
+
queue[i] = null;
|
168
|
+
else {
|
169
|
+
E moved = (E) queue[s];
|
170
|
+
queue[s] = null;
|
171
|
+
siftDown(i, moved);
|
172
|
+
if (queue[i] == moved) {
|
173
|
+
siftUp(i, moved);
|
174
|
+
if (queue[i] != moved)
|
175
|
+
return moved;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
return null;
|
179
|
+
}
|
180
|
+
|
181
|
+
/**
|
182
|
+
* Inserts item x at position k, maintaining heap invariant by promoting x
|
183
|
+
* up the tree until it is greater than or equal to its parent, or is the
|
184
|
+
* root.
|
185
|
+
* <p/>
|
186
|
+
* To simplify and speed up coercions and comparisons. the Comparable and
|
187
|
+
* Comparator versions are separated into different methods that are
|
188
|
+
* otherwise identical. (Similarly for siftDown.)
|
189
|
+
*
|
190
|
+
* @param k the position to fill
|
191
|
+
* @param x the item to insert
|
192
|
+
*/
|
193
|
+
private void siftUp(int k, E x) {
|
194
|
+
Comparable<? super E> key = (Comparable<? super E>) x;
|
195
|
+
while (k > 0) {
|
196
|
+
int parent = (k - 1) >>> 1;
|
197
|
+
Object e = queue[parent];
|
198
|
+
if (key.compareTo((E) e) >= 0)
|
199
|
+
break;
|
200
|
+
queue[k] = e;
|
201
|
+
k = parent;
|
202
|
+
}
|
203
|
+
queue[k] = key;
|
204
|
+
}
|
205
|
+
|
206
|
+
/**
|
207
|
+
* Inserts item x at position k, maintaining heap invariant by demoting x
|
208
|
+
* down the tree repeatedly until it is less than or equal to its children
|
209
|
+
* or is a leaf.
|
210
|
+
*
|
211
|
+
* @param k the position to fill
|
212
|
+
* @param x the item to insert
|
213
|
+
*/
|
214
|
+
private void siftDown(int k, E x) {
|
215
|
+
Comparable<? super E> key = (Comparable<? super E>) x;
|
216
|
+
int half = size >>> 1; // loop while a non-leaf
|
217
|
+
while (k < half) {
|
218
|
+
int child = (k << 1) + 1; // assume left child is least
|
219
|
+
Object c = queue[child];
|
220
|
+
int right = child + 1;
|
221
|
+
if (right < size && ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
|
222
|
+
c = queue[child = right];
|
223
|
+
if (key.compareTo((E) c) <= 0)
|
224
|
+
break;
|
225
|
+
queue[k] = c;
|
226
|
+
k = child;
|
227
|
+
}
|
228
|
+
queue[k] = key;
|
229
|
+
}
|
230
|
+
|
231
|
+
@Override
|
232
|
+
public String toString() {
|
233
|
+
return "size=" + size;
|
234
|
+
}
|
235
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,182 @@
|
|
1
|
+
package org.httpkit.client;
|
2
|
+
|
3
|
+
import org.httpkit.*;
|
4
|
+
|
5
|
+
import java.nio.ByteBuffer;
|
6
|
+
import java.util.Map;
|
7
|
+
import java.util.TreeMap;
|
8
|
+
|
9
|
+
import static org.httpkit.HttpUtils.*;
|
10
|
+
import static org.httpkit.HttpVersion.HTTP_1_0;
|
11
|
+
import static org.httpkit.HttpVersion.HTTP_1_1;
|
12
|
+
import static org.httpkit.client.State.*;
|
13
|
+
|
14
|
+
enum State {
|
15
|
+
ALL_READ, READ_CHUNK_DELIMITER, READ_CHUNK_FOOTER, READ_CHUNK_SIZE,
|
16
|
+
READ_CHUNKED_CONTENT, READ_FIXED_LENGTH_CONTENT, READ_HEADER, READ_INITIAL,
|
17
|
+
READ_VARIABLE_LENGTH_CONTENT
|
18
|
+
}
|
19
|
+
|
20
|
+
public class Decoder {
|
21
|
+
|
22
|
+
private final Map<String, Object> headers = new TreeMap<String, Object>();
|
23
|
+
// package visible
|
24
|
+
final IRespListener listener;
|
25
|
+
private final LineReader lineReader;
|
26
|
+
int readRemaining = 0;
|
27
|
+
State state = READ_INITIAL;
|
28
|
+
private final HttpMethod method;
|
29
|
+
|
30
|
+
private boolean emptyBodyExpected = false;
|
31
|
+
|
32
|
+
public Decoder(IRespListener listener, HttpMethod method) {
|
33
|
+
this.listener = listener;
|
34
|
+
this.method = method;
|
35
|
+
lineReader = new LineReader(8096);
|
36
|
+
}
|
37
|
+
|
38
|
+
private void parseInitialLine(String sb) throws ProtocolException, AbortException {
|
39
|
+
int aStart;
|
40
|
+
int aEnd;
|
41
|
+
int bStart;
|
42
|
+
int bEnd;
|
43
|
+
int cStart;
|
44
|
+
int cEnd;
|
45
|
+
|
46
|
+
aStart = findNonWhitespace(sb, 0);
|
47
|
+
aEnd = findWhitespace(sb, aStart);
|
48
|
+
|
49
|
+
bStart = findNonWhitespace(sb, aEnd);
|
50
|
+
bEnd = findWhitespace(sb, bStart);
|
51
|
+
|
52
|
+
cStart = findNonWhitespace(sb, bEnd);
|
53
|
+
cEnd = findEndOfString(sb);
|
54
|
+
|
55
|
+
if ((cStart < cEnd)
|
56
|
+
// Account for buggy web servers that omit Reason-Phrase from Status-Line.
|
57
|
+
// http://www.w3.org/Protocols/HTTP/1.0/draft-ietf-http-spec.html#Response
|
58
|
+
|| (cStart == cEnd && bStart < bEnd)) {
|
59
|
+
try {
|
60
|
+
int status = Integer.parseInt(sb.substring(bStart, bEnd));
|
61
|
+
// status is not 1xx, 204 or 304, then the body is unbounded.
|
62
|
+
// RFC2616, section 4.4
|
63
|
+
emptyBodyExpected = status / 100 == 1 || status == 204 || status == 304;
|
64
|
+
HttpStatus s = HttpStatus.valueOf(status);
|
65
|
+
|
66
|
+
HttpVersion version = HTTP_1_1;
|
67
|
+
if ("HTTP/1.0".equals(sb.substring(aStart, aEnd))) {
|
68
|
+
version = HTTP_1_0;
|
69
|
+
}
|
70
|
+
|
71
|
+
listener.onInitialLineReceived(version, s);
|
72
|
+
state = READ_HEADER;
|
73
|
+
} catch (NumberFormatException e) {
|
74
|
+
throw new ProtocolException("not http protocol? " + sb);
|
75
|
+
}
|
76
|
+
} else {
|
77
|
+
throw new ProtocolException("not http protocol? " + sb);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
public State decode(ByteBuffer buffer) throws LineTooLargeException, ProtocolException,
|
82
|
+
AbortException {
|
83
|
+
String line;
|
84
|
+
while (buffer.hasRemaining() && state != State.ALL_READ) {
|
85
|
+
switch (state) {
|
86
|
+
case READ_INITIAL:
|
87
|
+
if ((line = lineReader.readLine(buffer)) != null) {
|
88
|
+
parseInitialLine(line);
|
89
|
+
}
|
90
|
+
break;
|
91
|
+
case READ_HEADER:
|
92
|
+
readHeaders(buffer);
|
93
|
+
break;
|
94
|
+
case READ_CHUNK_SIZE:
|
95
|
+
line = lineReader.readLine(buffer);
|
96
|
+
if (line != null && !line.isEmpty()) {
|
97
|
+
readRemaining = getChunkSize(line);
|
98
|
+
if (readRemaining == 0) {
|
99
|
+
state = READ_CHUNK_FOOTER;
|
100
|
+
} else {
|
101
|
+
state = READ_CHUNKED_CONTENT;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
break;
|
105
|
+
case READ_FIXED_LENGTH_CONTENT:
|
106
|
+
readBody(buffer, ALL_READ);
|
107
|
+
break;
|
108
|
+
case READ_CHUNKED_CONTENT:
|
109
|
+
readBody(buffer, READ_CHUNK_DELIMITER);
|
110
|
+
break;
|
111
|
+
case READ_CHUNK_FOOTER:
|
112
|
+
readEmptyLine(buffer);
|
113
|
+
state = ALL_READ;
|
114
|
+
break;
|
115
|
+
case READ_CHUNK_DELIMITER:
|
116
|
+
readEmptyLine(buffer);
|
117
|
+
state = READ_CHUNK_SIZE;
|
118
|
+
break;
|
119
|
+
case READ_VARIABLE_LENGTH_CONTENT:
|
120
|
+
readBody(buffer, null);
|
121
|
+
break;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
return state;
|
125
|
+
}
|
126
|
+
|
127
|
+
private void readBody(ByteBuffer buffer, State nextState) throws AbortException {
|
128
|
+
int toRead = Math.min(buffer.remaining(), readRemaining);
|
129
|
+
byte[] bytes = new byte[toRead];
|
130
|
+
buffer.get(bytes, 0, toRead);
|
131
|
+
listener.onBodyReceived(bytes, toRead);
|
132
|
+
if (nextState != null) {
|
133
|
+
readRemaining -= toRead;
|
134
|
+
if (readRemaining == 0) {
|
135
|
+
state = nextState;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
void readEmptyLine(ByteBuffer buffer) {
|
141
|
+
byte b = buffer.get();
|
142
|
+
if (b == CR && buffer.hasRemaining()) {
|
143
|
+
buffer.get(); // should be LF
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
private void readHeaders(ByteBuffer buffer) throws LineTooLargeException, AbortException {
|
148
|
+
String line = lineReader.readLine(buffer);
|
149
|
+
while (line != null && !line.isEmpty()) {
|
150
|
+
HttpUtils.splitAndAddHeader(line, headers);
|
151
|
+
line = lineReader.readLine(buffer);
|
152
|
+
}
|
153
|
+
if (line == null)
|
154
|
+
return; // data is not received enough. for next run
|
155
|
+
listener.onHeadersReceived(headers);
|
156
|
+
if (method == HttpMethod.HEAD) {
|
157
|
+
state = ALL_READ;
|
158
|
+
return;
|
159
|
+
}
|
160
|
+
|
161
|
+
String te = HttpUtils.getStringValue(headers, TRANSFER_ENCODING);
|
162
|
+
if (CHUNKED.equals(te)) {
|
163
|
+
state = READ_CHUNK_SIZE;
|
164
|
+
} else {
|
165
|
+
String cl = HttpUtils.getStringValue(headers, CONTENT_LENGTH);
|
166
|
+
if (cl != null) {
|
167
|
+
readRemaining = Integer.parseInt(cl);
|
168
|
+
if (readRemaining == 0) {
|
169
|
+
state = ALL_READ;
|
170
|
+
} else {
|
171
|
+
state = READ_FIXED_LENGTH_CONTENT;
|
172
|
+
}
|
173
|
+
} else if (emptyBodyExpected) {
|
174
|
+
state = ALL_READ;
|
175
|
+
} else {
|
176
|
+
state = READ_VARIABLE_LENGTH_CONTENT;
|
177
|
+
// for readBody min
|
178
|
+
readRemaining = Integer.MAX_VALUE;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
Binary file
|
Binary file
|