1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.PrintWriter;
19 import javax.servlet.ServletInputStream;
20 import javax.servlet.ServletOutputStream;
21 import javax.servlet.http.HttpServletResponse;
22
23 import org.eclipse.jetty.continuation.ContinuationThrowable;
24 import org.eclipse.jetty.http.AbstractGenerator;
25 import org.eclipse.jetty.http.EncodedHttpURI;
26 import org.eclipse.jetty.http.Generator;
27 import org.eclipse.jetty.http.HttpBuffers;
28 import org.eclipse.jetty.http.HttpContent;
29 import org.eclipse.jetty.http.HttpException;
30 import org.eclipse.jetty.http.HttpFields;
31 import org.eclipse.jetty.http.HttpGenerator;
32 import org.eclipse.jetty.http.HttpHeaderValues;
33 import org.eclipse.jetty.http.HttpHeaders;
34 import org.eclipse.jetty.http.HttpMethods;
35 import org.eclipse.jetty.http.HttpParser;
36 import org.eclipse.jetty.http.HttpStatus;
37 import org.eclipse.jetty.http.HttpURI;
38 import org.eclipse.jetty.http.HttpVersions;
39 import org.eclipse.jetty.http.MimeTypes;
40 import org.eclipse.jetty.http.Parser;
41 import org.eclipse.jetty.io.AsyncEndPoint;
42 import org.eclipse.jetty.io.Buffer;
43 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
44 import org.eclipse.jetty.io.Connection;
45 import org.eclipse.jetty.io.EndPoint;
46 import org.eclipse.jetty.io.EofException;
47 import org.eclipse.jetty.io.RuntimeIOException;
48 import org.eclipse.jetty.io.UncheckedPrintWriter;
49 import org.eclipse.jetty.server.nio.NIOConnector;
50 import org.eclipse.jetty.server.ssl.SslConnector;
51 import org.eclipse.jetty.util.QuotedStringTokenizer;
52 import org.eclipse.jetty.util.StringUtil;
53 import org.eclipse.jetty.util.URIUtil;
54 import org.eclipse.jetty.util.log.Log;
55 import org.eclipse.jetty.util.resource.Resource;
56 import org.eclipse.jetty.util.thread.Timeout;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 public class HttpConnection implements Connection
90 {
91 private static final int UNKNOWN = -2;
92 private static final ThreadLocal<HttpConnection> __currentConnection = new ThreadLocal<HttpConnection>();
93
94 private final long _timeStamp=System.currentTimeMillis();
95 private int _requests;
96 private volatile boolean _handling;
97
98 protected final Connector _connector;
99 protected final EndPoint _endp;
100 protected final Server _server;
101 protected final HttpURI _uri;
102
103 protected final Parser _parser;
104 protected final HttpFields _requestFields;
105 protected final Request _request;
106 protected ServletInputStream _in;
107
108 protected final Generator _generator;
109 protected final HttpFields _responseFields;
110 protected final Response _response;
111 protected Output _out;
112 protected OutputWriter _writer;
113 protected PrintWriter _printWriter;
114
115 int _include;
116
117 private Object _associatedObject;
118
119 private int _version = UNKNOWN;
120
121 private boolean _expect = false;
122 private boolean _expect100Continue = false;
123 private boolean _expect102Processing = false;
124 private boolean _head = false;
125 private boolean _host = false;
126 private boolean _delayedHandling=false;
127
128
129 public static HttpConnection getCurrentConnection()
130 {
131 return __currentConnection.get();
132 }
133
134
135 protected static void setCurrentConnection(HttpConnection connection)
136 {
137 __currentConnection.set(connection);
138 }
139
140
141
142
143
144 public HttpConnection(Connector connector, EndPoint endpoint, Server server)
145 {
146 _uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
147 _connector = connector;
148 _endp = endpoint;
149 HttpBuffers ab = (HttpBuffers)_connector;
150 _parser = new HttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler());
151 _requestFields = new HttpFields();
152 _responseFields = new HttpFields(server.getMaxCookieVersion());
153 _request = new Request(this);
154 _response = new Response(this);
155 _generator = new HttpGenerator(ab.getResponseBuffers(), _endp);
156 _generator.setSendServerVersion(server.getSendServerVersion());
157 _server = server;
158 }
159
160
161 protected HttpConnection(Connector connector, EndPoint endpoint, Server server,
162 Parser parser, Generator generator, Request request)
163 {
164 _uri = URIUtil.__CHARSET.equals(StringUtil.__UTF8)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
165 _connector = connector;
166 _endp = endpoint;
167 _parser = parser;
168 _requestFields = new HttpFields();
169 _responseFields = new HttpFields(server.getMaxCookieVersion());
170 _request = request;
171 _response = new Response(this);
172 _generator = generator;
173 _generator.setSendServerVersion(server.getSendServerVersion());
174 _server = server;
175 }
176
177
178
179
180
181 public Parser getParser()
182 {
183 return _parser;
184 }
185
186
187
188
189
190 public int getRequests()
191 {
192 return _requests;
193 }
194
195
196 public Server getServer()
197 {
198 return _server;
199 }
200
201
202
203
204
205 public long getTimeStamp()
206 {
207 return _timeStamp;
208 }
209
210
211
212
213
214 public Object getAssociatedObject()
215 {
216 return _associatedObject;
217 }
218
219
220
221
222
223 public void setAssociatedObject(Object associatedObject)
224 {
225 _associatedObject = associatedObject;
226 }
227
228
229
230
231
232 public Connector getConnector()
233 {
234 return _connector;
235 }
236
237
238
239
240
241 public HttpFields getRequestFields()
242 {
243 return _requestFields;
244 }
245
246
247
248
249
250 public HttpFields getResponseFields()
251 {
252 return _responseFields;
253 }
254
255
256
257
258
259
260 public boolean isConfidential(Request request)
261 {
262 if (_connector!=null)
263 return _connector.isConfidential(request);
264 return false;
265 }
266
267
268
269
270
271
272
273
274 public boolean isIntegral(Request request)
275 {
276 if (_connector!=null)
277 return _connector.isIntegral(request);
278 return false;
279 }
280
281
282
283
284
285 public EndPoint getEndPoint()
286 {
287 return _endp;
288 }
289
290
291
292
293
294 public boolean getResolveNames()
295 {
296 return _connector.getResolveNames();
297 }
298
299
300
301
302
303 public Request getRequest()
304 {
305 return _request;
306 }
307
308
309
310
311
312 public Response getResponse()
313 {
314 return _response;
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328 public ServletInputStream getInputStream() throws IOException
329 {
330
331 if (_expect100Continue)
332 {
333
334 if (((HttpParser)_parser).getHeaderBuffer()==null || ((HttpParser)_parser).getHeaderBuffer().length()<2)
335 {
336 if (_generator.isCommitted())
337 throw new IllegalStateException("Committed before 100 Continues");
338
339 ((HttpGenerator)_generator).send1xx(HttpStatus.CONTINUE_100);
340 }
341 _expect100Continue=false;
342 }
343
344 if (_in == null)
345 _in = new HttpInput(((HttpParser)_parser),_connector.getMaxIdleTime());
346 return _in;
347 }
348
349
350
351
352
353 public ServletOutputStream getOutputStream()
354 {
355 if (_out == null)
356 _out = new Output();
357 return _out;
358 }
359
360
361
362
363
364
365 public PrintWriter getPrintWriter(String encoding)
366 {
367 getOutputStream();
368 if (_writer==null)
369 {
370 _writer=new OutputWriter();
371 _printWriter=new UncheckedPrintWriter(_writer);
372 }
373 _writer.setCharacterEncoding(encoding);
374 return _printWriter;
375 }
376
377
378 public boolean isResponseCommitted()
379 {
380 return _generator.isCommitted();
381 }
382
383
384 public Connection handle() throws IOException
385 {
386 Connection connection = this;
387
388
389 boolean more_in_buffer =true;
390 boolean progress=true;
391
392 try
393 {
394 assert getCurrentConnection()==null;
395 assert _handling==false;
396 _handling=true;
397 setCurrentConnection(this);
398
399 while (more_in_buffer && _endp.isOpen())
400 {
401 try
402 {
403 if (_request._async.isAsync())
404 {
405
406
407
408 Log.debug("async request",_request);
409 if (!_request._async.isComplete())
410 handleRequest();
411 else if (!_parser.isComplete())
412 {
413 long parsed=_parser.parseAvailable();
414 progress|=parsed>0;
415 }
416
417 if (_generator.isCommitted() && !_generator.isComplete())
418 progress|=_generator.flushBuffer()>0;
419 if (_endp.isBufferingOutput())
420 _endp.flush();
421 }
422 else
423 {
424
425 if (!_parser.isComplete())
426 progress|=_parser.parseAvailable()>0;
427
428
429
430
431
432 while (_generator.isCommitted() && !_generator.isComplete())
433 {
434 long written=_generator.flushBuffer();
435 if (written<=0)
436 break;
437 progress=true;
438 if (_endp.isBufferingOutput())
439 _endp.flush();
440 }
441
442
443 if (_endp.isBufferingOutput())
444 {
445 _endp.flush();
446 if (!_endp.isBufferingOutput())
447 progress=true;
448 }
449
450 if (!progress)
451 return this;
452 }
453 progress=false;
454 }
455 catch (HttpException e)
456 {
457 if (Log.isDebugEnabled())
458 {
459 Log.debug("uri="+_uri);
460 Log.debug("fields="+_requestFields);
461 Log.debug(e);
462 }
463 _generator.sendError(e.getStatus(), e.getReason(), null, true);
464
465 _parser.reset(true);
466 _endp.close();
467 }
468 finally
469 {
470 more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
471
472
473 if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput())
474 {
475
476 Connection switched=(_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
477 ?(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection"):null;
478
479
480 if (switched!=null)
481 {
482 _parser.reset(true);
483 _generator.reset(true);
484 connection=switched;
485 }
486 else
487 {
488
489 if (!_generator.isPersistent())
490 {
491 _parser.reset(true);
492 more_in_buffer=false;
493 _endp.close();
494 }
495
496 if (more_in_buffer)
497 {
498 reset(false);
499 more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
500 }
501 else
502 reset(true);
503 progress=true;
504 }
505 }
506
507 if (_request.isAsyncStarted())
508 {
509 Log.debug("return with suspended request");
510 more_in_buffer=false;
511 }
512 else if (_generator.isCommitted() && !_generator.isComplete() && _endp instanceof AsyncEndPoint)
513 ((AsyncEndPoint)_endp).setWritable(false);
514 }
515 }
516 }
517 finally
518 {
519 setCurrentConnection(null);
520 _handling=false;
521 }
522 return connection;
523 }
524
525
526 public void scheduleTimeout(Timeout.Task task, long timeoutMs)
527 {
528 throw new UnsupportedOperationException();
529 }
530
531
532 public void cancelTimeout(Timeout.Task task)
533 {
534 throw new UnsupportedOperationException();
535 }
536
537
538 public void reset(boolean returnBuffers)
539 {
540 _parser.reset(returnBuffers);
541 _requestFields.clear();
542 _request.recycle();
543
544 _generator.reset(returnBuffers);
545 _responseFields.clear();
546 _response.recycle();
547
548 _uri.clear();
549 }
550
551
552 protected void handleRequest() throws IOException
553 {
554 boolean error = false;
555
556 String threadName=null;
557 try
558 {
559 if (Log.isDebugEnabled())
560 {
561 threadName=Thread.currentThread().getName();
562 Thread.currentThread().setName(threadName+" - "+_uri);
563 }
564
565
566
567
568
569
570
571
572
573
574 final Server server=_server;
575 boolean handling=_request._async.handling() && server!=null && server.isRunning();
576 while (handling)
577 {
578 _request.setHandled(false);
579
580 String info=null;
581 try
582 {
583 _uri.getPort();
584 info=URIUtil.canonicalPath(_uri.getDecodedPath());
585 if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT))
586 throw new HttpException(400);
587 _request.setPathInfo(info);
588
589 if (_out!=null)
590 _out.reopen();
591
592 if (_request._async.isInitial())
593 {
594 _request.setDispatcherType(DispatcherType.REQUEST);
595 _connector.customize(_endp, _request);
596 server.handle(this);
597 }
598 else
599 {
600 _request.setDispatcherType(DispatcherType.ASYNC);
601 server.handleAsync(this);
602 }
603 }
604 catch (ContinuationThrowable e)
605 {
606 Log.ignore(e);
607 }
608 catch (EofException e)
609 {
610 Log.debug(e);
611 _request.setHandled(true);
612 error=true;
613 }
614 catch (RuntimeIOException e)
615 {
616 Log.debug(e);
617 _request.setHandled(true);
618 error=true;
619 }
620 catch (HttpException e)
621 {
622 Log.debug(e);
623 _request.setHandled(true);
624 _response.sendError(e.getStatus(), e.getReason());
625 error=true;
626 }
627 catch (Throwable e)
628 {
629 if (e instanceof ThreadDeath)
630 throw (ThreadDeath)e;
631
632 error=true;
633 Log.warn(_uri+": "+e);
634 Log.debug(e);
635 _request.setHandled(true);
636 _generator.sendError(info==null?400:500, null, null, true);
637 }
638 finally
639 {
640 handling = !_request._async.unhandle() && server.isRunning() && _server!=null;
641 }
642 }
643 }
644 finally
645 {
646 if (threadName!=null)
647 Thread.currentThread().setName(threadName);
648
649 if (_request._async.isUncompleted())
650 {
651 _request._async.doComplete();
652
653 if (_expect100Continue)
654 {
655 Log.debug("100 continues not sent");
656
657
658
659
660 _expect100Continue = false;
661
662 if (!_response.isCommitted())
663 _generator.setPersistent(false);
664 }
665
666 if(_endp.isOpen())
667 {
668 if (error)
669 _endp.close();
670 else
671 {
672 if (!_response.isCommitted() && !_request.isHandled())
673 _response.sendError(HttpServletResponse.SC_NOT_FOUND);
674 _response.complete();
675 if (_generator.isPersistent())
676 _connector.persist(_endp);
677 }
678 }
679 else
680 {
681 _response.complete();
682 }
683
684 _request.setHandled(true);
685 }
686 }
687 }
688
689
690 public void commitResponse(boolean last) throws IOException
691 {
692 if (!_generator.isCommitted())
693 {
694 _generator.setResponse(_response.getStatus(), _response.getReason());
695 try
696 {
697
698
699 if (_expect100Continue && _response.getStatus()!=100)
700 _generator.setPersistent(false);
701 _generator.completeHeader(_responseFields, last);
702 }
703 catch(IOException io)
704 {
705 throw io;
706 }
707 catch(RuntimeException e)
708 {
709 Log.warn("header full: "+e);
710
711 _response.reset();
712 _generator.reset(true);
713 _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
714 _generator.completeHeader(_responseFields,Generator.LAST);
715 _generator.complete();
716 throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
717 }
718
719 }
720 if (last)
721 _generator.complete();
722 }
723
724
725 public void completeResponse() throws IOException
726 {
727 if (!_generator.isCommitted())
728 {
729 _generator.setResponse(_response.getStatus(), _response.getReason());
730 try
731 {
732 _generator.completeHeader(_responseFields, Generator.LAST);
733 }
734 catch(IOException io)
735 {
736 throw io;
737 }
738 catch(RuntimeException e)
739 {
740 Log.warn("header full: "+e);
741 Log.debug(e);
742
743 _response.reset();
744 _generator.reset(true);
745 _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500,null);
746 _generator.completeHeader(_responseFields,Generator.LAST);
747 _generator.complete();
748 throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
749 }
750 }
751
752 _generator.complete();
753 }
754
755
756 public void flushResponse() throws IOException
757 {
758 try
759 {
760 commitResponse(Generator.MORE);
761 _generator.flushBuffer();
762 }
763 catch(IOException e)
764 {
765 throw (e instanceof EofException) ? e:new EofException(e);
766 }
767 }
768
769
770 public Generator getGenerator()
771 {
772 return _generator;
773 }
774
775
776 public boolean isIncluding()
777 {
778 return _include>0;
779 }
780
781
782 public void include()
783 {
784 _include++;
785 }
786
787
788 public void included()
789 {
790 _include--;
791 if (_out!=null)
792 _out.reopen();
793 }
794
795
796 public boolean isIdle()
797 {
798 return _generator.isIdle() && (_parser.isIdle() || _delayedHandling);
799 }
800
801
802
803
804
805 public boolean isSuspended()
806 {
807 return _request.getAsyncContinuation().isSuspended();
808 }
809
810
811 public void closed()
812 {
813 }
814
815
816 public boolean isExpecting100Continues()
817 {
818 return _expect100Continue;
819 }
820
821
822 public boolean isExpecting102Processing()
823 {
824 return _expect102Processing;
825 }
826
827
828
829
830 private class RequestHandler extends HttpParser.EventHandler
831 {
832 private String _charset;
833
834
835
836
837
838
839 @Override
840 public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
841 {
842 _host = false;
843 _expect = false;
844 _expect100Continue=false;
845 _expect102Processing=false;
846 _delayedHandling=false;
847 _charset=null;
848
849 if(_request.getTimeStamp()==0)
850 _request.setTimeStamp(System.currentTimeMillis());
851 _request.setMethod(method.toString());
852
853 try
854 {
855 _head=false;
856 switch (HttpMethods.CACHE.getOrdinal(method))
857 {
858 case HttpMethods.CONNECT_ORDINAL:
859 _uri.parseConnect(uri.array(), uri.getIndex(), uri.length());
860 break;
861
862 case HttpMethods.HEAD_ORDINAL:
863 _head=true;
864
865
866 default:
867 _uri.parse(uri.array(), uri.getIndex(), uri.length());
868 }
869
870 _request.setUri(_uri);
871
872 if (version==null)
873 {
874 _request.setProtocol(HttpVersions.HTTP_0_9);
875 _version=HttpVersions.HTTP_0_9_ORDINAL;
876 }
877 else
878 {
879 version= HttpVersions.CACHE.get(version);
880 _version = HttpVersions.CACHE.getOrdinal(version);
881 if (_version <= 0) _version = HttpVersions.HTTP_1_0_ORDINAL;
882 _request.setProtocol(version.toString());
883 }
884 }
885 catch (Exception e)
886 {
887 Log.debug(e);
888 throw new HttpException(HttpStatus.BAD_REQUEST_400,null,e);
889 }
890 }
891
892
893
894
895 @Override
896 public void parsedHeader(Buffer name, Buffer value)
897 {
898 int ho = HttpHeaders.CACHE.getOrdinal(name);
899 switch (ho)
900 {
901 case HttpHeaders.HOST_ORDINAL:
902
903 _host = true;
904 break;
905
906 case HttpHeaders.EXPECT_ORDINAL:
907 value = HttpHeaderValues.CACHE.lookup(value);
908 switch(HttpHeaderValues.CACHE.getOrdinal(value))
909 {
910 case HttpHeaderValues.CONTINUE_ORDINAL:
911 _expect100Continue=_generator instanceof HttpGenerator;
912 break;
913
914 case HttpHeaderValues.PROCESSING_ORDINAL:
915 _expect102Processing=_generator instanceof HttpGenerator;
916 break;
917
918 default:
919 String[] values = value.toString().split(",");
920 for (int i=0;values!=null && i<values.length;i++)
921 {
922 CachedBuffer cb=HttpHeaderValues.CACHE.get(values[i].trim());
923 if (cb==null)
924 _expect=true;
925 else
926 {
927 switch(cb.getOrdinal())
928 {
929 case HttpHeaderValues.CONTINUE_ORDINAL:
930 _expect100Continue=_generator instanceof HttpGenerator;
931 break;
932 case HttpHeaderValues.PROCESSING_ORDINAL:
933 _expect102Processing=_generator instanceof HttpGenerator;
934 break;
935 default:
936 _expect=true;
937 }
938 }
939 }
940 }
941 break;
942
943 case HttpHeaders.ACCEPT_ENCODING_ORDINAL:
944 case HttpHeaders.USER_AGENT_ORDINAL:
945 value = HttpHeaderValues.CACHE.lookup(value);
946 break;
947
948 case HttpHeaders.CONTENT_TYPE_ORDINAL:
949 value = MimeTypes.CACHE.lookup(value);
950 _charset=MimeTypes.getCharsetFromContentType(value);
951 break;
952
953 case HttpHeaders.CONNECTION_ORDINAL:
954
955 switch(HttpHeaderValues.CACHE.getOrdinal(value))
956 {
957 case -1:
958 {
959 String[] values = value.toString().split(",");
960 for (int i=0;values!=null && i<values.length;i++)
961 {
962 CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
963
964 if (cb!=null)
965 {
966 switch(cb.getOrdinal())
967 {
968 case HttpHeaderValues.CLOSE_ORDINAL:
969 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
970 _generator.setPersistent(false);
971 break;
972
973 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
974 if (_version==HttpVersions.HTTP_1_0_ORDINAL)
975 _responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
976 break;
977 }
978 }
979 }
980 break;
981 }
982 case HttpHeaderValues.CLOSE_ORDINAL:
983 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
984 _generator.setPersistent(false);
985 break;
986
987 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
988 if (_version==HttpVersions.HTTP_1_0_ORDINAL)
989 _responseFields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE_BUFFER);
990 break;
991 }
992 }
993
994 _requestFields.add(name, value);
995 }
996
997
998
999
1000 @Override
1001 public void headerComplete() throws IOException
1002 {
1003 if (_endp instanceof AsyncEndPoint)
1004 ((AsyncEndPoint)_endp).scheduleIdle();
1005 _requests++;
1006 _generator.setVersion(_version);
1007 switch (_version)
1008 {
1009 case HttpVersions.HTTP_0_9_ORDINAL:
1010 break;
1011 case HttpVersions.HTTP_1_0_ORDINAL:
1012 _generator.setHead(_head);
1013
1014 if (_server.getSendDateHeader())
1015 _generator.setDate(_request.getTimeStampBuffer());
1016
1017 break;
1018 case HttpVersions.HTTP_1_1_ORDINAL:
1019 _generator.setHead(_head);
1020
1021 if (_server.getSendDateHeader())
1022 _generator.setDate(_request.getTimeStampBuffer());
1023
1024 if (!_host)
1025 {
1026 _generator.setResponse(HttpStatus.BAD_REQUEST_400, null);
1027 _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
1028 _generator.completeHeader(_responseFields, true);
1029 _generator.complete();
1030 return;
1031 }
1032
1033 if (_expect)
1034 {
1035 _generator.setResponse(HttpStatus.EXPECTATION_FAILED_417, null);
1036 _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
1037 _generator.completeHeader(_responseFields, true);
1038 _generator.complete();
1039 return;
1040 }
1041
1042 break;
1043 default:
1044 }
1045
1046 if(_charset!=null)
1047 _request.setCharacterEncodingUnchecked(_charset);
1048
1049
1050 if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect100Continue)
1051 handleRequest();
1052 else
1053 _delayedHandling=true;
1054 }
1055
1056
1057
1058
1059
1060 @Override
1061 public void content(Buffer ref) throws IOException
1062 {
1063 if (_endp instanceof AsyncEndPoint)
1064 ((AsyncEndPoint)_endp).scheduleIdle();
1065 if (_delayedHandling)
1066 {
1067 _delayedHandling=false;
1068 handleRequest();
1069 }
1070 }
1071
1072
1073
1074
1075
1076
1077
1078 @Override
1079 public void messageComplete(long contentLength) throws IOException
1080 {
1081 if (_delayedHandling)
1082 {
1083 _delayedHandling=false;
1084 handleRequest();
1085 }
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095 @Override
1096 public void startResponse(Buffer version, int status, Buffer reason)
1097 {
1098 Log.debug("Bad request!: "+version+" "+status+" "+reason);
1099 }
1100 }
1101
1102
1103
1104
1105
1106 public class Output extends HttpOutput
1107 {
1108 Output()
1109 {
1110 super((AbstractGenerator)HttpConnection.this._generator,
1111 _connector.isLowResources()?_connector.getLowResourceMaxIdleTime():_connector.getMaxIdleTime());
1112 }
1113
1114
1115
1116
1117
1118 @Override
1119 public void close() throws IOException
1120 {
1121 if (isClosed())
1122 return;
1123
1124 if (!isIncluding() && !super._generator.isCommitted())
1125 commitResponse(Generator.LAST);
1126 else
1127 flushResponse();
1128
1129 super.close();
1130 }
1131
1132
1133
1134
1135
1136
1137 @Override
1138 public void flush() throws IOException
1139 {
1140 if (!super._generator.isCommitted())
1141 commitResponse(Generator.MORE);
1142 super.flush();
1143 }
1144
1145
1146
1147
1148
1149 @Override
1150 public void print(String s) throws IOException
1151 {
1152 if (isClosed())
1153 throw new IOException("Closed");
1154 PrintWriter writer=getPrintWriter(null);
1155 writer.print(s);
1156 }
1157
1158
1159 public void sendResponse(Buffer response) throws IOException
1160 {
1161 ((HttpGenerator)super._generator).sendResponse(response);
1162 }
1163
1164
1165 public void sendContent(Object content) throws IOException
1166 {
1167 Resource resource=null;
1168
1169 if (isClosed())
1170 throw new IOException("Closed");
1171
1172 if (super._generator.isWritten())
1173 throw new IllegalStateException("!empty");
1174
1175
1176 if (content instanceof HttpContent)
1177 {
1178 HttpContent httpContent = (HttpContent) content;
1179 Buffer contentType = httpContent.getContentType();
1180 if (contentType != null && !_responseFields.containsKey(HttpHeaders.CONTENT_TYPE_BUFFER))
1181 {
1182 String enc = _response.getSetCharacterEncoding();
1183 if(enc==null)
1184 _responseFields.add(HttpHeaders.CONTENT_TYPE_BUFFER, contentType);
1185 else
1186 {
1187 if(contentType instanceof CachedBuffer)
1188 {
1189 CachedBuffer content_type = ((CachedBuffer)contentType).getAssociate(enc);
1190 if(content_type!=null)
1191 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER, content_type);
1192 else
1193 {
1194 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1195 contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(enc,";= "));
1196 }
1197 }
1198 else
1199 {
1200 _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
1201 contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(enc,";= "));
1202 }
1203 }
1204 }
1205 if (httpContent.getContentLength() > 0)
1206 _responseFields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER, httpContent.getContentLength());
1207 Buffer lm = httpContent.getLastModified();
1208 long lml=httpContent.getResource().lastModified();
1209 if (lm != null)
1210 _responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER, lm,lml);
1211 else if (httpContent.getResource()!=null)
1212 {
1213 if (lml!=-1)
1214 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, lml);
1215 }
1216
1217 boolean direct=_connector instanceof NIOConnector && ((NIOConnector)_connector).getUseDirectBuffers() && !(_connector instanceof SslConnector);
1218 content = direct?httpContent.getDirectBuffer():httpContent.getIndirectBuffer();
1219 if (content==null)
1220 content=httpContent.getInputStream();
1221 }
1222 else if (content instanceof Resource)
1223 {
1224 resource=(Resource)content;
1225 _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, resource.lastModified());
1226 content=resource.getInputStream();
1227 }
1228
1229
1230 if (content instanceof Buffer)
1231 {
1232 super._generator.addContent((Buffer) content, Generator.LAST);
1233 commitResponse(Generator.LAST);
1234 }
1235 else if (content instanceof InputStream)
1236 {
1237 InputStream in = (InputStream)content;
1238
1239 try
1240 {
1241 int max = super._generator.prepareUncheckedAddContent();
1242 Buffer buffer = super._generator.getUncheckedBuffer();
1243
1244 int len=buffer.readFrom(in,max);
1245
1246 while (len>=0)
1247 {
1248 super._generator.completeUncheckedAddContent();
1249 _out.flush();
1250
1251 max = super._generator.prepareUncheckedAddContent();
1252 buffer = super._generator.getUncheckedBuffer();
1253 len=buffer.readFrom(in,max);
1254 }
1255 super._generator.completeUncheckedAddContent();
1256 _out.flush();
1257 }
1258 finally
1259 {
1260 if (resource!=null)
1261 resource.release();
1262 else
1263 in.close();
1264
1265 }
1266 }
1267 else
1268 throw new IllegalArgumentException("unknown content type?");
1269
1270
1271 }
1272 }
1273
1274
1275
1276
1277 public class OutputWriter extends HttpWriter
1278 {
1279 OutputWriter()
1280 {
1281 super(HttpConnection.this._out);
1282 }
1283 }
1284
1285 }