=== 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 |