Revert changes
[PyWWW-Get.git] / pyhttpserv.py
blobe582cb629781a52812b4d008a464be1c7b2b0a76
1 #!/usr/bin/env python
3 '''
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the Revised BSD License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 Revised BSD License for more details.
12 Copyright 2016-2023 Game Maker 2k - https://github.com/GameMaker2k
13 Copyright 2016-2023 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
15 $FileInfo: pyhttpserv.py - Last Update: 10/5/2023 Ver. 2.0.2 RC 1 - Author: cooldude2k $
16 '''
18 import os
19 import argparse
20 import gzip
21 import zlib
22 import bz2
24 havebrotli = False
25 try:
26 import brotli
27 havebrotli = True
28 except ImportError:
29 havebrotli = False
30 havezstd = False
31 try:
32 import zstandard
33 havezstd = True
34 except ImportError:
35 havezstd = False
36 havelzma = False
37 try:
38 import lzma
39 havelzma = True
40 except ImportError:
41 havelzma = False
43 __program_name__ = "PyHTTPServer"
44 __program_alt_name__ = "PyHTTPServer"
45 __program_small_name__ = "httpserver"
46 __project__ = __program_name__
47 __project_url__ = "https://github.com/GameMaker2k/PyWWW-Get"
48 __version_info__ = (2, 0, 2, "RC 1", 1)
49 __version_date_info__ = (2023, 10, 5, "RC 1", 1)
50 __version_date__ = str(__version_date_info__[0])+"."+str(__version_date_info__[
51 1]).zfill(2)+"."+str(__version_date_info__[2]).zfill(2)
52 __revision__ = __version_info__[3]
53 __revision_id__ = "$Id$"
54 if(__version_info__[4] is not None):
55 __version_date_plusrc__ = __version_date__ + \
56 "-"+str(__version_date_info__[4])
57 if(__version_info__[4] is None):
58 __version_date_plusrc__ = __version_date__
59 if(__version_info__[3] is not None):
60 __version__ = str(__version_info__[0])+"."+str(__version_info__[1])+"."+str(
61 __version_info__[2])+" "+str(__version_info__[3])
62 if(__version_info__[3] is None):
63 __version__ = str(
64 __version_info__[0])+"."+str(__version_info__[1])+"."+str(__version_info__[2])
66 parser = argparse.ArgumentParser(
67 description="Simple HTTP Server in Python.", conflict_handler="resolve", add_help=True)
68 parser.add_argument("-V", "--version", action="version",
69 version=__program_name__+" "+__version__)
70 parser.add_argument("-e", "--enablessl",
71 action="store_true", help="Enable SSL")
72 parser.add_argument("-k", "--sslkeypem", default=None,
73 help="specify a custom user agent")
74 parser.add_argument("-c", "--sslcertpem", default=None,
75 help="specify a custom referer, use if the video access")
76 parser.add_argument("-p", "--servport", type=int, default=8080,
77 help="specify a file name for output")
78 getargs = parser.parse_args()
80 enablessl = getargs.enablessl
81 sslkeypem = getargs.sslkeypem
82 sslcertpem = getargs.sslcertpem
83 servport = int(getargs.servport)
84 if(isinstance(servport, int)):
85 if(servport < 1 or servport > 65535):
86 servport = 8080
87 elif(isinstance(servport, str)):
88 if(servport.isnumeric()):
89 servport = int(servport)
90 if(servport < 1 or servport > 65535):
91 servport = 8080
92 else:
93 servport = 8080
94 else:
95 servport = 8080
96 if(enablessl):
97 if(sslkeypem is not None and
98 (not os.path.exists(sslkeypem) or not os.path.isfile(sslkeypem))):
99 sslkeypem = None
100 enablessl = False
101 if(sslcertpem is not None and
102 (not os.path.exists(sslkeypem) or not os.path.isfile(sslkeypem))):
103 sslcertpem = None
104 enablessl = False
105 pyoldver = True
106 try:
107 from BaseHTTPServer import HTTPServer
108 from SimpleHTTPServer import SimpleHTTPRequestHandler
109 from urlparse import parse_qs
110 from Cookie import SimpleCookie
111 except ImportError:
112 from http.server import SimpleHTTPRequestHandler, HTTPServer
113 from urllib.parse import parse_qs
114 from http.cookies import SimpleCookie
115 pyoldver = False
116 if(enablessl and
117 (sslkeypem is not None and (os.path.exists(sslkeypem) and os.path.isfile(sslkeypem))) and
118 (sslcertpem is not None and (os.path.exists(sslkeypem) and os.path.isfile(sslkeypem)))):
119 import ssl
120 # HTTP/HTTPS Server Class
123 class CustomHTTPRequestHandler(SimpleHTTPRequestHandler):
124 def compress_content(self, content):
125 """Compress content using gzip or deflate depending on Accept-Encoding header."""
126 accept_encoding = self.headers.get('Accept-Encoding', '')
127 accept_encoding = None
128 if 'gzip' in accept_encoding:
129 self.send_header('Content-Encoding', 'gzip')
130 compressed_content = gzip.compress(content.encode('utf-8'))
131 self.send_header('Content-Length', len(compressed_content))
132 return compressed_content
133 elif 'deflate' in accept_encoding:
134 self.send_header('Content-Encoding', 'deflate')
135 compressed_content = zlib.compress(content.encode('utf-8'))
136 self.send_header('Content-Length', len(compressed_content))
137 return compressed_content
138 elif 'br' in accept_encoding:
139 self.send_header('Content-Encoding', 'br')
140 compressed_content = brotli.compress(content.encode('utf-8'))
141 self.send_header('Content-Length', len(compressed_content))
142 return compressed_content
143 elif 'zstd' in accept_encoding:
144 self.send_header('Content-Encoding', 'zstd')
145 compressed_content = zstandard.compress(content.encode('utf-8'))
146 self.send_header('Content-Length', len(compressed_content))
147 return compressed_content
148 elif 'lzma' in accept_encoding:
149 self.send_header('Content-Encoding', 'lzma')
150 compressed_content = lzma.compress(content.encode('utf-8'))
151 self.send_header('Content-Length', len(compressed_content))
152 return compressed_content
153 elif 'xz' in accept_encoding:
154 self.send_header('Content-Encoding', 'xz')
155 compressed_content = lzma.compress(content.encode('utf-8'))
156 self.send_header('Content-Length', len(compressed_content))
157 return compressed_content
158 else:
159 self.send_header('Content-Length', len(content))
160 return content.encode('utf-8')
161 return content.encode()
163 def display_info(self):
164 # Setting headers for the response
165 self.send_response(200)
166 self.send_header('Content-type', 'text/plain')
167 # Set a sample cookie in the response;
168 self.send_header('Set-Cookie', 'sample_cookie=sample_value; Path=/;')
169 self.end_headers()
170 # Displaying request method
171 response = 'Method: {}\n'.format(self.command)
172 response += 'Path: {}\n'.format(self.path)
173 # Displaying all headers
174 headers_list = ["{}: {}".format(
175 key.title(), self.headers[key]) for key in self.headers]
176 response += '\nHeaders:\n' + '\n'.join(headers_list) + '\n'
177 # Extract and display cookies from headers
178 if 'Cookie' in self.headers:
179 response += '\nCookies:\n'
180 cookies = SimpleCookie(self.headers['Cookie'])
181 for key, morsel in cookies.items():
182 response += '{}: {}\n'.format(key, morsel.value)
183 # Displaying GET parameters (if any)
184 if self.command == 'GET':
185 query = self.path.split('?', 1)[-1]
186 params = parse_qs(query)
187 if params:
188 response += '\nGET Parameters:\n'
189 for key, values in params.items():
190 response += '{}: {}\n'.format(key, ', '.join(values))
191 # Sending the response
192 self.wfile.write(self.compress_content(response))
193 # Get Method
195 def do_GET(self):
196 self.display_info()
197 # Post Method
199 def do_POST(self):
200 if 'Transfer-Encoding' in self.headers and self.headers['Transfer-Encoding'] == 'chunked':
201 post_data = ''
202 while True:
203 chunk_size_line = self.rfile.readline().decode('utf-8')
204 chunk_size = int(chunk_size_line, 16)
205 if chunk_size == 0:
206 self.rfile.readline()
207 break
208 chunk_data = self.rfile.read(chunk_size).decode('utf-8')
209 post_data += chunk_data
210 self.rfile.readline()
211 else:
212 content_length = int(self.headers['Content-Length'])
213 post_data = self.rfile.read(content_length).decode('utf-8')
214 params = parse_qs(post_data)
215 response = 'POST Parameters:\n'
216 for key, values in params.items():
217 response += '{}: {}\n'.format(key, ', '.join(values))
218 self.send_response(200)
219 self.send_header('Content-type', 'text/plain')
220 self.send_header('Set-Cookie', 'sample_cookie=sample_value; Path=/;')
221 self.end_headers()
222 self.wfile.write(self.compress_content(response))
225 # Start Server Forever
226 if __name__ == "__main__":
227 server_address = ('', int(servport))
228 httpd = HTTPServer(server_address, CustomHTTPRequestHandler)
229 if(enablessl and sslkeypem is not None and sslcertpem is not None):
230 httpd.socket = ssl.wrap_socket(httpd.socket,
231 keyfile=sslkeypem, certfile=sslcertpem, server_side=True)
232 if(enablessl):
233 print("Server started at https://localhost:"+str(servport))
234 else:
235 print("Server started at http://localhost:"+str(servport))
236 httpd.serve_forever()