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

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: Removed CanResumeDownload (unused) and updated comment in RDH::BeginDownload. 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 if query:
1645 for ele in query.split('&'):
Paweł Hajdan Jr. 2013/01/04 22:56:58 Are you doing query string parsing here? Please us
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Whoops. Very good point. Done.
1646 namevalue = ele.split('=')
1647 name = namevalue[0]
1648 value = namevalue[1] if len(namevalue) == 2 else None
1649 if name == 'size':
1650 size = int(val)
1651 elif name == 'rst_boundary':
1652 rst_boundary = int(val)
1653 elif name == 'bounce_range':
1654 respond_to_range = False
1655 elif name == 'hold':
1656 hold_for_signal = True
1657 else:
1658 return False
1659
1660 first_byte = 0
1661 last_byte = size - 1
1662
1663 # Does that define what we want to return, or do we need to apply
1664 # a range?
1665 range_response = False
1666 range_header = self.headers.getheader('range')
1667 if range_header and respond_to_range:
1668 mo = re.match("bytes=([0-9]*)-([0-9]*)", range_header)
Paweł Hajdan Jr. 2013/01/04 22:56:58 nit: Why not \d for the digits?
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Too much time using emacs regexps + hammering in a
1669 if mo.group(1):
1670 first_byte = int(mo.group(1))
1671 if mo.group(2):
1672 last_byte = int(mo.group(2))
1673 if last_byte > size - 1:
1674 last_byte = size - 1
1675 range_response = True
1676 if last_byte < first_byte:
1677 return False
1678
1679 if not range_response:
Paweł Hajdan Jr. 2013/01/04 22:56:58 nit: Reverse the order - put if range_response bra
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Done.
1680 self.send_response(200)
1681 else:
1682 self.send_response(206)
1683 self.send_header('Content-Range',
1684 'bytes %d-%d/%d' % (first_byte, last_byte, size))
1685 self.send_header('Content-Type', 'application/octet-stream')
1686 self.send_header('Content-Length', last_byte - first_byte + 1)
1687 self.end_headers()
1688
1689 if hold_for_signal:
1690 ## Needed to allow server to handle new requests (weird).
Paweł Hajdan Jr. 2013/01/04 22:56:58 nit: No double # please, and what is really going
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 I've updated the comment; let me know if you want
1691 self.wfile.write('X')
1692 first_byte = first_byte + 1
1693 # handle requests until one of them clears this flag.
1694 self.server.waitForDownload = True
1695 while self.server.waitForDownload:
1696 self.server.handle_request()
1697
1698 possible_rst = ((first_byte / rst_boundary) + 1) * rst_boundary
1699 if possible_rst < last_byte:
1700 ## We're resetting the conneciton part way in.
Paweł Hajdan Jr. 2013/01/04 22:56:58 nit: No double #.
benjhayden 2013/01/06 15:46:04 connecTIon
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Done.
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Done.
1701 self.wfile.write('X' * (possible_rst - first_byte))
1702 s = self.connection # This is the request socket.
Paweł Hajdan Jr. 2013/01/04 22:56:58 nit: Make the comment more meaningful. What is thi
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Done.
1703 l_onoff = 1 # Linger is active.
1704 l_linger = 0 # Seconds to linger for.
1705 s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
1706 struct.pack('ii', l_onoff, l_linger))
1707 s.close()
1708 time.sleep(0.05) # Give time to the system.
Paweł Hajdan Jr. 2013/01/04 22:56:58 Huh? That makes me extremely suspicious. Did you i
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Interesting. I copied that code, assuming that we
Randy Smith (Not in Mondays) 2013/01/08 19:31:12 Pawel: I was wrong, that sleep was needed for the
1709 else:
1710 ## A more normal response
Paweł Hajdan Jr. 2013/01/04 22:56:58 nit: No double #, and make it more meaningful plea
Randy Smith (Not in Mondays) 2013/01/07 20:54:10 Done, although I wince a little, as that makes the
1711 self.wfile.write('X' * (last_byte - first_byte + 1))
1712
1713 return True
1714
1624 def DefaultResponseHandler(self): 1715 def DefaultResponseHandler(self):
1625 """This is the catch-all response handler for requests that aren't handled 1716 """This is the catch-all response handler for requests that aren't handled
1626 by one of the special handlers above. 1717 by one of the special handlers above.
1627 Note that we specify the content-length as without it the https connection 1718 Note that we specify the content-length as without it the https connection
1628 is not closed properly (and the browser keeps expecting data).""" 1719 is not closed properly (and the browser keeps expecting data)."""
1629 1720
1630 contents = "Default response given for path: " + self.path 1721 contents = "Default response given for path: " + self.path
1631 self.send_response(200) 1722 self.send_response(200)
1632 self.send_header('Content-Type', 'text/html') 1723 self.send_header('Content-Type', 'text/html')
1633 self.send_header('Content-Length', len(contents)) 1724 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 ' 2533 'load multipe keys into the server. If the '
2443 'server has multiple keys, it will rotate ' 2534 'server has multiple keys, it will rotate '
2444 'through them in at each request a ' 2535 'through them in at each request a '
2445 'round-robin fashion. The server will ' 2536 'round-robin fashion. The server will '
2446 'generate a random key if none is specified ' 2537 'generate a random key if none is specified '
2447 'on the command line.') 2538 'on the command line.')
2448 2539
2449 2540
2450 if __name__ == '__main__': 2541 if __name__ == '__main__':
2451 sys.exit(ServerRunner().main()) 2542 sys.exit(ServerRunner().main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698