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