=== added file 'DO_NOT_MERGE_,FOR_TWISTED_ONLY'
=== modified file 'twisted/web/_newclient.py' (properties changed: -x to +x)
|
|
|
209 | 209 | # |
210 | 210 | # -exarkun |
211 | 211 | |
| 212 | delimiter = '\n' |
| 213 | |
212 | 214 | CONNECTION_CONTROL_HEADERS = set([ |
213 | 215 | 'content-length', 'connection', 'keep-alive', 'te', 'trailers', |
214 | 216 | 'transfer-encoding', 'upgrade', 'proxy-connection']) |
… |
… |
|
237 | 239 | """ |
238 | 240 | Handle one line from a response. |
239 | 241 | """ |
| 242 | |
| 243 | # some servers like http://news.ycombinator.com/ return status lines |
| 244 | # and http headers delimited by \n instead of \r\n |
| 245 | if line[-1:] == '\r': |
| 246 | line = line[:-1] |
| 247 | |
240 | 248 | if self.state == STATUS: |
241 | 249 | self.statusReceived(line) |
242 | 250 | self.state = HEADER |
=== modified file 'twisted/web/test/test_newclient.py' (properties changed: -x to +x)
|
|
|
150 | 150 | |
151 | 151 | |
152 | 152 | |
153 | | class HTTPParserTests(TestCase): |
154 | | """ |
155 | | Tests for L{HTTPParser} which is responsible for the bulk of the task of |
156 | | parsing HTTP bytes. |
157 | | """ |
| 153 | class _HTTPParserTests(object): |
| 154 | """ |
| 155 | Base test class for L{HTTPParser} which is responsible for the bulk of |
| 156 | the task of parsing HTTP bytes. |
| 157 | """ |
| 158 | |
| 159 | sep = None |
| 160 | |
158 | 161 | def test_statusCallback(self): |
159 | 162 | """ |
160 | 163 | L{HTTPParser} calls its C{statusReceived} method when it receives a |
… |
… |
|
165 | 168 | protocol.statusReceived = status.append |
166 | 169 | protocol.makeConnection(StringTransport()) |
167 | 170 | self.assertEqual(protocol.state, STATUS) |
168 | | protocol.dataReceived('HTTP/1.1 200 OK\r\n') |
| 171 | protocol.dataReceived('HTTP/1.1 200 OK' + self.sep) |
169 | 172 | self.assertEqual(status, ['HTTP/1.1 200 OK']) |
170 | 173 | self.assertEqual(protocol.state, HEADER) |
171 | 174 | |
… |
… |
|
175 | 178 | protocol = HTTPParser() |
176 | 179 | protocol.headerReceived = header.__setitem__ |
177 | 180 | protocol.makeConnection(StringTransport()) |
178 | | protocol.dataReceived('HTTP/1.1 200 OK\r\n') |
| 181 | protocol.dataReceived('HTTP/1.1 200 OK' + self.sep) |
179 | 182 | return header, protocol |
180 | 183 | |
181 | 184 | |
… |
… |
|
185 | 188 | header. |
186 | 189 | """ |
187 | 190 | header, protocol = self._headerTestSetup() |
188 | | protocol.dataReceived('X-Foo:bar\r\n') |
| 191 | protocol.dataReceived('X-Foo:bar' + self.sep) |
189 | 192 | # Cannot tell it's not a continue header until the next line arrives |
190 | 193 | # and is not a continuation |
191 | | protocol.dataReceived('\r\n') |
| 194 | protocol.dataReceived(self.sep) |
192 | 195 | self.assertEqual(header, {'X-Foo': 'bar'}) |
193 | 196 | self.assertEqual(protocol.state, BODY) |
194 | 197 | |
… |
… |
|
199 | 202 | C{headerReceived} with the entire value once it is received. |
200 | 203 | """ |
201 | 204 | header, protocol = self._headerTestSetup() |
202 | | protocol.dataReceived('X-Foo: bar\r\n') |
203 | | protocol.dataReceived(' baz\r\n') |
204 | | protocol.dataReceived('\tquux\r\n') |
205 | | protocol.dataReceived('\r\n') |
| 205 | protocol.dataReceived('X-Foo: bar' + self.sep) |
| 206 | protocol.dataReceived(' baz' + self.sep) |
| 207 | protocol.dataReceived('\tquux' + self.sep) |
| 208 | protocol.dataReceived(self.sep) |
206 | 209 | self.assertEqual(header, {'X-Foo': 'bar baz\tquux'}) |
207 | 210 | self.assertEqual(protocol.state, BODY) |
208 | 211 | |
… |
… |
|
213 | 216 | value passed to the C{headerReceived} callback. |
214 | 217 | """ |
215 | 218 | header, protocol = self._headerTestSetup() |
216 | | value = ' \t \r\n bar \t\r\n \t\r\n' |
| 219 | value = ' \t %(sep)s bar \t%(sep)s \t%(sep)s' % dict(sep=self.sep) |
217 | 220 | protocol.dataReceived('X-Bar:' + value) |
218 | 221 | protocol.dataReceived('X-Foo:' + value) |
219 | | protocol.dataReceived('\r\n') |
| 222 | protocol.dataReceived(self.sep) |
220 | 223 | self.assertEqual(header, {'X-Foo': 'bar', |
221 | 224 | 'X-Bar': 'bar'}) |
222 | 225 | |
… |
… |
|
232 | 235 | called.append(protocol.state) |
233 | 236 | protocol.state = STATUS |
234 | 237 | protocol.allHeadersReceived = allHeadersReceived |
235 | | protocol.dataReceived('\r\n') |
| 238 | protocol.dataReceived(self.sep) |
236 | 239 | self.assertEqual(called, [HEADER]) |
237 | 240 | self.assertEqual(protocol.state, STATUS) |
238 | 241 | |
… |
… |
|
243 | 246 | C{headerReceived}. |
244 | 247 | """ |
245 | 248 | header, protocol = self._headerTestSetup() |
246 | | protocol.dataReceived('\r\n') |
| 249 | protocol.dataReceived(self.sep) |
247 | 250 | self.assertEqual(header, {}) |
248 | 251 | self.assertEqual(protocol.state, BODY) |
249 | 252 | |
… |
… |
|
255 | 258 | """ |
256 | 259 | protocol = HTTPParser() |
257 | 260 | protocol.makeConnection(StringTransport()) |
258 | | protocol.dataReceived('HTTP/1.1 200 OK\r\n') |
259 | | protocol.dataReceived('X-Foo: bar\r\n') |
260 | | protocol.dataReceived('X-Foo: baz\r\n') |
261 | | protocol.dataReceived('\r\n') |
262 | | self.assertEqual( |
263 | | list(protocol.headers.getAllRawHeaders()), |
264 | | [('X-Foo', ['bar', 'baz'])]) |
| 261 | protocol.dataReceived('HTTP/1.1 200 OK' + self.sep) |
| 262 | protocol.dataReceived('X-Foo: bar' + self.sep) |
| 263 | protocol.dataReceived('X-Foo: baz' + self.sep) |
| 264 | protocol.dataReceived(self.sep) |
| 265 | expected = [('X-Foo', ['bar', 'baz'])] |
| 266 | self.assertEqual(expected, list(protocol.headers.getAllRawHeaders())) |
265 | 267 | |
266 | 268 | |
267 | 269 | def test_connectionControlHeaders(self): |
… |
… |
|
298 | 300 | |
299 | 301 | |
300 | 302 | |
| 303 | class HTTPParserTestsRFCComplaintDelimeter(_HTTPParserTests, TestCase): |
| 304 | """ |
| 305 | L{_HTTPParserTests} using standard CR LF newlines. |
| 306 | """ |
| 307 | sep = '\r\n' |
| 308 | |
| 309 | |
| 310 | |
| 311 | class HTTPParserTestsNonRFCComplaintDelimeter(_HTTPParserTests, TestCase): |
| 312 | """ |
| 313 | L{_HTTPParserTests} using bare LF newlines. |
| 314 | """ |
| 315 | sep = '\n' |
| 316 | |
| 317 | |
| 318 | |
301 | 319 | class HTTPClientParserTests(TestCase): |
302 | 320 | """ |
303 | 321 | Tests for L{HTTPClientParser} which is responsible for parsing HTTP |