| # Copyright 2015 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """An HTTP server to use for external repository integration tests.""" |
| |
| # pylint: disable=g-import-not-at-top,g-importing-member |
| import argparse |
| import base64 |
| try: |
| from http.server import BaseHTTPRequestHandler |
| except ImportError: |
| # Python 2.x compatibility hack. |
| from BaseHTTPServer import BaseHTTPRequestHandler |
| import os |
| import os.path |
| try: |
| from socketserver import TCPServer |
| from socketserver import UnixStreamServer |
| except ImportError: |
| # Python 2.x compatibility hack. |
| from SocketServer import TCPServer |
| from SocketServer import UnixStreamServer |
| import random |
| import socket |
| import sys |
| import time |
| |
| |
| class Handler(BaseHTTPRequestHandler): |
| """Handlers for testing HTTP server.""" |
| auth = False |
| not_found = False |
| simulate_timeout = False |
| filename = None |
| redirect = None |
| valid_header = b'Basic ' + base64.b64encode('foo:bar'.encode('ascii')) |
| |
| def do_HEAD(self): # pylint: disable=invalid-name |
| self.send_response(200) |
| self.send_header('Content-type', 'text/html') |
| self.end_headers() |
| |
| def do_AUTHHEAD(self): # pylint: disable=invalid-name |
| self.send_response(401) |
| self.send_header('WWW-Authenticate', 'Basic realm=\"Bazel\"') |
| self.send_header('Content-type', 'text/html') |
| self.end_headers() |
| |
| def do_GET(self): # pylint: disable=invalid-name |
| if not self.client_address: |
| # Needed for Unix domain connections as the response functions |
| # fail without this being set. |
| self.client_address = 'localhost' |
| |
| if self.simulate_timeout: |
| while True: |
| time.sleep(1) |
| |
| if self.not_found: |
| self.send_response(404) |
| self.end_headers() |
| return |
| |
| if self.redirect is not None: |
| self.send_response(301) |
| self.send_header('Location', self.redirect) |
| self.end_headers() |
| return |
| |
| if not self.auth: |
| self.do_HEAD() |
| self.serve_file() |
| return |
| |
| auth_header = self.headers.get('Authorization', '').encode('ascii') |
| if auth_header == self.valid_header: |
| self.do_HEAD() |
| self.serve_file() |
| else: |
| self.do_AUTHHEAD() |
| self.wfile.write(b'Login required.') |
| |
| def serve_file(self): |
| path_to_serve = self.path[1:] |
| if self.filename is not None: |
| path_to_serve = self.filename |
| to_serve = os.path.join(os.getcwd(), path_to_serve) |
| with open(to_serve, 'rb') as file_to_serve: |
| self.wfile.write(file_to_serve.read()) |
| |
| |
| def main(argv): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--unix_socket', action='store') |
| parser.add_argument('mode', type=str, nargs='?') |
| parser.add_argument('target', type=str, nargs='?') |
| args = parser.parse_args(argv) |
| |
| if args.mode: |
| if args.mode == 'always' and args.target: |
| Handler.filename = args.target |
| elif args.mode == 'redirect' and args.target: |
| Handler.redirect = args.target |
| elif args.mode == '404': |
| Handler.not_found = True |
| elif args.mode == 'timeout': |
| Handler.simulate_timeout = True |
| elif args.mode == 'auth': |
| Handler.auth = True |
| if args.target: |
| Handler.filename = args.target |
| |
| httpd = None |
| if args.unix_socket: |
| httpd = UnixStreamServer(args.unix_socket, Handler) |
| sys.stderr.write('Serving forever on %s.\n' % args.unix_socket) |
| else: |
| port = None |
| while port is None: |
| try: |
| port = random.randrange(32760, 59760) |
| httpd = TCPServer(('', port), Handler) |
| except socket.error: |
| port = None |
| sys.stdout.write('%d\nstarted\n' % (port,)) |
| sys.stdout.flush() |
| sys.stdout.close() |
| sys.stderr.write('Serving forever on %d.\n' % port) |
| |
| try: |
| httpd.serve_forever() |
| finally: |
| sys.stderr.write('Goodbye.\n') |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv[1:])) |