blob: 1b97e780f6491dd8aefe96685a12a1c568ad86a6 [file] [log] [blame]
#!/usr/bin/env python3
# This script acts as a stateful proxy for retrieving files. When the state is set to
# offline, it simulates a network error with a nonsense response.
import os
import sys
import tempfile
from datetime import datetime
from portabilityLayer import get_state, set_state
from urllib.parse import parse_qs
query = parse_qs(os.environ.get('QUERY_STRING', ''), keep_blank_values=True)
test = query.get('test', [None])[0]
command = query.get('command', [None])[0]
if test is None:
sys.stdout.write(
'status: 500\r\n'
'Content-Type: text/html\r\n\r\n'
'test parameter must be specified for a unique test name\n'
)
sys.exit(0)
def temp_path_base():
return os.path.join(tempfile.gettempdir(), test)
state_file = temp_path_base() + '-state'
def generate_no_cache_http_header():
sys.stdout.write(
'Expires: Thu, 01 Dec 2003 16:00:00 GMT\r\n'
'Cache-Control: no-cache, no-store, must-revalidate\r\n'
'Pragma: no-cache\r\n'
)
def content_type(path):
return {
'html': 'text/html',
'manifest': 'text/cache-manifest',
'js': 'text/javascript',
'xml': 'application/xml',
'xhtml': 'application/xhtml+xml',
'svg': 'application/svg+xml',
'xsl': 'application/xslt+xml',
'gif': 'image/gif',
'jpg': 'image/jpeg',
'png': 'image/png'
}.get(path.split('.')[-1], 'text/plain')
def generate_response(path):
state = get_state(state_file)
if state == 'Offline':
# Simulate a network error by replying with a nonsense response.
sys.stdout.write(
'status: 307\r\n'
'Location: {}\r\n\r\n' # Redirect to self.
'Intentionally incorrect response.'.format(os.environ.get('REQUEST_URI', ''))
)
else:
# A little securuty checking can't hurt.
if '..' in path:
sys.stdout.write('Content-Type: text/html\r\n\r\n')
sys.exit(0)
if len(path) > 0 and path[0] == '/':
path = '..' + path
if 'allow-caching' not in query.keys():
generate_no_cache_http_header()
if os.path.isfile(path):
sys.stdout.write(
'Last-Modified: {} GMT\r\n'
'Content-Type: {}\r\n\r\n'.format(datetime.utcfromtimestamp(os.stat(path).st_mtime).strftime('%a, %d %b %Y %H:%M:%S'), content_type(path))
)
with open(path, 'rb') as open_file:
sys.stdout.flush()
sys.stdout.buffer.write(open_file.read())
else:
sys.stdout.write('status: 404\r\n\r\n')
def handle_increate_resource_count_command(path):
resource_count_file = temp_path_base() + '-count'
resource_count = get_state(resource_count_file)
pieces = resource_count.split(' ')
count = 0
if len(pieces) == 2 and pieces[0] == path:
count = 1 + int(pieces[1])
else:
count = 1
set_state(resource_count_file, '{} {}'.format(path, count))
generate_response(path)
def handle_reset_resource_count_command():
resource_count_file = temp_path_base() + '-count'
set_state(resource_count_file, '0')
generate_no_cache_http_header()
sys.stdout.write('status: 200\r\n\r\n')
def handle_get_resource_count_command(path):
resource_count_file = temp_path_base() + '-count'
resource_count = get_state(resource_count_file)
pieces = resource_count.split(' ')
generate_no_cache_http_header()
sys.stdout.write('status: 200\r\n\r\n')
if len(pieces) == 2 and pieces[0] == path:
sys.stdout.write(str(pieces[1]))
else:
sys.stdout.write('0')
def handle_start_resource_requests_log():
resource_log_file = temp_path_base() + '-log'
set_state(resource_log_file, '')
sys.stdout.write('Content-Type: text/html\r\n\r\n')
def handle_get_resource_requests_log():
resource_log_file = temp_path_base() + '-log'
generate_no_cache_http_header()
sys.stdout.write('Content-Type: text/html\r\n\r\n')
with open(resource_log_file, 'r') as open_file:
sys.stdout.write(open_file.read())
def handle_log_resource_request(path):
resource_log_file = temp_path_base() + '-log'
new_data = '\n' + path
with open(resource_log_file, 'a') as open_file:
open_file.write(new_data)
sys.stdout.write('Content-Type: text/html\r\n\r\n')
if command is not None:
if command == 'connect':
set_state(state_file, 'Online')
sys.stdout.write('Content-Type: text/html\r\n\r\n')
elif command == 'disconnect':
set_state(state_file, 'Offline')
sys.stdout.write('Content-Type: text/html\r\n\r\n')
elif command == 'increase-resource-count':
handle_increate_resource_count_command(query.get('path', [''])[0])
elif command == 'reset-resource-count':
handle_reset_resource_count_command()
elif command == 'get-resource-count':
handle_get_resource_count_command(query.get('path', [''])[0])
elif command == 'start-resource-request-log':
handle_start_resource_requests_log()
elif command == 'lear-resource-request-log':
handle_start_resource_requests_log()
elif command == 'get-resource-request-log':
handle_get_resource_requests_log()
elif command == 'log-resource-request':
handle_log_resource_request(query.get('path', [''])[0])
else:
sys.stdout.write(
'Content-Type: text/html\r\n\r\n'
'Unknown command: {}\n'.format(command)
)
sys.exit(0)
else:
request_path = query.get('path', [''])[0]
generate_response(request_path)