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