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