Added support for implementation mirrors
[zeroinstall/solver.git] / tests / server.py
blobabe9ed51872eab94267a1935ed3b2e2a42862c21
1 #!/usr/bin/env python
3 from __future__ import print_function
5 import os, sys
6 import traceback
8 if sys.version_info[0] > 2:
9 from urllib import parse as urlparse # Python 3
10 from http import server
11 import pickle
12 else:
13 import urlparse
14 import BaseHTTPServer as server
15 import cPickle as pickle
17 next_step = None
19 class Give404:
20 def __init__(self, path):
21 self.path = path
23 def __str__(self):
24 return self.path
26 def __repr__(self):
27 return "404 on " + self.path
29 class MyHandler(server.BaseHTTPRequestHandler):
30 def do_GET(self):
31 parsed = urlparse.urlparse(self.path)
33 print(parsed)
34 if parsed.path.startswith('/redirect/'):
35 self.send_response(302)
36 self.wfile.write(('Location: /' + parsed.path[1:].split('/', 1)[1]).encode('utf-8'))
37 return
39 leaf = os.path.basename(parsed.path)
41 acceptable = dict([(str(x), x) for x in next_step])
43 resp = acceptable.get(parsed.path, None) or \
44 acceptable.get(leaf, None) or \
45 acceptable.get('*', None)
47 # (don't use a symlink as they don't work on Windows)
48 if leaf == 'latest.xml':
49 leaf = 'Hello.xml'
50 elif parsed.path == '/0mirror/feeds/http/example.com:8000/Hello.xml/impl/sha1=3ce644dc725f1d21cfcf02562c76f375944b266a':
51 leaf = 'HelloWorld.tgz'
53 if not resp:
54 self.send_error(404, "Expected %s; got %s" % (next_step, parsed.path))
55 elif parsed.path.startswith('/key-info/'):
56 self.send_response(200)
57 self.end_headers()
58 self.wfile.write(b'<key-lookup><item vote="good">Approved for testing</item></key-lookup>')
59 self.wfile.close()
60 elif os.path.exists(leaf) and not isinstance(resp, Give404):
61 self.send_response(200)
62 self.end_headers()
63 with open(leaf, 'rb') as stream:
64 self.wfile.write(stream.read())
65 self.wfile.close()
66 else:
67 self.send_error(404, "Missing: %s" % leaf)
69 def handle_requests(*script):
70 from subprocess import Popen, PIPE
72 # Pass the script on the command line as a pickle.
73 child = Popen(
74 [sys.executable, __file__, repr(pickle.dumps(script)) ],
75 stdout=PIPE, universal_newlines=True)
77 # Make sure the server is actually running before we try to
78 # interact with it.
79 l = child.stdout.readline()
80 assert l == 'Waiting for request\n', l
81 return child
83 def main():
84 # Grab the script that was passed on the command line from the parent
85 script = pickle.loads(eval(sys.argv[1]))
86 server_address = ('localhost', 8000)
87 httpd = server.HTTPServer(server_address, MyHandler)
88 try:
89 sys.stderr = sys.stdout
90 #sys.stdout = sys.stderr
91 print("Waiting for request")
92 sys.stdout.flush() # Make sure the "Waiting..." message is seen by the parent
93 global next_step
94 for next_step in script:
95 if type(next_step) != tuple: next_step = (next_step,)
96 for x in next_step:
97 httpd.handle_request()
98 print("Done")
99 os._exit(0)
100 except:
101 traceback.print_exc()
102 os._exit(1)
104 if __name__ == '__main__':
105 # This is the child process. We have to import ourself and
106 # run the main routine there, or the pickled Give404 instances
107 # passed from the parent won't be recognized as having the
108 # same class (server.Give404).
109 import server
110 server.main()