Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(514)

Side by Side Diff: net/tools/testserver/testserver.py

Issue 11571025: Initial CL for Downloads resumption. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporated comments. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ server used for testing Chrome. 6 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ server used for testing Chrome.
7 7
8 It supports several test URLs, as specified by the handlers in TestPageHandler. 8 It supports several test URLs, as specified by the handlers in TestPageHandler.
9 By default, it listens on an ephemeral port and sends the port number back to 9 By default, it listens on an ephemeral port and sends the port number back to
10 the originating process over a pipe. The originating process can specify an 10 the originating process over a pipe. The originating process can specify an
(...skipping 10 matching lines...) Expand all
21 import hashlib 21 import hashlib
22 import json 22 import json
23 import logging 23 import logging
24 import minica 24 import minica
25 import os 25 import os
26 import random 26 import random
27 import re 27 import re
28 import select 28 import select
29 import socket 29 import socket
30 import SocketServer 30 import SocketServer
31 import struct
31 import sys 32 import sys
32 import threading 33 import threading
33 import time 34 import time
34 import urllib 35 import urllib
35 import urlparse 36 import urlparse
36 import zlib 37 import zlib
37 38
38 import echo_message 39 import echo_message
39 import pyftpdlib.ftpserver 40 import pyftpdlib.ftpserver
40 import testserver_base 41 import testserver_base
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 self.SlowServerHandler, 467 self.SlowServerHandler,
467 self.ChunkedServerHandler, 468 self.ChunkedServerHandler,
468 self.ContentTypeHandler, 469 self.ContentTypeHandler,
469 self.NoContentHandler, 470 self.NoContentHandler,
470 self.ServerRedirectHandler, 471 self.ServerRedirectHandler,
471 self.ClientRedirectHandler, 472 self.ClientRedirectHandler,
472 self.MultipartHandler, 473 self.MultipartHandler,
473 self.MultipartSlowHandler, 474 self.MultipartSlowHandler,
474 self.GetSSLSessionCacheHandler, 475 self.GetSSLSessionCacheHandler,
475 self.CloseSocketHandler, 476 self.CloseSocketHandler,
477 self.RangeResetHandler,
476 self.DefaultResponseHandler] 478 self.DefaultResponseHandler]
477 post_handlers = [ 479 post_handlers = [
478 self.EchoTitleHandler, 480 self.EchoTitleHandler,
479 self.EchoHandler, 481 self.EchoHandler,
480 self.DeviceManagementHandler, 482 self.DeviceManagementHandler,
481 self.PostOnlyFileHandler] + get_handlers 483 self.PostOnlyFileHandler] + get_handlers
482 put_handlers = [ 484 put_handlers = [
483 self.EchoTitleHandler, 485 self.EchoTitleHandler,
484 self.EchoHandler] + get_handlers 486 self.EchoHandler] + get_handlers
485 head_handlers = [ 487 head_handlers = [
(...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1614 1616
1615 def CloseSocketHandler(self): 1617 def CloseSocketHandler(self):
1616 """Closes the socket without sending anything.""" 1618 """Closes the socket without sending anything."""
1617 1619
1618 if not self._ShouldHandleRequest('/close-socket'): 1620 if not self._ShouldHandleRequest('/close-socket'):
1619 return False 1621 return False
1620 1622
1621 self.wfile.close() 1623 self.wfile.close()
1622 return True 1624 return True
1623 1625
1626 def RangeResetHandler(self):
1627 """Send data broken up by connection resets every N (default 10K) bytes.
1628 Support range requests. If the data requested doesn't straddle a reset
1629 boundary, it will all be sent. Used for testing resuming downloads."""
1630
1631 if not self._ShouldHandleRequest('/rangereset'):
1632 return False
1633
1634 _, _, url_path, _, query, _ = urlparse.urlparse(self.path)
1635
1636 # Defaults
1637 size = 15000
1638 # Note that the rst is sent just before sending the rst_boundary byte.
1639 rst_boundary = 10000
1640 respond_to_range = True
1641 hold_for_signal = False
1642
1643 # Parse the query
1644 qdict = urlparse.parse_qs(query, True)
1645 if 'size' in qdict:
1646 size = int(qdict['size'])
1647 if 'rst_boundary' in qdict:
1648 rst_boundary = int(qdict['rst_boundary'])
1649 if 'bounce_range' in qdict:
1650 respond_to_range = False
1651 if 'hold' in qdict:
1652 hold_for_signal = True
1653
1654 first_byte = 0
1655 last_byte = size - 1
1656
1657 # Does that define what we want to return, or do we need to apply
1658 # a range?
1659 range_response = False
1660 range_header = self.headers.getheader('range')
1661 if range_header and respond_to_range:
1662 mo = re.match("bytes=(\d*)-(\d*)", range_header)
1663 if mo.group(1):
1664 first_byte = int(mo.group(1))
1665 if mo.group(2):
1666 last_byte = int(mo.group(2))
1667 if last_byte > size - 1:
1668 last_byte = size - 1
1669 range_response = True
1670 if last_byte < first_byte:
1671 return False
1672
1673 if range_response:
1674 self.send_response(206)
1675 self.send_header('Content-Range',
1676 'bytes %d-%d/%d' % (first_byte, last_byte, size))
1677 else:
1678 self.send_response(200)
1679 self.send_header('Content-Type', 'application/octet-stream')
1680 self.send_header('Content-Length', last_byte - first_byte + 1)
1681 self.end_headers()
1682
1683 if hold_for_signal:
1684 # Hack alert/explanation: Without writing a single byte, the
1685 # self.server.handle_request() below hangs without processing
1686 # new incoming requests. Presumably this is due to a bug in
1687 # BaseHTTPRequestHandler.
1688 self.wfile.write('X')
1689 first_byte = first_byte + 1
1690 # handle requests until one of them clears this flag.
1691 self.server.waitForDownload = True
1692 while self.server.waitForDownload:
1693 self.server.handle_request()
1694
1695 possible_rst = ((first_byte / rst_boundary) + 1) * rst_boundary
1696 if possible_rst >= last_byte:
1697 # No RST has been requested in this range, so we don't need to
1698 # do anything fancy; just write the data and let the python
1699 # infrastructure close the connection.
1700 self.wfile.write('X' * (last_byte - first_byte + 1))
1701 return True
1702
1703 # We're resetting the connection part way in; go to the RST
1704 # boundary and then send an RST.
1705 self.wfile.write('X' * (possible_rst - first_byte))
1706 l_onoff = 1 # Linger is active.
1707 l_linger = 0 # Seconds to linger for.
1708 self.connection.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
1709 struct.pack('ii', l_onoff, l_linger))
1710 self.connection.close()
1711
1712 return True
1713
1624 def DefaultResponseHandler(self): 1714 def DefaultResponseHandler(self):
1625 """This is the catch-all response handler for requests that aren't handled 1715 """This is the catch-all response handler for requests that aren't handled
1626 by one of the special handlers above. 1716 by one of the special handlers above.
1627 Note that we specify the content-length as without it the https connection 1717 Note that we specify the content-length as without it the https connection
1628 is not closed properly (and the browser keeps expecting data).""" 1718 is not closed properly (and the browser keeps expecting data)."""
1629 1719
1630 contents = "Default response given for path: " + self.path 1720 contents = "Default response given for path: " + self.path
1631 self.send_response(200) 1721 self.send_response(200)
1632 self.send_header('Content-Type', 'text/html') 1722 self.send_header('Content-Type', 'text/html')
1633 self.send_header('Content-Length', len(contents)) 1723 self.send_header('Content-Length', len(contents))
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 'load multipe keys into the server. If the ' 2532 'load multipe keys into the server. If the '
2443 'server has multiple keys, it will rotate ' 2533 'server has multiple keys, it will rotate '
2444 'through them in at each request a ' 2534 'through them in at each request a '
2445 'round-robin fashion. The server will ' 2535 'round-robin fashion. The server will '
2446 'generate a random key if none is specified ' 2536 'generate a random key if none is specified '
2447 'on the command line.') 2537 'on the command line.')
2448 2538
2449 2539
2450 if __name__ == '__main__': 2540 if __name__ == '__main__':
2451 sys.exit(ServerRunner().main()) 2541 sys.exit(ServerRunner().main())
OLDNEW
« content/public/browser/download_item.h ('K') | « content/public/test/mock_download_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698