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.annotation.NotThreadSafe;
42 import org.apache.http.config.MessageConstraints;
43 import org.apache.http.entity.ContentLengthStrategy;
44 import org.apache.http.impl.entity.DisallowIdentityContentLengthStrategy;
45 import org.apache.http.impl.entity.LaxContentLengthStrategy;
46 import org.apache.http.impl.entity.StrictContentLengthStrategy;
47 import org.apache.http.impl.nio.codecs.DefaultHttpRequestParser;
48 import org.apache.http.impl.nio.codecs.DefaultHttpRequestParserFactory;
49 import org.apache.http.impl.nio.codecs.DefaultHttpResponseWriter;
50 import org.apache.http.impl.nio.codecs.DefaultHttpResponseWriterFactory;
51 import org.apache.http.nio.NHttpMessageParser;
52 import org.apache.http.nio.NHttpMessageParserFactory;
53 import org.apache.http.nio.NHttpMessageWriter;
54 import org.apache.http.nio.NHttpMessageWriterFactory;
55 import org.apache.http.nio.NHttpServerConnection;
56 import org.apache.http.nio.NHttpServerEventHandler;
57 import org.apache.http.nio.NHttpServerIOTarget;
58 import org.apache.http.nio.NHttpServiceHandler;
59 import org.apache.http.nio.reactor.EventMask;
60 import org.apache.http.nio.reactor.IOSession;
61 import org.apache.http.nio.reactor.SessionInputBuffer;
62 import org.apache.http.nio.reactor.SessionOutputBuffer;
63 import org.apache.http.nio.util.ByteBufferAllocator;
64 import org.apache.http.nio.util.HeapByteBufferAllocator;
65 import org.apache.http.params.HttpParamConfig;
66 import org.apache.http.params.HttpParams;
67 import org.apache.http.util.Args;
68
69
70
71
72
73
74 @SuppressWarnings("deprecation")
75 @NotThreadSafe
76 public class DefaultNHttpServerConnection
77 extends NHttpConnectionBase implements NHttpServerIOTarget {
78
79 protected final NHttpMessageParser<HttpRequest> requestParser;
80 protected final NHttpMessageWriter<HttpResponse> responseWriter;
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 @Deprecated
96 public DefaultNHttpServerConnection(
97 final IOSession session,
98 final HttpRequestFactory requestFactory,
99 final ByteBufferAllocator allocator,
100 final HttpParams params) {
101 super(session, allocator, params);
102 Args.notNull(requestFactory, "Request factory");
103 this.requestParser = createRequestParser(this.inbuf, requestFactory, params);
104 this.responseWriter = createResponseWriter(this.outbuf, params);
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
131
132 public DefaultNHttpServerConnection(
133 final IOSession session,
134 final int buffersize,
135 final int fragmentSizeHint,
136 final ByteBufferAllocator allocator,
137 final CharsetDecoder chardecoder,
138 final CharsetEncoder charencoder,
139 final MessageConstraints constraints,
140 final ContentLengthStrategy incomingContentStrategy,
141 final ContentLengthStrategy outgoingContentStrategy,
142 final NHttpMessageParserFactory<HttpRequest> requestParserFactory,
143 final NHttpMessageWriterFactory<HttpResponse> responseWriterFactory) {
144 super(session, buffersize, fragmentSizeHint, allocator, chardecoder, charencoder,
145 constraints,
146 incomingContentStrategy != null ? incomingContentStrategy :
147 DisallowIdentityContentLengthStrategy.INSTANCE,
148 outgoingContentStrategy != null ? outgoingContentStrategy :
149 StrictContentLengthStrategy.INSTANCE);
150 this.requestParser = (requestParserFactory != null ? requestParserFactory :
151 DefaultHttpRequestParserFactory.INSTANCE).create(this.inbuf, constraints);
152 this.responseWriter = (responseWriterFactory != null ? responseWriterFactory :
153 DefaultHttpResponseWriterFactory.INSTANCE).create(this.outbuf);
154 }
155
156
157
158
159 public DefaultNHttpServerConnection(
160 final IOSession session,
161 final int buffersize,
162 final CharsetDecoder chardecoder,
163 final CharsetEncoder charencoder,
164 final MessageConstraints constraints) {
165 this(session, buffersize, buffersize, null, chardecoder, charencoder, constraints,
166 null, null, null, null);
167 }
168
169
170
171
172 public DefaultNHttpServerConnection(final IOSession session, final int buffersize) {
173 this(session, buffersize, buffersize, null, null, null, null, null, null, null, null);
174 }
175
176
177
178
179 @Override
180 @Deprecated
181 protected ContentLengthStrategy createIncomingContentStrategy() {
182 return new DisallowIdentityContentLengthStrategy(new LaxContentLengthStrategy(0));
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196 @Deprecated
197 protected NHttpMessageParser<HttpRequest> createRequestParser(
198 final SessionInputBuffer buffer,
199 final HttpRequestFactory requestFactory,
200 final HttpParams params) {
201 final MessageConstraints constraints = HttpParamConfig.getMessageConstraints(params);
202 return new DefaultHttpRequestParser(buffer, null, requestFactory, constraints);
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217 @Deprecated
218 protected NHttpMessageWriter<HttpResponse> createResponseWriter(
219 final SessionOutputBuffer buffer,
220 final HttpParams params) {
221
222 return new DefaultHttpResponseWriter(buffer, null);
223 }
224
225
226
227
228 protected void onRequestReceived(final HttpRequest request) {
229 }
230
231
232
233
234 protected void onResponseSubmitted(final HttpResponse response) {
235 }
236
237 public void resetInput() {
238 this.request = null;
239 this.contentDecoder = null;
240 this.requestParser.reset();
241 }
242
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 onRequestReceived(this.request);
272 handler.requestReceived(this);
273 if (this.contentDecoder == null) {
274
275
276 resetInput();
277 }
278 }
279 if (bytesRead == -1) {
280 handler.endOfInput(this);
281 }
282 }
283 if (this.contentDecoder != null && (this.session.getEventMask() & SelectionKey.OP_READ) > 0) {
284 handler.inputReady(this, this.contentDecoder);
285 if (this.contentDecoder.isCompleted()) {
286
287
288 resetInput();
289 }
290 }
291 } catch (final HttpException ex) {
292 resetInput();
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) {
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 if (this.contentEncoder == null && this.status != CLOSED) {
328 this.session.clearEvent(EventMask.WRITE);
329 }
330 }
331 } catch (final Exception ex) {
332 handler.exception(this, ex);
333 } finally {
334
335 this.hasBufferedOutput = this.outbuf.hasData();
336 }
337 }
338
339 public void submitResponse(final HttpResponse response) throws IOException, HttpException {
340 Args.notNull(response, "HTTP response");
341 assertNotClosed();
342 if (this.response != null) {
343 throw new HttpException("Response already submitted");
344 }
345 onResponseSubmitted(response);
346 this.responseWriter.write(response);
347 this.hasBufferedOutput = this.outbuf.hasData();
348
349 if (response.getStatusLine().getStatusCode() >= 200) {
350 this.connMetrics.incrementResponseCount();
351 if (response.getEntity() != null) {
352 this.response = response;
353 prepareEncoder(response);
354 }
355 }
356
357 this.session.setEvent(EventMask.WRITE);
358 }
359
360 public boolean isResponseSubmitted() {
361 return this.response != null;
362 }
363
364 public void consumeInput(final NHttpServiceHandler handler) {
365 consumeInput(new NHttpServerEventHandlerAdaptor(handler));
366 }
367
368 public void produceOutput(final NHttpServiceHandler handler) {
369 produceOutput(new NHttpServerEventHandlerAdaptor(handler));
370 }
371
372 }