Project

General

Profile

Download (3.82 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / test / server.py @ 6c69435c

1
# Copyright (C) 2021 jahoti <jahoti@tilde.team>
2
# Licensing information is collated in the `copyright` file
3

    
4
"""
5
A modular "virtual network" proxy,
6
wrapping the classes in proxy_core.py
7
"""
8

    
9
from proxy_core import *
10
from urllib.parse import parse_qs
11

    
12
internet = {} # Add info here later
13
mime_types = {
14
	"7z": "application/x-7z-compressed",	"oga": "audio/ogg",
15
	"abw": "application/x-abiword",		"ogv": "video/ogg",
16
	"arc": "application/x-freearc",		"ogx": "application/ogg",
17
	"bin": "application/octet-stream",	"opus": "audio/opus",
18
	"bz": "application/x-bzip",		"otf": "font/otf",
19
	"bz2": "application/x-bzip2",		"pdf": "application/pdf",
20
	"css": "text/css",			"png": "image/png",
21
	"csv": "text/csv",			"sh": "application/x-sh",
22
	"gif": "image/gif",			"svg": "image/svg+xml",
23
	"gz": "application/gzip",		"tar": "application/x-tar",
24
	"htm": "text/html",			"ts": "video/mp2t",
25
	"html": "text/html",			"ttf": "font/ttf",
26
	"ico": "image/vnd.microsoft.icon",	"txt": "text/plain",
27
	"js": "text/javascript",		"wav": "audio/wav",
28
	"jpeg": "image/jpeg",			"weba": "audio/webm",
29
	"jpg": "image/jpeg",			"webm": "video/webm",
30
	"json": "application/json",		"woff": "font/woff",	
31
	"mjs": "text/javascript",		"woff2": "font/woff2",
32
	"mp3": "audio/mpeg",			"xhtml": "application/xhtml+xml",
33
	"mp4": "video/mp4",			"zip": "application/zip",
34
	"mpeg": "video/mpeg",
35
	"odp": "application/vnd.oasis.opendocument.presentation",
36
	"ods": "application/vnd.oasis.opendocument.spreadsheet",
37
	"odt": "application/vnd.oasis.opendocument.text",
38
	"xml": "application/xml" # text/xml if readable from casual users
39
}
40

    
41
class RequestHijacker(ProxyRequestHandler):
42
	certdir = global_certdir
43
	
44
	def handle_request(self, req_body):
45
		path_components = self.path.split('?', maxsplit=1)
46
		path = path_components[0]
47
		try:
48
			# Response format: (status_code, headers (dict. of strings),
49
			#       body as bytes or filename containing body as string)
50
			if path in internet:
51
				info = internet[path]
52
				if type(info) == tuple:
53
					status_code, headers, body_file = info
54
					if type(body_file) == str:
55
						if 'Content-Type' not in headers and '.' in body_file:
56
							ext = body_file.rsplit('.', maxsplit=1)[-1]
57
							if ext in mime_types:
58
								headers['Content-Type'] = mime_types[ext]
59
							
60
						with open(body_file, mode='rb') as f:
61
							body_file = f.read()
62
						
63
				else:
64
					# A function to evaluate to get the response
65
					get_params, post_params = {}, {}
66
					if len(path_components) == 2:
67
						get_params = parse_qs(path_components[1])
68
					
69
					# Parse POST parameters; currently only supports
70
					# application/x-www-form-urlencoded
71
					if req_body:
72
						post_params = parse_qs(req_body.encode())
73

    
74
					status_code, headers, body_file = info(self.command, get_params, post_params)
75
					if type(body_file) == str:
76
						body_file = body_file.encode()
77
			
78
				if type(status_code) != int or status_code <= 0:
79
					raise Exception('Invalid status code %r' % status_code)
80
				
81
				for header, header_value in headers.items():
82
					if type(header) != str:
83
						raise Exception('Invalid header key %r' % header)
84
					
85
					elif type(header_value) != str:
86
						raise Exception('Invalid header value %r' % header_value)
87
			else:
88
				status_code, headers = 404, {'Content-Type': 'text/plain'}
89
				body_file = b'Handler for this URL not found.'
90
		
91
		except Exception as e:
92
			status_code, headers, body_file = 500, {'Content-Type': 'text/plain'}, b'Internal Error:\n' + repr(e).encode()
93
		
94
		headers['Content-Length'] = str(len(body_file))
95
		self.send_response(status_code)
96
		for header, header_value in headers.items():
97
			self.send_header(header, header_value)
98
		
99
		self.end_headers()
100
		self.wfile.write(body_file)
101
		
102

    
103

    
104
def do_an_internet(certdir, port):
105
	"""Start up the proxy/server"""
106
	global global_certdir
107
	global_certdir = certdir
108
	
109
	httpd = ThreadingHTTPServer(('', port), RequestHijacker)
110
	httpd.serve_forever()
(4-4/4)