Mercurial Hosting > luan
comparison src/org/eclipse/jetty/http/HttpParser.java @ 980:bd26bd9320e2
simplify HttpParser
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 16 Oct 2016 21:01:26 -0600 |
parents | c8cd3e96db5f |
children | 39154cfa58e4 |
comparison
equal
deleted
inserted
replaced
979:c8cd3e96db5f | 980:bd26bd9320e2 |
---|---|
35 public final class HttpParser | 35 public final class HttpParser |
36 { | 36 { |
37 private static final Logger LOG = LoggerFactory.getLogger(HttpParser.class); | 37 private static final Logger LOG = LoggerFactory.getLogger(HttpParser.class); |
38 | 38 |
39 // States | 39 // States |
40 public static final int STATE_START=-14; | 40 private static final int STATE_START=-14; |
41 public static final int STATE_FIELD0=-13; | 41 private static final int STATE_FIELD0=-13; |
42 public static final int STATE_SPACE1=-12; | 42 private static final int STATE_SPACE1=-12; |
43 public static final int STATE_STATUS=-11; | 43 private static final int STATE_STATUS=-11; |
44 public static final int STATE_URI=-10; | 44 private static final int STATE_URI=-10; |
45 public static final int STATE_SPACE2=-9; | 45 private static final int STATE_SPACE2=-9; |
46 public static final int STATE_END0=-8; | 46 private static final int STATE_END0=-8; |
47 public static final int STATE_END1=-7; | 47 private static final int STATE_END1=-7; |
48 public static final int STATE_FIELD2=-6; | 48 private static final int STATE_FIELD2=-6; |
49 public static final int STATE_HEADER=-5; | 49 private static final int STATE_HEADER=-5; |
50 public static final int STATE_HEADER_NAME=-4; | 50 private static final int STATE_HEADER_NAME=-4; |
51 public static final int STATE_HEADER_IN_NAME=-3; | 51 private static final int STATE_HEADER_IN_NAME=-3; |
52 public static final int STATE_HEADER_VALUE=-2; | 52 private static final int STATE_HEADER_VALUE=-2; |
53 public static final int STATE_HEADER_IN_VALUE=-1; | 53 private static final int STATE_HEADER_IN_VALUE=-1; |
54 public static final int STATE_END=0; | 54 private static final int STATE_END=0; |
55 public static final int STATE_EOF_CONTENT=1; | 55 private static final int STATE_EOF_CONTENT=1; |
56 public static final int STATE_CONTENT=2; | 56 private static final int STATE_CONTENT=2; |
57 public static final int STATE_CHUNKED_CONTENT=3; | 57 private static final int STATE_CHUNKED_CONTENT=3; |
58 public static final int STATE_CHUNK_SIZE=4; | 58 private static final int STATE_CHUNK_SIZE=4; |
59 public static final int STATE_CHUNK_PARAMS=5; | 59 private static final int STATE_CHUNK_PARAMS=5; |
60 public static final int STATE_CHUNK=6; | 60 private static final int STATE_CHUNK=6; |
61 public static final int STATE_SEEKING_EOF=7; | 61 private static final int STATE_SEEKING_EOF=7; |
62 | 62 |
63 private final EventHandler _handler; | 63 private final EventHandler _handler; |
64 private final Buffers _buffers; // source of buffers | 64 private final Buffers _buffers; // source of buffers |
65 private final EndPoint _endp; | 65 private final EndPoint _endp; |
66 private Buffer _header; // Buffer for header data (and small _content) | 66 private Buffer _header; // Buffer for header data (and small _content) |
69 private CachedBuffer _cached; | 69 private CachedBuffer _cached; |
70 private final View.CaseInsensitive _tok0; // Saved token: header name, request method or response version | 70 private final View.CaseInsensitive _tok0; // Saved token: header name, request method or response version |
71 private final View.CaseInsensitive _tok1; // Saved token: header value, request URI or response code | 71 private final View.CaseInsensitive _tok1; // Saved token: header value, request URI or response code |
72 private String _multiLineValue; | 72 private String _multiLineValue; |
73 private int _responseStatus; // If >0 then we are parsing a response | 73 private int _responseStatus; // If >0 then we are parsing a response |
74 private boolean _forceContentBuffer; | |
75 private boolean _persistent; | 74 private boolean _persistent; |
76 | 75 |
77 /* ------------------------------------------------------------------------------- */ | 76 protected final View _contentView = new View(); // View of the content in the buffer for {@link Input} |
78 protected final View _contentView=new View(); // View of the content in the buffer for {@link Input} | 77 protected int _state = STATE_START; |
79 protected int _state=STATE_START; | |
80 protected byte _eol; | 78 protected byte _eol; |
81 protected int _length; | 79 protected int _length; |
82 protected long _contentLength; | 80 protected long _contentLength; |
83 protected long _contentPosition; | 81 protected long _contentPosition; |
84 protected int _chunkLength; | 82 protected int _chunkLength; |
85 protected int _chunkPosition; | 83 protected int _chunkPosition; |
86 private boolean _headResponse; | 84 private boolean _headResponse; |
87 | 85 |
88 /* ------------------------------------------------------------------------------- */ | |
89 /** | |
90 * Constructor. | |
91 */ | |
92 public HttpParser(Buffer buffer, EventHandler handler) | |
93 { | |
94 _endp=null; | |
95 _buffers=null; | |
96 _header=buffer; | |
97 _buffer=buffer; | |
98 _handler=handler; | |
99 | |
100 _tok0=new View.CaseInsensitive(_header); | |
101 _tok1=new View.CaseInsensitive(_header); | |
102 } | |
103 | |
104 /* ------------------------------------------------------------------------------- */ | |
105 /** | |
106 * Constructor. | |
107 * @param buffers the buffers to use | |
108 * @param endp the endpoint | |
109 * @param handler the even handler | |
110 */ | |
111 public HttpParser(Buffers buffers, EndPoint endp, EventHandler handler) | 86 public HttpParser(Buffers buffers, EndPoint endp, EventHandler handler) |
112 { | 87 { |
113 _buffers=buffers; | 88 _buffers = buffers; |
114 _endp=endp; | 89 _endp = endp; |
115 _handler=handler; | 90 _handler = handler; |
116 _tok0=new View.CaseInsensitive(); | 91 _tok0 = new View.CaseInsensitive(); |
117 _tok1=new View.CaseInsensitive(); | 92 _tok1 = new View.CaseInsensitive(); |
118 } | 93 } |
119 | 94 |
120 /* ------------------------------------------------------------------------------- */ | |
121 public long getContentLength() | 95 public long getContentLength() |
122 { | 96 { |
123 return _contentLength; | 97 return _contentLength; |
124 } | 98 } |
125 | 99 |
126 /* ------------------------------------------------------------ */ | |
127 public long getContentRead() | 100 public long getContentRead() |
128 { | 101 { |
129 return _contentPosition; | 102 return _contentPosition; |
130 } | 103 } |
131 | 104 |
133 /** Set if a HEAD response is expected | 106 /** Set if a HEAD response is expected |
134 * @param head | 107 * @param head |
135 */ | 108 */ |
136 public void setHeadResponse(boolean head) | 109 public void setHeadResponse(boolean head) |
137 { | 110 { |
138 _headResponse=head; | 111 _headResponse = head; |
139 } | 112 } |
140 | 113 |
141 /* ------------------------------------------------------------------------------- */ | |
142 public int getState() | |
143 { | |
144 return _state; | |
145 } | |
146 | |
147 /* ------------------------------------------------------------------------------- */ | |
148 public boolean inContentState() | |
149 { | |
150 return _state > 0; | |
151 } | |
152 | |
153 /* ------------------------------------------------------------------------------- */ | |
154 public boolean inHeaderState() | |
155 { | |
156 return _state < 0; | |
157 } | |
158 | |
159 /* ------------------------------------------------------------------------------- */ | |
160 public boolean isChunking() | 114 public boolean isChunking() |
161 { | 115 { |
162 return _contentLength==HttpTokens.CHUNKED_CONTENT; | 116 return _contentLength==HttpTokens.CHUNKED_CONTENT; |
163 } | 117 } |
164 | 118 |
165 /* ------------------------------------------------------------ */ | |
166 public boolean isIdle() | 119 public boolean isIdle() |
167 { | 120 { |
168 return isState(STATE_START); | 121 return _state==STATE_START; |
169 } | 122 } |
170 | 123 |
171 /* ------------------------------------------------------------ */ | |
172 public boolean isComplete() | 124 public boolean isComplete() |
173 { | 125 { |
174 return isState(STATE_END); | 126 return _state==STATE_END; |
175 } | 127 } |
176 | 128 |
177 /* ------------------------------------------------------------ */ | |
178 public boolean isMoreInBuffer() | |
179 throws IOException | |
180 { | |
181 return ( _header!=null && _header.hasContent() || | |
182 _body!=null && _body.hasContent()); | |
183 } | |
184 | |
185 /* ------------------------------------------------------------------------------- */ | |
186 public boolean isState(int state) | |
187 { | |
188 return _state == state; | |
189 } | |
190 | |
191 /* ------------------------------------------------------------------------------- */ | |
192 public boolean isPersistent() | 129 public boolean isPersistent() |
193 { | 130 { |
194 return _persistent; | 131 return _persistent; |
195 } | 132 } |
196 | 133 |
197 /* ------------------------------------------------------------------------------- */ | |
198 public void setPersistent(boolean persistent) | 134 public void setPersistent(boolean persistent) |
199 { | 135 { |
200 _persistent = persistent; | 136 _persistent = persistent; |
201 if (!_persistent &&(_state==STATE_END || _state==STATE_START)) | 137 if (!_persistent &&(_state==STATE_END || _state==STATE_START)) |
202 _state=STATE_SEEKING_EOF; | 138 _state=STATE_SEEKING_EOF; |
203 } | |
204 | |
205 /* ------------------------------------------------------------------------------- */ | |
206 /** | |
207 * Parse until {@link #STATE_END END} state. | |
208 * If the parser is already in the END state, then it is {@link #reset reset} and re-parsed. | |
209 * @throws IllegalStateException If the buffers have already been partially parsed. | |
210 */ | |
211 public void parse() throws IOException | |
212 { | |
213 if (_state==STATE_END) | |
214 reset(); | |
215 if (_state!=STATE_START) | |
216 throw new IllegalStateException("!START"); | |
217 | |
218 // continue parsing | |
219 while (_state != STATE_END) | |
220 if (parseNext()<0) | |
221 return; | |
222 } | 139 } |
223 | 140 |
224 /* ------------------------------------------------------------------------------- */ | 141 /* ------------------------------------------------------------------------------- */ |
225 /** | 142 /** |
226 * Parse until END state. | 143 * Parse until END state. |
245 /* ------------------------------------------------------------------------------- */ | 162 /* ------------------------------------------------------------------------------- */ |
246 /** | 163 /** |
247 * Parse until next Event. | 164 * Parse until next Event. |
248 * @return an indication of progress <0 EOF, 0 no progress, >0 progress. | 165 * @return an indication of progress <0 EOF, 0 no progress, >0 progress. |
249 */ | 166 */ |
250 public int parseNext() throws IOException | 167 private int parseNext() throws IOException |
251 { | 168 { |
252 try | 169 try |
253 { | 170 { |
254 int progress=0; | 171 int progress=0; |
255 | 172 |
416 _responseStatus=_responseStatus*10+(ch-'0'); | 333 _responseStatus=_responseStatus*10+(ch-'0'); |
417 continue; | 334 continue; |
418 } | 335 } |
419 else if (ch < HttpTokens.SPACE && ch>=0) | 336 else if (ch < HttpTokens.SPACE && ch>=0) |
420 { | 337 { |
421 _handler.startResponse(HttpMethods.CACHE.lookup(_tok0), _responseStatus, null); | |
422 _eol=ch; | 338 _eol=ch; |
423 _state=STATE_HEADER; | 339 _state=STATE_HEADER; |
424 _tok0.setPutIndex(_tok0.getIndex()); | 340 _tok0.setPutIndex(_tok0.getIndex()); |
425 _tok1.setPutIndex(_tok1.getIndex()); | 341 _tok1.setPutIndex(_tok1.getIndex()); |
426 _multiLineValue=null; | 342 _multiLineValue=null; |
458 } | 374 } |
459 else if (ch < HttpTokens.SPACE) | 375 else if (ch < HttpTokens.SPACE) |
460 { | 376 { |
461 if (_responseStatus>0) | 377 if (_responseStatus>0) |
462 { | 378 { |
463 _handler.startResponse(HttpMethods.CACHE.lookup(_tok0), _responseStatus, null); | |
464 _eol=ch; | 379 _eol=ch; |
465 _state=STATE_HEADER; | 380 _state=STATE_HEADER; |
466 _tok0.setPutIndex(_tok0.getIndex()); | 381 _tok0.setPutIndex(_tok0.getIndex()); |
467 _tok1.setPutIndex(_tok1.getIndex()); | 382 _tok1.setPutIndex(_tok1.getIndex()); |
468 _multiLineValue=null; | 383 _multiLineValue=null; |
483 case STATE_FIELD2: | 398 case STATE_FIELD2: |
484 if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) | 399 if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) |
485 { | 400 { |
486 Buffer version; | 401 Buffer version; |
487 if (_responseStatus>0) | 402 if (_responseStatus>0) |
488 _handler.startResponse(version=HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark()); | 403 // _handler.startResponse(version=HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark()); |
404 version = HttpVersions.CACHE.lookup(_tok0); | |
489 else | 405 else |
490 _handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, version=HttpVersions.CACHE.lookup(_buffer.sliceFromMark())); | 406 _handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, version=HttpVersions.CACHE.lookup(_buffer.sliceFromMark())); |
491 _eol=ch; | 407 _eol=ch; |
492 _persistent=HttpVersions.CACHE.getOrdinal(version)>=HttpVersions.HTTP_1_1_ORDINAL; | 408 _persistent=HttpVersions.CACHE.getOrdinal(version)>=HttpVersions.HTTP_1_1_ORDINAL; |
493 _state=STATE_HEADER; | 409 _state=STATE_HEADER; |
998 | 914 |
999 /* ------------------------------------------------------------------------------- */ | 915 /* ------------------------------------------------------------------------------- */ |
1000 /** fill the buffers from the endpoint | 916 /** fill the buffers from the endpoint |
1001 * | 917 * |
1002 */ | 918 */ |
1003 protected int fill() throws IOException | 919 private int fill() throws IOException |
1004 { | 920 { |
1005 // Do we have a buffer? | 921 // Do we have a buffer? |
1006 if (_buffer==null) | 922 if (_buffer==null) |
1007 _buffer=getHeaderBuffer(); | 923 _buffer=getHeaderBuffer(); |
1008 | 924 |
1012 _buffer=_body; | 928 _buffer=_body; |
1013 return _buffer.length(); | 929 return _buffer.length(); |
1014 } | 930 } |
1015 | 931 |
1016 // Shall we switch to a body buffer? | 932 // Shall we switch to a body buffer? |
1017 if (_buffer==_header && _state>STATE_END && _header.length()==0 && (_forceContentBuffer || (_contentLength-_contentPosition)>_header.capacity()) && (_body!=null||_buffers!=null)) | 933 if (_buffer==_header && _state>STATE_END && _header.length()==0 && ((_contentLength-_contentPosition)>_header.capacity()) && (_body!=null||_buffers!=null)) |
1018 { | 934 { |
1019 if (_body==null) | 935 if (_body==null) |
1020 _body=_buffers.getBuffer(); | 936 _body=_buffers.getBuffer(); |
1021 _buffer=_body; | 937 _buffer=_body; |
1022 } | 938 } |
1023 | 939 |
1024 // Do we have somewhere to fill from? | 940 // Shall we compact the body? |
1025 if (_endp != null ) | 941 if (_buffer==_body || _state>STATE_END) |
1026 { | 942 { |
1027 // Shall we compact the body? | 943 _buffer.compact(); |
1028 if (_buffer==_body || _state>STATE_END) | 944 } |
1029 { | 945 |
1030 _buffer.compact(); | 946 // Are we full? |
1031 } | 947 if (_buffer.space() == 0) |
1032 | 948 { |
1033 // Are we full? | 949 LOG.warn("HttpParser Full for {} ",_endp); |
1034 if (_buffer.space() == 0) | 950 _buffer.clear(); |
1035 { | 951 throw new HttpException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "Request Entity Too Large: "+(_buffer==_body?"body":"head")); |
1036 LOG.warn("HttpParser Full for {} ",_endp); | 952 } |
1037 _buffer.clear(); | 953 |
1038 throw new HttpException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "Request Entity Too Large: "+(_buffer==_body?"body":"head")); | 954 try |
1039 } | 955 { |
1040 | 956 int filled = _endp.fill(_buffer); |
1041 try | 957 return filled; |
1042 { | 958 } |
1043 int filled = _endp.fill(_buffer); | 959 catch(IOException e) |
1044 return filled; | 960 { |
1045 } | 961 LOG.debug("",e); |
1046 catch(IOException e) | 962 throw (e instanceof EofException) ? e:new EofException(e); |
1047 { | 963 } |
1048 LOG.debug("",e); | 964 } |
1049 throw (e instanceof EofException) ? e:new EofException(e); | 965 |
1050 } | |
1051 } | |
1052 | |
1053 return -1; | |
1054 } | |
1055 | |
1056 /* ------------------------------------------------------------------------------- */ | |
1057 public void reset() | 966 public void reset() |
1058 { | 967 { |
1059 // reset state | 968 // reset state |
1060 _contentView.setGetIndex(_contentView.putIndex()); | 969 _contentView.setGetIndex(_contentView.putIndex()); |
1061 _state=_persistent?STATE_START:(_endp.isInputShutdown()?STATE_END:STATE_SEEKING_EOF); | 970 _state=_persistent?STATE_START:(_endp.isInputShutdown()?STATE_END:STATE_SEEKING_EOF); |
1098 _buffer=_header; | 1007 _buffer=_header; |
1099 returnBuffers(); | 1008 returnBuffers(); |
1100 } | 1009 } |
1101 | 1010 |
1102 | 1011 |
1103 /* ------------------------------------------------------------------------------- */ | |
1104 public void returnBuffers() | 1012 public void returnBuffers() |
1105 { | 1013 { |
1106 if (_body!=null && !_body.hasContent() && _body.markIndex()==-1 && _buffers!=null) | 1014 if (_body!=null && !_body.hasContent() && _body.markIndex()==-1 && _buffers!=null) |
1107 { | 1015 { |
1108 if (_buffer==_body) | 1016 if (_buffer==_body) |
1119 _buffers.returnBuffer(_header); | 1027 _buffers.returnBuffer(_header); |
1120 _header=null; | 1028 _header=null; |
1121 } | 1029 } |
1122 } | 1030 } |
1123 | 1031 |
1124 /* ------------------------------------------------------------------------------- */ | |
1125 public void setState(int state) | |
1126 { | |
1127 this._state=state; | |
1128 _contentLength=HttpTokens.UNKNOWN_CONTENT; | |
1129 } | |
1130 | |
1131 /* ------------------------------------------------------------------------------- */ | |
1132 public String toString(Buffer buf) | |
1133 { | |
1134 return "state=" + _state + " length=" + _length + " buf=" + buf.hashCode(); | |
1135 } | |
1136 | |
1137 /* ------------------------------------------------------------------------------- */ | |
1138 @Override | 1032 @Override |
1139 public String toString() | 1033 public String toString() |
1140 { | 1034 { |
1141 return String.format("%s{s=%d,l=%d,c=%d}", | 1035 return String.format("%s{s=%d,l=%d,c=%d}", |
1142 getClass().getSimpleName(), | 1036 getClass().getSimpleName(), |
1143 _state, | 1037 _state, |
1144 _length, | 1038 _length, |
1145 _contentLength); | 1039 _contentLength); |
1146 } | 1040 } |
1147 | 1041 |
1148 /* ------------------------------------------------------------ */ | |
1149 public Buffer getHeaderBuffer() | 1042 public Buffer getHeaderBuffer() |
1150 { | 1043 { |
1151 if (_header == null) | 1044 if (_header == null) |
1152 { | 1045 { |
1153 _header=_buffers.getHeader(); | 1046 _header = _buffers.getHeader(); |
1154 _tok0.update(_header); | 1047 _tok0.update(_header); |
1155 _tok1.update(_header); | 1048 _tok1.update(_header); |
1156 } | 1049 } |
1157 return _header; | 1050 return _header; |
1158 } | 1051 } |
1159 | 1052 |
1160 /* ------------------------------------------------------------ */ | |
1161 public Buffer getBodyBuffer() | |
1162 { | |
1163 return _body; | |
1164 } | |
1165 | |
1166 /* ------------------------------------------------------------ */ | |
1167 /** | |
1168 * @param force True if a new buffer will be forced to be used for content and the header buffer will not be used. | |
1169 */ | |
1170 public void setForceContentBuffer(boolean force) | |
1171 { | |
1172 _forceContentBuffer=force; | |
1173 } | |
1174 | |
1175 /* ------------------------------------------------------------ */ | |
1176 public Buffer blockForContent(long maxIdleTime) throws IOException | 1053 public Buffer blockForContent(long maxIdleTime) throws IOException |
1177 { | 1054 { |
1178 if (_contentView.length()>0) | 1055 if (_contentView.length()>0) |
1179 return _contentView; | 1056 return _contentView; |
1180 | 1057 |
1181 if (getState() <= STATE_END || isState(STATE_SEEKING_EOF)) | 1058 if (_state <= STATE_END || _state==STATE_SEEKING_EOF) |
1182 return null; | 1059 return null; |
1183 | 1060 |
1184 try | 1061 try |
1185 { | 1062 { |
1186 parseNext(); | 1063 parseNext(); |
1187 | 1064 |
1188 // parse until some progress is made (or IOException thrown for timeout) | 1065 // parse until some progress is made (or IOException thrown for timeout) |
1189 while(_contentView.length() == 0 && !(isState(HttpParser.STATE_END)||isState(HttpParser.STATE_SEEKING_EOF)) && _endp!=null && _endp.isOpen()) | 1066 while(_contentView.length() == 0 && !(_state==STATE_END||_state==STATE_SEEKING_EOF) && _endp.isOpen()) |
1190 { | 1067 { |
1191 if (!_endp.isBlocking()) | 1068 if (!_endp.isBlocking()) |
1192 { | 1069 { |
1193 if (parseNext()>0) | 1070 if (parseNext()>0) |
1194 continue; | 1071 continue; |
1229 | 1106 |
1230 parseNext(); | 1107 parseNext(); |
1231 return _contentView==null?0:_contentView.length(); | 1108 return _contentView==null?0:_contentView.length(); |
1232 } | 1109 } |
1233 | 1110 |
1234 /* ------------------------------------------------------------ */ | 1111 |
1235 /* ------------------------------------------------------------ */ | 1112 public interface EventHandler |
1236 /* ------------------------------------------------------------ */ | |
1237 public static abstract class EventHandler | |
1238 { | 1113 { |
1239 public abstract void content(Buffer ref) throws IOException; | 1114 public abstract void content(Buffer ref) throws IOException; |
1240 | 1115 |
1241 public void headerComplete() throws IOException | 1116 public void headerComplete() throws IOException; |
1242 { | 1117 |
1243 } | 1118 public void messageComplete(long contentLength) throws IOException; |
1244 | |
1245 public void messageComplete(long contentLength) throws IOException | |
1246 { | |
1247 } | |
1248 | 1119 |
1249 /** | 1120 /** |
1250 * This is the method called by parser when a HTTP Header name and value is found | 1121 * This is the method called by parser when a HTTP Header name and value is found |
1251 */ | 1122 */ |
1252 public void parsedHeader(Buffer name, Buffer value) throws IOException | 1123 public void parsedHeader(Buffer name, Buffer value) throws IOException; |
1253 { | |
1254 } | |
1255 | 1124 |
1256 /** | 1125 /** |
1257 * This is the method called by parser when the HTTP request line is parsed | 1126 * This is the method called by parser when the HTTP request line is parsed |
1258 */ | 1127 */ |
1259 public abstract void startRequest(Buffer method, Buffer url, Buffer version) | 1128 public abstract void startRequest(Buffer method, Buffer url, Buffer version) |
1260 throws IOException; | 1129 throws IOException; |
1261 | 1130 |
1262 /** | 1131 public void earlyEOF(); |
1263 * This is the method called by parser when the HTTP request line is parsed | |
1264 */ | |
1265 public abstract void startResponse(Buffer version, int status, Buffer reason) | |
1266 throws IOException; | |
1267 | |
1268 public void earlyEOF() | |
1269 {} | |
1270 } | 1132 } |
1271 | 1133 |
1272 | 1134 |
1273 | 1135 |
1274 | 1136 |