jruby-http-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +72 -0
  7. data/Rakefile +1 -0
  8. data/example/config.ru +9 -0
  9. data/example/hello_world.rb +17 -0
  10. data/example/rack.rb +11 -0
  11. data/example/ring.rb +31 -0
  12. data/example/sinatra/app.rb +9 -0
  13. data/example/sinatra/config.ru +8 -0
  14. data/example/webmachine/Gemfile +4 -0
  15. data/example/webmachine/Gemfile.lock +16 -0
  16. data/example/webmachine/app.rb +37 -0
  17. data/jruby-http-kit.gemspec +25 -0
  18. data/lib/http_kit/rack_handler.rb +139 -0
  19. data/lib/http_kit/server.rb +62 -0
  20. data/lib/http_kit/version.rb +3 -0
  21. data/lib/http_kit.rb +6 -0
  22. data/lib/java/clojure-1.5.1.jar +0 -0
  23. data/lib/java/http-kit.jar +0 -0
  24. data/lib/rack/handler/http_kit.rb +3 -0
  25. data/lib/rack/http_kit.rb +3 -0
  26. data/lib/webmachine/adapters/ring.rb +135 -0
  27. data/spec/spec_helper.rb +24 -0
  28. data/spec/support/test_resource.rb +75 -0
  29. data/spec/webmachine/ring_adapter_spec.rb +127 -0
  30. data/src/.classpath +7 -0
  31. data/src/.project +17 -0
  32. data/src/org/httpkit/BytesInputStream.class +0 -0
  33. data/src/org/httpkit/BytesInputStream.java +83 -0
  34. data/src/org/httpkit/DateFormatter.class +0 -0
  35. data/src/org/httpkit/DynamicBytes.class +0 -0
  36. data/src/org/httpkit/DynamicBytes.java +76 -0
  37. data/src/org/httpkit/HTTPException.class +0 -0
  38. data/src/org/httpkit/HTTPException.java +10 -0
  39. data/src/org/httpkit/HeaderMap.class +0 -0
  40. data/src/org/httpkit/HeaderMap.java +98 -0
  41. data/src/org/httpkit/HttpMethod.class +0 -0
  42. data/src/org/httpkit/HttpMethod.java +28 -0
  43. data/src/org/httpkit/HttpStatus.class +0 -0
  44. data/src/org/httpkit/HttpStatus.java +416 -0
  45. data/src/org/httpkit/HttpUtils.class +0 -0
  46. data/src/org/httpkit/HttpUtils.java +484 -0
  47. data/src/org/httpkit/HttpVersion.class +0 -0
  48. data/src/org/httpkit/HttpVersion.java +5 -0
  49. data/src/org/httpkit/LineReader.class +0 -0
  50. data/src/org/httpkit/LineReader.java +52 -0
  51. data/src/org/httpkit/LineTooLargeException.class +0 -0
  52. data/src/org/httpkit/LineTooLargeException.java +13 -0
  53. data/src/org/httpkit/PrefixThreadFactory.class +0 -0
  54. data/src/org/httpkit/PrefixThreadFactory.java +20 -0
  55. data/src/org/httpkit/PriorityQueue.class +0 -0
  56. data/src/org/httpkit/PriorityQueue.java +235 -0
  57. data/src/org/httpkit/ProtocolException.class +0 -0
  58. data/src/org/httpkit/ProtocolException.java +10 -0
  59. data/src/org/httpkit/RequestTooLargeException.class +0 -0
  60. data/src/org/httpkit/RequestTooLargeException.java +10 -0
  61. data/src/org/httpkit/client/AbortException.class +0 -0
  62. data/src/org/httpkit/client/AbortException.java +13 -0
  63. data/src/org/httpkit/client/Decoder.class +0 -0
  64. data/src/org/httpkit/client/Decoder.java +182 -0
  65. data/src/org/httpkit/client/Handler.class +0 -0
  66. data/src/org/httpkit/client/HttpClient.class +0 -0
  67. data/src/org/httpkit/client/HttpClient.java +393 -0
  68. data/src/org/httpkit/client/HttpsRequest.class +0 -0
  69. data/src/org/httpkit/client/HttpsRequest.java +141 -0
  70. data/src/org/httpkit/client/IFilter$1.class +0 -0
  71. data/src/org/httpkit/client/IFilter$MaxBodyFilter.class +0 -0
  72. data/src/org/httpkit/client/IFilter.class +0 -0
  73. data/src/org/httpkit/client/IFilter.java +53 -0
  74. data/src/org/httpkit/client/IRespListener.class +0 -0
  75. data/src/org/httpkit/client/IRespListener.java +30 -0
  76. data/src/org/httpkit/client/IResponseHandler.class +0 -0
  77. data/src/org/httpkit/client/IResponseHandler.java +18 -0
  78. data/src/org/httpkit/client/PersistentConn.class +0 -0
  79. data/src/org/httpkit/client/PersistentConn.java +33 -0
  80. data/src/org/httpkit/client/Request.class +0 -0
  81. data/src/org/httpkit/client/Request.java +74 -0
  82. data/src/org/httpkit/client/RequestConfig.class +0 -0
  83. data/src/org/httpkit/client/RequestConfig.java +28 -0
  84. data/src/org/httpkit/client/RespListener.class +0 -0
  85. data/src/org/httpkit/client/RespListener.java +160 -0
  86. data/src/org/httpkit/client/SslContextFactory.class +0 -0
  87. data/src/org/httpkit/client/SslContextFactory.java +79 -0
  88. data/src/org/httpkit/client/State.class +0 -0
  89. data/src/org/httpkit/client/TimeoutException.class +0 -0
  90. data/src/org/httpkit/client/TimeoutException.java +12 -0
  91. data/src/org/httpkit/client/TrustManagerFactory$1.class +0 -0
  92. data/src/org/httpkit/client/TrustManagerFactory.class +0 -0
  93. data/src/org/httpkit/server/AsyncChannel.class +0 -0
  94. data/src/org/httpkit/server/AsyncChannel.java +286 -0
  95. data/src/org/httpkit/server/ClojureRing.class +0 -0
  96. data/src/org/httpkit/server/Frame$BinaryFrame.class +0 -0
  97. data/src/org/httpkit/server/Frame$CloseFrame.class +0 -0
  98. data/src/org/httpkit/server/Frame$PingFrame.class +0 -0
  99. data/src/org/httpkit/server/Frame$TextFrame.class +0 -0
  100. data/src/org/httpkit/server/Frame.class +0 -0
  101. data/src/org/httpkit/server/Frame.java +73 -0
  102. data/src/org/httpkit/server/HttpAtta.class +0 -0
  103. data/src/org/httpkit/server/HttpAtta.java +10 -0
  104. data/src/org/httpkit/server/HttpDecoder$State.class +0 -0
  105. data/src/org/httpkit/server/HttpDecoder.class +0 -0
  106. data/src/org/httpkit/server/HttpDecoder.java +202 -0
  107. data/src/org/httpkit/server/HttpHandler.class +0 -0
  108. data/src/org/httpkit/server/HttpRequest.class +0 -0
  109. data/src/org/httpkit/server/HttpRequest.java +109 -0
  110. data/src/org/httpkit/server/HttpServer.class +0 -0
  111. data/src/org/httpkit/server/HttpServer.java +281 -0
  112. data/src/org/httpkit/server/IHandler.class +0 -0
  113. data/src/org/httpkit/server/IHandler.java +12 -0
  114. data/src/org/httpkit/server/LinkingRunnable.class +0 -0
  115. data/src/org/httpkit/server/Rack.class +0 -0
  116. data/src/org/httpkit/server/RackApplication.class +0 -0
  117. data/src/org/httpkit/server/RackApplication.java +10 -0
  118. data/src/org/httpkit/server/RackHandler$1.class +0 -0
  119. data/src/org/httpkit/server/RackHandler.class +0 -0
  120. data/src/org/httpkit/server/RackHandler.java +259 -0
  121. data/src/org/httpkit/server/RackHttpHandler.class +0 -0
  122. data/src/org/httpkit/server/RackHttpHandler.java +20 -0
  123. data/src/org/httpkit/server/RespCallback.class +0 -0
  124. data/src/org/httpkit/server/RespCallback.java +19 -0
  125. data/src/org/httpkit/server/RingHandler$1.class +0 -0
  126. data/src/org/httpkit/server/RingHandler.class +0 -0
  127. data/src/org/httpkit/server/RingHandler.java +222 -0
  128. data/src/org/httpkit/server/ServerAtta.class +0 -0
  129. data/src/org/httpkit/server/ServerAtta.java +22 -0
  130. data/src/org/httpkit/server/WSDecoder$State.class +0 -0
  131. data/src/org/httpkit/server/WSDecoder.class +0 -0
  132. data/src/org/httpkit/server/WSDecoder.java +181 -0
  133. data/src/org/httpkit/server/WSHandler.class +0 -0
  134. data/src/org/httpkit/server/WsAtta.class +0 -0
  135. data/src/org/httpkit/server/WsAtta.java +11 -0
  136. data/src/org/httpkit/timer/CancelableFutureTask.class +0 -0
  137. data/src/org/httpkit/timer/CancelableFutureTask.java +52 -0
  138. data/src/org/httpkit/timer/TimerService.class +0 -0
  139. data/src/org/httpkit/timer/TimerService.java +89 -0
  140. 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
+ }
@@ -0,0 +1,10 @@
1
+ package org.httpkit;
2
+
3
+ public class ProtocolException extends HTTPException {
4
+
5
+ private static final long serialVersionUID = 1L;
6
+
7
+ public ProtocolException(String msg) {
8
+ super(msg);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ package org.httpkit;
2
+
3
+ public class RequestTooLargeException extends HTTPException {
4
+
5
+ private static final long serialVersionUID = 1L;
6
+
7
+ public RequestTooLargeException(String msg) {
8
+ super(msg);
9
+ }
10
+ }
@@ -0,0 +1,13 @@
1
+ package org.httpkit.client;
2
+
3
+ import org.httpkit.HTTPException;
4
+
5
+ public class AbortException extends HTTPException {
6
+
7
+ public AbortException(String msg) {
8
+ super(msg);
9
+ }
10
+
11
+ private static final long serialVersionUID = 1L;
12
+
13
+ }
@@ -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
+ }