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