comparison src/org/eclipse/jetty/http/HttpGenerator.java @ 1066:bbbda7c6e8ec

fix use of HttpGenerator._header
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 09 Nov 2016 05:48:10 -0700
parents 158d1e6ac17f
children 56b515be91e1
comparison
equal deleted inserted replaced
1065:158d1e6ac17f 1066:bbbda7c6e8ec
148 if (_content != null && _content.remaining()>0) 148 if (_content != null && _content.remaining()>0)
149 { 149 {
150 if (_bufferChunked) 150 if (_bufferChunked)
151 { 151 {
152 JBuffer nc = _buffers.getBuffer(_content.remaining()+CHUNK_SPACE+content.remaining()); 152 JBuffer nc = _buffers.getBuffer(_content.remaining()+CHUNK_SPACE+content.remaining());
153 nc.put(_content); 153 nc.clear();
154 nc.put(HttpTokens.CRLF); 154 nc.putQ(_content);
155 nc.putQ(HttpTokens.CRLF);
155 BufferUtil.putHexInt(nc, content.remaining()); 156 BufferUtil.putHexInt(nc, content.remaining());
156 nc.put(HttpTokens.CRLF); 157 nc.putQ(HttpTokens.CRLF);
157 nc.put(content); 158 nc.putQ(content);
158 content=nc; 159 nc.flip();
160 content = nc;
159 } 161 }
160 else 162 else
161 { 163 {
162 JBuffer nc = _buffers.getBuffer(_content.remaining()+content.remaining()); 164 JBuffer nc = _buffers.getBuffer(_content.remaining()+content.remaining());
163 nc.put(_content); 165 nc.clear();
164 nc.put(content); 166 nc.putQ(_content);
165 content=nc; 167 nc.putQ(content);
168 nc.flip();
169 content = nc;
166 } 170 }
167 } 171 }
168 } 172 }
169 173
170 _content = content; 174 _content = content;
243 throw new IllegalArgumentException("!1xx"); 247 throw new IllegalArgumentException("!1xx");
244 Status status = __status[code]; 248 Status status = __status[code];
245 if (status==null) 249 if (status==null)
246 throw new IllegalArgumentException(code+"?"); 250 throw new IllegalArgumentException(code+"?");
247 251
248 // get a header buffer 252 _header.putQ(status._responseLine);
249 if (_header == null) 253 _header.putQ(HttpTokens.CRLF);
250 _header = _buffers.getHeader();
251
252 _header.put(status._responseLine);
253 _header.put(HttpTokens.CRLF);
254 254
255 try 255 try
256 { 256 {
257 // nasty semi busy flush! 257 // nasty semi busy flush!
258 _header.flip();
258 while(_header.remaining()>0) 259 while(_header.remaining()>0)
259 { 260 {
260 int len = _endp.flush(_header); 261 int len = _endp.flush(_header);
261 if (len<0) 262 if (len<0)
262 throw new EofException(); 263 throw new EofException();
282 283
283 if (_last && !allContentAdded) 284 if (_last && !allContentAdded)
284 throw new IllegalStateException("last?"); 285 throw new IllegalStateException("last?");
285 _last = _last | allContentAdded; 286 _last = _last | allContentAdded;
286 287
287 // get a header buffer
288 if (_header == null)
289 _header = _buffers.getHeader();
290
291 boolean has_server = false; 288 boolean has_server = false;
292 289
293 try 290 try
294 { 291 {
295 // Responses 292 // Responses
308 // add response line 305 // add response line
309 Status status = _status<__status.length?__status[_status]:null; 306 Status status = _status<__status.length?__status[_status]:null;
310 307
311 if (status==null) 308 if (status==null)
312 { 309 {
313 _header.put(HttpVersions.HTTP_1_1_BYTES); 310 _header.putQ(HttpVersions.HTTP_1_1_BYTES);
314 _header.put((byte) ' '); 311 _header.putQ((byte) ' ');
315 _header.put((byte) ('0' + _status / 100)); 312 _header.putQ((byte) ('0' + _status / 100));
316 _header.put((byte) ('0' + (_status % 100) / 10)); 313 _header.putQ((byte) ('0' + (_status % 100) / 10));
317 _header.put((byte) ('0' + (_status % 10))); 314 _header.putQ((byte) ('0' + (_status % 10)));
318 _header.put((byte) ' '); 315 _header.putQ((byte) ' ');
319 if (_reason==null) 316 if (_reason==null)
320 { 317 {
321 _header.put((byte) ('0' + _status / 100)); 318 _header.putQ((byte) ('0' + _status / 100));
322 _header.put((byte) ('0' + (_status % 100) / 10)); 319 _header.putQ((byte) ('0' + (_status % 100) / 10));
323 _header.put((byte) ('0' + (_status % 10))); 320 _header.putQ((byte) ('0' + (_status % 10)));
324 } 321 }
325 else 322 else
326 _header.put(_reason); 323 _header.putQ(_reason);
327 _header.put(HttpTokens.CRLF); 324 _header.putQ(HttpTokens.CRLF);
328 } 325 }
329 else 326 else
330 { 327 {
331 if (_reason==null) 328 if (_reason==null)
332 _header.put(status._responseLine); 329 _header.putQ(status._responseLine);
333 else 330 else
334 { 331 {
335 _header.put(status._schemeCode); 332 _header.putQ(status._schemeCode);
336 _header.put(_reason); 333 _header.putQ(_reason);
337 _header.put(HttpTokens.CRLF); 334 _header.putQ(HttpTokens.CRLF);
338 } 335 }
339 } 336 }
340 337
341 if (_status<200 && _status>=100 ) 338 if (_status<200 && _status>=100 )
342 { 339 {
346 _buffer.clearJ(); 343 _buffer.clearJ();
347 // end the header. 344 // end the header.
348 345
349 if (_status!=101 ) 346 if (_status!=101 )
350 { 347 {
351 _header.put(HttpTokens.CRLF); 348 _header.putQ(HttpTokens.CRLF);
352 _state = STATE_CONTENT; 349 _state = STATE_CONTENT;
353 return; 350 return;
354 } 351 }
355 } 352 }
356 else if (_status==204 || _status==304) 353 else if (_status==204 || _status==304)
530 // we have seen all the _content there is 527 // we have seen all the _content there is
531 _contentLength = _contentWritten; 528 _contentLength = _contentWritten;
532 if (content_length == null && !_noContent) 529 if (content_length == null && !_noContent)
533 { 530 {
534 // known length but not actually set. 531 // known length but not actually set.
535 _header.put(HttpHeaders.CONTENT_LENGTH_BYTES); 532 _header.putQ(HttpHeaders.CONTENT_LENGTH_BYTES);
536 _header.put(HttpTokens.COLON); 533 _header.putQ(HttpTokens.COLON);
537 _header.put((byte) ' '); 534 _header.putQ((byte) ' ');
538 BufferUtil.putDecLong(_header, _contentLength); 535 BufferUtil.putDecLong(_header, _contentLength);
539 _header.put(HttpTokens.CRLF); 536 _header.putQ(HttpTokens.CRLF);
540 } 537 }
541 } 538 }
542 else 539 else
543 { 540 {
544 // No idea, so we must assume that a body is coming 541 // No idea, so we must assume that a body is coming
546 } 543 }
547 break; 544 break;
548 545
549 case HttpTokens.NO_CONTENT: 546 case HttpTokens.NO_CONTENT:
550 if (content_length == null && _status >= 200 && _status != 204 && _status != 304) 547 if (content_length == null && _status >= 200 && _status != 204 && _status != 304)
551 _header.put(CONTENT_LENGTH_0); 548 _header.putQ(CONTENT_LENGTH_0);
552 break; 549 break;
553 550
554 case HttpTokens.EOF_CONTENT: 551 case HttpTokens.EOF_CONTENT:
555 _persistent = false; 552 _persistent = false;
556 break; 553 break;
574 transfer_encoding.putTo(_header); 571 transfer_encoding.putTo(_header);
575 else 572 else
576 throw new IllegalArgumentException("BAD TE"); 573 throw new IllegalArgumentException("BAD TE");
577 } 574 }
578 else 575 else
579 _header.put(TRANSFER_ENCODING_CHUNKED); 576 _header.putQ(TRANSFER_ENCODING_CHUNKED);
580 } 577 }
581 578
582 // Handle connection if need be 579 // Handle connection if need be
583 if (_contentLength==HttpTokens.EOF_CONTENT) 580 if (_contentLength==HttpTokens.EOF_CONTENT)
584 { 581 {
586 _persistent=false; 583 _persistent=false;
587 } 584 }
588 585
589 if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL)) 586 if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL))
590 { 587 {
591 _header.put(CONNECTION_CLOSE); 588 _header.putQ(CONNECTION_CLOSE);
592 if (connection!=null) 589 if (connection!=null)
593 { 590 {
594 _header.setPutIndex(_header.putIndex()-2); 591 _header.position(_header.position()-2);
595 _header.put((byte)','); 592 _header.putQ((byte)',');
596 _header.put(connection.toString().getBytes()); 593 _header.putQ(connection.toString().getBytes());
597 _header.put(CRLF); 594 _header.putQ(CRLF);
598 } 595 }
599 } 596 }
600 else if (keep_alive) 597 else if (keep_alive)
601 { 598 {
602 _header.put(CONNECTION_KEEP_ALIVE); 599 _header.putQ(CONNECTION_KEEP_ALIVE);
603 if (connection!=null) 600 if (connection!=null)
604 { 601 {
605 _header.setPutIndex(_header.putIndex()-2); 602 _header.position(_header.position()-2);
606 _header.put((byte)','); 603 _header.putQ((byte)',');
607 _header.put(connection.toString().getBytes()); 604 _header.putQ(connection.toString().getBytes());
608 _header.put(CRLF); 605 _header.putQ(CRLF);
609 } 606 }
610 } 607 }
611 else if (connection!=null) 608 else if (connection!=null)
612 { 609 {
613 _header.put(CONNECTION_); 610 _header.putQ(CONNECTION_);
614 _header.put(connection.toString().getBytes()); 611 _header.putQ(connection.toString().getBytes());
615 _header.put(CRLF); 612 _header.putQ(CRLF);
616 } 613 }
617 614
618 if (!has_server && _status>199) 615 if (!has_server && _status>199)
619 _header.put(SERVER); 616 _header.putQ(SERVER);
620 617
621 // end the header. 618 // end the header.
622 _header.put(HttpTokens.CRLF); 619 _header.putQ(HttpTokens.CRLF);
623 _state = STATE_CONTENT; 620 _state = STATE_CONTENT;
624 621
625 } 622 }
626 catch(ArrayIndexOutOfBoundsException e) 623 catch(ArrayIndexOutOfBoundsException e)
627 { 624 {
628 throw new RuntimeException("Header>"+_header.capacity(),e); 625 throw new RuntimeException("Header>"+_header.remaining(),e);
629 } 626 }
630 } 627 }
631 628
632 /* ------------------------------------------------------------ */ 629 /* ------------------------------------------------------------ */
633 /** 630 /**
671 do 668 do
672 { 669 {
673 last_flush = to_flush; 670 last_flush = to_flush;
674 switch (to_flush) 671 switch (to_flush)
675 { 672 {
673 //qqq
676 case 7: 674 case 7:
677 throw new IllegalStateException(); // should never happen! 675 throw new IllegalStateException(); // should never happen!
678 case 6: 676 case 6:
677 _header.flip();
679 len = _endp.flush(_header, _buffer, null); 678 len = _endp.flush(_header, _buffer, null);
679 _header.compact();
680 break; 680 break;
681 case 5: 681 case 5:
682 _header.flip();
682 len = _endp.flush(_header, _content, null); 683 len = _endp.flush(_header, _content, null);
684 _header.compact();
683 break; 685 break;
684 case 4: 686 case 4:
687 _header.flip();
685 len = _endp.flush(_header); 688 len = _endp.flush(_header);
689 _header.compact();
686 break; 690 break;
687 case 3: 691 case 3:
688 len = _endp.flush(_buffer, _content, null); 692 len = _endp.flush(_buffer, _content, null);
689 break; 693 break;
690 case 2: 694 case 2:
695 break; 699 break;
696 case 0: 700 case 0:
697 { 701 {
698 len=0; 702 len=0;
699 // Nothing more we can write now. 703 // Nothing more we can write now.
700 if (_header != null) 704 _header.clear();
701 _header.clearJ();
702 705
703 _bypass = false; 706 _bypass = false;
704 _bufferChunked = false; 707 _bufferChunked = false;
705 708
706 if (_buffer != null) 709 if (_buffer != null)
752 } 755 }
753 } 756 }
754 757
755 private int flushMask() 758 private int flushMask()
756 { 759 {
757 return ((_header != null && _header.remaining() > 0)?4:0) 760 return ((_header.position() > 0)?4:0)
758 | ((_buffer != null && _buffer.remaining() > 0)?2:0) 761 | ((_buffer != null && _buffer.remaining() > 0)?2:0)
759 | ((_bypass && _content != null && _content.remaining() > 0)?1:0); 762 | ((_bypass && _content != null && _content.remaining() > 0)?1:0);
760 } 763 }
761 764
762 private void prepareBuffers() 765 private void prepareBuffers()
780 { 783 {
781 // this is a bypass write 784 // this is a bypass write
782 int size = _content.remaining(); 785 int size = _content.remaining();
783 _bufferChunked = true; 786 _bufferChunked = true;
784 787
785 if (_header == null)
786 _header = _buffers.getHeader();
787
788 // if we need CRLF add this to header 788 // if we need CRLF add this to header
789 if (_needCRLF) 789 if (_needCRLF)
790 { 790 {
791 if (_header.remaining() > 0) throw new IllegalStateException("EOC"); 791 if (_header.position() > 0) throw new IllegalStateException("EOC");
792 _header.put(HttpTokens.CRLF); 792 _header.putQ(HttpTokens.CRLF);
793 _needCRLF = false; 793 _needCRLF = false;
794 } 794 }
795 // Add the chunk size to the header 795 // Add the chunk size to the header
796 BufferUtil.putHexInt(_header, size); 796 BufferUtil.putHexInt(_header, size);
797 _header.put(HttpTokens.CRLF); 797 _header.putQ(HttpTokens.CRLF);
798 798
799 // Need a CRLF after the content 799 // Need a CRLF after the content
800 _needCRLF = true; 800 _needCRLF = true;
801 } 801 }
802 else if (_buffer!=null) 802 else if (_buffer!=null)
805 if (size > 0) 805 if (size > 0)
806 { 806 {
807 // Prepare a chunk! 807 // Prepare a chunk!
808 _bufferChunked = true; 808 _bufferChunked = true;
809 809
810 if (_header == null)
811 _header = _buffers.getHeader();
812
813 if (_needCRLF) 810 if (_needCRLF)
814 { 811 {
815 if (_header.remaining() > 0) throw new IllegalStateException("EOC"); 812 if (_header.position() > 0) throw new IllegalStateException("EOC");
816 _header.put(HttpTokens.CRLF); 813 _header.putQ(HttpTokens.CRLF);
817 _needCRLF = false; 814 _needCRLF = false;
818 } 815 }
819 BufferUtil.putHexInt(_header, size); 816 BufferUtil.putHexInt(_header, size);
820 _header.put(HttpTokens.CRLF); 817 _header.putQ(HttpTokens.CRLF);
821 818
822 // Add end chunk trailer. 819 // Add end chunk trailer.
823 if (_buffer.space() >= 2) 820 if (_buffer.space() >= 2)
824 _buffer.put(HttpTokens.CRLF); 821 _buffer.put(HttpTokens.CRLF);
825 else 822 else
828 } 825 }
829 826
830 // If we need EOC and everything written 827 // If we need EOC and everything written
831 if (_needEOC && (_content == null || _content.remaining() == 0)) 828 if (_needEOC && (_content == null || _content.remaining() == 0))
832 { 829 {
833 if (_header == null && _buffer == null)
834 _header = _buffers.getHeader();
835
836 if (_needCRLF) 830 if (_needCRLF)
837 { 831 {
838 if (_buffer == null && _header != null && _header.space() >= HttpTokens.CRLF.length) 832 if (_buffer == null && _header.remaining() >= HttpTokens.CRLF.length)
839 { 833 {
840 _header.put(HttpTokens.CRLF); 834 _header.putQ(HttpTokens.CRLF);
841 _needCRLF = false; 835 _needCRLF = false;
842 } 836 }
843 else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length) 837 else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length)
844 { 838 {
845 _buffer.put(HttpTokens.CRLF); 839 _buffer.put(HttpTokens.CRLF);
847 } 841 }
848 } 842 }
849 843
850 if (!_needCRLF && _needEOC) 844 if (!_needCRLF && _needEOC)
851 { 845 {
852 if (_buffer == null && _header != null && _header.space() >= LAST_CHUNK.length) 846 if (_buffer == null && _header.remaining() >= LAST_CHUNK.length)
853 { 847 {
854 if (!_head) 848 if (!_head)
855 { 849 {
856 _header.put(LAST_CHUNK); 850 _header.putQ(LAST_CHUNK);
857 _bufferChunked=true; 851 _bufferChunked=true;
858 } 852 }
859 _needEOC = false; 853 _needEOC = false;
860 } 854 }
861 else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length) 855 else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length)
878 } 872 }
879 873
880 @Override 874 @Override
881 public String toString() 875 public String toString()
882 { 876 {
883 JBuffer header=_header; 877 JBuffer header = _header;
884 JBuffer buffer=_buffer; 878 JBuffer buffer=_buffer;
885 JBuffer content=_content; 879 JBuffer content=_content;
886 return String.format("%s{s=%d,h=%d,b=%d,c=%d}", 880 return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
887 getClass().getSimpleName(), 881 getClass().getSimpleName(),
888 _state, 882 _state,
889 header == null ? -1 : header.remaining(), 883 header == null ? -1 : header.position(),
890 buffer == null ? -1 : buffer.remaining(), 884 buffer == null ? -1 : buffer.remaining(),
891 content == null ? -1 : content.remaining()); 885 content == null ? -1 : content.remaining());
892 } 886 }
893 887
894 888
929 private boolean _last = false; 923 private boolean _last = false;
930 private boolean _head = false; 924 private boolean _head = false;
931 private boolean _noContent = false; 925 private boolean _noContent = false;
932 private Boolean _persistent = null; 926 private Boolean _persistent = null;
933 927
934 private JBuffer _header; // JBuffer for HTTP header (and maybe small _content) 928 private final JBuffer _header; // JBuffer for HTTP header (and maybe small _content)
935 private JBuffer _buffer; // JBuffer for copy of passed _content 929 private JBuffer _buffer; // JBuffer for copy of passed _content
936 private JBuffer _content; // JBuffer passed to addContent 930 private JBuffer _content; // JBuffer passed to addContent
937 931
938 932
939 public HttpGenerator(Buffers buffers, EndPoint io) 933 public HttpGenerator(Buffers buffers, EndPoint io)
940 { 934 {
941 this._buffers = buffers; 935 this._buffers = buffers;
942 this._endp = io; 936 this._endp = io;
937 _header = _buffers.getHeader();
938 _header.clear();
943 } 939 }
944 940
945 public final boolean isOpen() 941 public final boolean isOpen()
946 { 942 {
947 return _endp.isOpen(); 943 return _endp.isOpen();