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.http.impl.nio;
29
30 import java.io.IOException;
31 import java.nio.channels.SelectionKey;
32 import java.nio.charset.CharsetDecoder;
33 import java.nio.charset.CharsetEncoder;
34
35 import org.apache.http.HttpEntity;
36 import org.apache.http.HttpEntityEnclosingRequest;
37 import org.apache.http.HttpException;
38 import org.apache.http.HttpRequest;
39 import org.apache.http.HttpRequestFactory;
40 import org.apache.http.HttpResponse;
41 import org.apache.http.config.MessageConstraints;
42 import org.apache.http.entity.ContentLengthStrategy;
43 import org.apache.http.impl.entity.DisallowIdentityContentLengthStrategy;
44 import org.apache.http.impl.entity.LaxContentLengthStrategy;
45 import org.apache.http.impl.entity.StrictContentLengthStrategy;
46 import org.apache.http.impl.nio.codecs.DefaultHttpRequestParser;
47 import org.apache.http.impl.nio.codecs.DefaultHttpRequestParserFactory;
48 import org.apache.http.impl.nio.codecs.DefaultHttpResponseWriter;
49 import org.apache.http.impl.nio.codecs.DefaultHttpResponseWriterFactory;
50 import org.apache.http.nio.NHttpMessageParser;
51 import org.apache.http.nio.NHttpMessageParserFactory;
52 import org.apache.http.nio.NHttpMessageWriter;
53 import org.apache.http.nio.NHttpMessageWriterFactory;
54 import org.apache.http.nio.NHttpServerEventHandler;
55 import org.apache.http.nio.NHttpServerIOTarget;
56 import org.apache.http.nio.NHttpServiceHandler;
57 import org.apache.http.nio.reactor.EventMask;
58 import org.apache.http.nio.reactor.IOSession;
59 import org.apache.http.nio.reactor.SessionInputBuffer;
60 import org.apache.http.nio.reactor.SessionOutputBuffer;
61 import org.apache.http.nio.util.ByteBufferAllocator;
62 import org.apache.http.params.HttpParamConfig;
63 import org.apache.http.params.HttpParams;
64 import org.apache.http.util.Args;
65
66
67
68
69
70
71
72 @SuppressWarnings("deprecation")
73 public class DefaultNHttpServerConnection
74 extends NHttpConnectionBase implements NHttpServerIOTarget {
75
76 protected final NHttpMessageParser<HttpRequest> requestParser;
77 protected final NHttpMessageWriter<HttpResponse> responseWriter;
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 @Deprecated
93 public DefaultNHttpServerConnection(
94 final IOSession session,
95 final HttpRequestFactory requestFactory,
96 final ByteBufferAllocator allocator,
97 final HttpParams params) {
98 super(session, allocator, params);
99 Args.notNull(requestFactory, "Request factory");
100 this.requestParser = createRequestParser(this.inbuf, requestFactory, params);
101 this.responseWriter = createResponseWriter(this.outbuf, params);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 public DefaultNHttpServerConnection(
131 final IOSession session,
132 final int bufferSize,
133 final int fragmentSizeHint,
134 final ByteBufferAllocator allocator,
135 final CharsetDecoder charDecoder,
136 final CharsetEncoder charEncoder,
137 final MessageConstraints constraints,
138 final ContentLengthStrategy incomingContentStrategy,
139 final ContentLengthStrategy outgoingContentStrategy,
140 final NHttpMessageParserFactory<HttpRequest> requestParserFactory,
141 final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory) {
142 super(session, bufferSize, fragmentSizeHint, allocator, charDecoder, charEncoder,
143 constraints,
144 incomingContentStrategy != null ? incomingContentStrategy :
145 DisallowIdentityContentLengthStrategy.INSTANCE,
146 outgoingContentStrategy != null ? outgoingContentStrategy :
147 StrictContentLengthStrategy.INSTANCE);
148 this.requestParser = (requestParserFactory != null ? requestParserFactory :
149 DefaultHttpRequestParserFactory.INSTANCE).create(this.inbuf, constraints);
150 this.responseWriter = (responseWriterFactory != null ? responseWriterFactory :
151 DefaultHttpResponseWriterFactory.INSTANCE).create(this.outbuf);
152 }
153
154
155
156
157 public DefaultNHttpServerConnection(
158 final IOSession session,
159 final int bufferSize,
160 final CharsetDecoder charDecoder,
161 final CharsetEncoder charEncoder,
162 final MessageConstraints constraints) {
163 this(session, bufferSize, bufferSize, null, charDecoder, charEncoder, constraints,
164 null, null, null, null);
165 }
166
167
168
169
170 public DefaultNHttpServerConnection(final IOSession session, final int bufferSize) {
171 this(session, bufferSize, bufferSize, null, null, null, null, null, null, null, null);
172 }
173
174
175
176
177 @Override
178 @Deprecated
179 protected ContentLengthStrategy createIncomingContentStrategy() {
180 return new DisallowIdentityContentLengthStrategy(new LaxContentLengthStrategy(0));
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194 @Deprecated
195 protected NHttpMessageParser<HttpRequest> createRequestParser(
196 final SessionInputBuffer buffer,
197 final HttpRequestFactory requestFactory,
198 final HttpParams params) {
199 final MessageConstraints constraints = HttpParamConfig.getMessageConstraints(params);
200 return new DefaultHttpRequestParser(buffer, null, requestFactory, constraints);
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215 @Deprecated
216 protected NHttpMessageWriter<HttpResponse> createResponseWriter(
217 final SessionOutputBuffer buffer,
218 final HttpParams params) {
219
220 return new DefaultHttpResponseWriter(buffer, null);
221 }
222
223
224
225
226 protected void onRequestReceived(final HttpRequest request) {
227 }
228
229
230
231
232 protected void onResponseSubmitted(final HttpResponse response) {
233 }
234
235 @Override
236 public void resetInput() {
237 this.request = null;
238 this.contentDecoder = null;
239 this.requestParser.reset();
240 }
241
242 @Override
243 public void resetOutput() {
244 this.response = null;
245 this.contentEncoder = null;
246 this.responseWriter.reset();
247 }
248
249 public void consumeInput(final NHttpServerEventHandler handler) {
250 if (this.status != ACTIVE) {
251 this.session.clearEvent(EventMask.READ);
252 return;
253 }
254 try {
255 if (this.request == null) {
256 int bytesRead;
257 do {
258 bytesRead = this.requestParser.fillBuffer(this.session.channel());
259 if (bytesRead > 0) {
260 this.inTransportMetrics.incrementBytesTransferred(bytesRead);
261 }
262 this.request = this.requestParser.parse();
263 } while (bytesRead > 0 && this.request == null);
264 if (this.request != null) {
265 if (this.request instanceof HttpEntityEnclosingRequest) {
266
267 final HttpEntity entity = prepareDecoder(this.request);
268 ((HttpEntityEnclosingRequest)this.request).setEntity(entity);
269 }
270 this.connMetrics.incrementRequestCount();
271 this.hasBufferedInput = this.inbuf.hasData();
272 onRequestReceived(this.request);
273 handler.requestReceived(this);
274 if (this.contentDecoder == null) {
275
276
277 resetInput();
278 }
279 }
280 if (bytesRead == -1 && !this.inbuf.hasData()) {
281 handler.endOfInput(this);
282 }
283 }
284 if (this.contentDecoder != null && (this.session.getEventMask() & SelectionKey.OP_READ) > 0) {
285 handler.inputReady(this, this.contentDecoder);
286 if (this.contentDecoder.isCompleted()) {
287
288
289 resetInput();
290 }
291 }
292 } catch (final HttpException ex) {
293 handler.exception(this, ex);
294 } catch (final Exception ex) {
295 handler.exception(this, ex);
296 } finally {
297
298 this.hasBufferedInput = this.inbuf.hasData();
299 }
300 }
301
302 public void produceOutput(final NHttpServerEventHandler handler) {
303 try {
304 if (this.status == ACTIVE) {
305 if (this.contentEncoder == null && !this.outbuf.hasData()) {
306 handler.responseReady(this);
307 }
308 if (this.contentEncoder != null) {
309 handler.outputReady(this, this.contentEncoder);
310 if (this.contentEncoder.isCompleted()) {
311 resetOutput();
312 }
313 }
314 }
315 if (this.outbuf.hasData()) {
316 final int bytesWritten = this.outbuf.flush(this.session.channel());
317 if (bytesWritten > 0) {
318 this.outTransportMetrics.incrementBytesTransferred(bytesWritten);
319 }
320 }
321 if (!this.outbuf.hasData()) {
322 if (this.status == CLOSING) {
323 this.session.close();
324 this.status = CLOSED;
325 resetOutput();
326 }
327 }
328 } catch (final Exception ex) {
329 handler.exception(this, ex);
330 } finally {
331
332 this.hasBufferedOutput = this.outbuf.hasData();
333 }
334 }
335
336 @Override
337 public void submitResponse(final HttpResponse response) throws IOException, HttpException {
338 Args.notNull(response, "HTTP response");
339 assertNotClosed();
340 if (this.response != null) {
341 throw new HttpException("Response already submitted");
342 }
343 onResponseSubmitted(response);
344 this.responseWriter.write(response);
345 this.hasBufferedOutput = this.outbuf.hasData();
346
347 if (response.getStatusLine().getStatusCode() >= 200) {
348 this.connMetrics.incrementResponseCount();
349 if (response.getEntity() != null) {
350 this.response = response;
351 prepareEncoder(response);
352 }
353 }
354
355 this.session.setEvent(EventMask.WRITE);
356 }
357
358 @Override
359 public boolean isResponseSubmitted() {
360 return this.response != null;
361 }
362
363 @Override
364 public void consumeInput(final NHttpServiceHandler handler) {
365 consumeInput(new NHttpServerEventHandlerAdaptor(handler));
366 }
367
368 @Override
369 public void produceOutput(final NHttpServiceHandler handler) {
370 produceOutput(new NHttpServerEventHandlerAdaptor(handler));
371 }
372
373 }