1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.client.http;
20
21 import java.io.EOFException;
22 import java.nio.ByteBuffer;
23
24 import org.eclipse.jetty.client.HttpClient;
25 import org.eclipse.jetty.client.HttpExchange;
26 import org.eclipse.jetty.client.HttpReceiver;
27 import org.eclipse.jetty.client.HttpResponse;
28 import org.eclipse.jetty.client.HttpResponseException;
29 import org.eclipse.jetty.http.HttpField;
30 import org.eclipse.jetty.http.HttpMethod;
31 import org.eclipse.jetty.http.HttpParser;
32 import org.eclipse.jetty.http.HttpVersion;
33 import org.eclipse.jetty.io.ByteBufferPool;
34 import org.eclipse.jetty.io.EndPoint;
35 import org.eclipse.jetty.io.EofException;
36 import org.eclipse.jetty.util.BufferUtil;
37
38 public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
39 {
40 private final HttpParser parser = new HttpParser(this);
41
42 public HttpReceiverOverHTTP(HttpChannelOverHTTP channel)
43 {
44 super(channel);
45 }
46
47 @Override
48 public HttpChannelOverHTTP getHttpChannel()
49 {
50 return (HttpChannelOverHTTP)super.getHttpChannel();
51 }
52
53 private HttpConnectionOverHTTP getHttpConnection()
54 {
55 return getHttpChannel().getHttpConnection();
56 }
57
58 public void receive()
59 {
60 HttpConnectionOverHTTP connection = getHttpConnection();
61 EndPoint endPoint = connection.getEndPoint();
62 HttpClient client = getHttpDestination().getHttpClient();
63 ByteBufferPool bufferPool = client.getByteBufferPool();
64 ByteBuffer buffer = bufferPool.acquire(client.getResponseBufferSize(), true);
65 try
66 {
67 while (true)
68 {
69
70 if (connection.isClosed())
71 {
72 LOG.debug("{} closed", connection);
73 break;
74 }
75 else
76 {
77 int read = endPoint.fill(buffer);
78 if (LOG.isDebugEnabled())
79 LOG.debug("Read {} bytes from {}", read, endPoint);
80 if (read > 0)
81 {
82 parse(buffer);
83 }
84 else if (read == 0)
85 {
86 fillInterested();
87 break;
88 }
89 else
90 {
91 shutdown();
92 break;
93 }
94 }
95 }
96 }
97 catch (EofException x)
98 {
99 LOG.ignore(x);
100 failAndClose(x);
101 }
102 catch (Exception x)
103 {
104 LOG.debug(x);
105 failAndClose(x);
106 }
107 finally
108 {
109 bufferPool.release(buffer);
110 }
111 }
112
113 private void parse(ByteBuffer buffer)
114 {
115 while (buffer.hasRemaining())
116 parser.parseNext(buffer);
117 }
118
119 private void fillInterested()
120 {
121
122 getHttpChannel().getHttpConnection().fillInterested();
123 }
124
125 private void shutdown()
126 {
127
128 parser.atEOF();
129 parser.parseNext(BufferUtil.EMPTY_BUFFER);
130 if (!responseFailure(new EOFException()))
131 getHttpChannel().getHttpConnection().close();
132 }
133
134 @Override
135 public int getHeaderCacheSize()
136 {
137
138 return 256;
139 }
140
141 @Override
142 public boolean startResponse(HttpVersion version, int status, String reason)
143 {
144 HttpExchange exchange = getHttpExchange();
145 if (exchange == null)
146 return false;
147
148 String method = exchange.getRequest().getMethod();
149 parser.setHeadResponse(HttpMethod.HEAD.is(method) || HttpMethod.CONNECT.is(method));
150 exchange.getResponse().version(version).status(status).reason(reason);
151
152 responseBegin(exchange);
153 return false;
154 }
155
156 @Override
157 public boolean parsedHeader(HttpField field)
158 {
159 HttpExchange exchange = getHttpExchange();
160 if (exchange == null)
161 return false;
162
163 responseHeader(exchange, field);
164 return false;
165 }
166
167 @Override
168 public boolean headerComplete()
169 {
170 HttpExchange exchange = getHttpExchange();
171 if (exchange == null)
172 return false;
173
174 responseHeaders(exchange);
175 return false;
176 }
177
178 @Override
179 public boolean content(ByteBuffer buffer)
180 {
181 HttpExchange exchange = getHttpExchange();
182 if (exchange == null)
183 return false;
184
185 responseContent(exchange, buffer);
186 return false;
187 }
188
189 @Override
190 public boolean messageComplete()
191 {
192 HttpExchange exchange = getHttpExchange();
193 if (exchange == null)
194 return false;
195
196 responseSuccess(exchange);
197 return true;
198 }
199
200 @Override
201 public void earlyEOF()
202 {
203 failAndClose(new EOFException());
204 }
205
206 @Override
207 public void badMessage(int status, String reason)
208 {
209 HttpExchange exchange = getHttpExchange();
210 if (exchange != null)
211 {
212 HttpResponse response = exchange.getResponse();
213 response.status(status).reason(reason);
214 failAndClose(new HttpResponseException("HTTP protocol violation: bad response", response));
215 }
216 }
217
218 @Override
219 protected void reset()
220 {
221 super.reset();
222 parser.reset();
223 }
224
225 @Override
226 protected void dispose()
227 {
228 super.dispose();
229 parser.close();
230 }
231
232 private void failAndClose(Throwable failure)
233 {
234 if (responseFailure(failure))
235 getHttpChannel().getHttpConnection().close();
236 }
237
238 @Override
239 public String toString()
240 {
241 return String.format("%s@%x on %s", getClass().getSimpleName(), hashCode(), getHttpConnection());
242 }
243 }