A simple and fun server framework to avoid using django and big stuff
- Import the module
from pyroboxCore import config, logger, SimpleHTTPRequestHandler as SH_base, DealPostData as DPD, run as run_server
* config: A class containing the configuration of the server. Kindly check the code comments for more info.
* logger: Logger module to log stuffs and also supress the logs.
* SimpleHTTPRequestHandler: A class that inherits from BaseHTTPRequestHandler and has some extra features. This is the main class that you will be using.
* DealPostData: A class that uses the SimpleHTTPRequestHandler class functions to deal with post data.
* run: A function that runs the server.
-
Incase you need to change SimpleHTTPRequestHandler methods or funtionality Create a class that inherits from SimpleHTTPRequestHandler and override the methods you want to change. You can check an example in here
-
Lets make our first server
from http import HTTPStatus
from pyroboxCore import config, logger, SimpleHTTPRequestHandler as SH_base, run as run_server
class SH(SH_base):
"""
Simply inherits from SimpleHTTPRequestHandler
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@SH.on_req('HEAD') # HEAD or GET both requests will be handled by this function
def default_get(self: SH, *args, **kwargs):
"""
Handles all the GET requests
"""
self.send_text(HTTPStatus.OK, "Hello World")
def run():
run_server(handler=SH, port=8080)
# this will run the server in current directory at port 8080
if __name__ == '__main__':
run()
-
So you've seen how it works.
- NOTE THAT The
@SH.on_req
decorator acts as switch case for the request type. So make sure to put default case at the end of handlers tree. Also handle 404 errors in the default case.
- NOTE THAT The
-
Lets spice it up a bit
from http import HTTPStatus
from pyroboxCore import config, logger, SimpleHTTPRequestHandler as SH_base, run as run_server
class SH(SH_base):
"""
Simply inherits from SimpleHTTPRequestHandler
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@SH.on_req('HEAD', url='/') # HEAD or GET both requests will be handled by this function
def index(self: SH, *args, **kwargs):
"""
Handles index page ("/") request only
"""
self.send_text(HTTPStatus.OK, "Hello World")
@SH.on_req('HEAD', url='/test') # @SH.on_req has many more args to handle request url and query string. Check the code comments for more info
def test(self: SH, *args, **kwargs):
"""
Handles requests to "/test" only
"""
self.send_text(HTTPStatus.OK, "This is a test")
# you can also send json data
# self.send_json({"test": "This is a test"})
# or send a file
# self.send_file("path/to/file")
@SH.on_req('HEAD') # anything other than home and /test will raise 404
def default_get(self: SH, *args, **kwargs):
"""
Handles all the other GET requests
"""
self.send_error(HTTPStatus.NOT_FOUND, "Page not found")
def run():
run_server(handler=SH, port=8080)
# this will run the server in current directory at port 8080
if __name__ == '__main__':
run()
- Now lets see how to deal with post data
from http import HTTPStatus
from pyroboxCore import config, logger, SimpleHTTPRequestHandler as SH_base, DealPostData as DPD, run as run_server
class SH(SH_base):
"""
Simply inherits from SimpleHTTPRequestHandler
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@SH.on_req('HEAD')
def default_get(self: SH, *args, **kwargs):
"""
Handles all the GET requests
"""
return self.send_text(HTTPStatus.OK, """
<html>
<head>
<title>Post demo</title>
</head>
<body>
<!-- multipart form -->
<form action="/post_address" method="post" enctype="multipart/form-data">
<!-- text field -->
<label for="text1">Name: </label>
<input type="text" name="text1" placeholder="Enter Name" />
</br>
<label for="text2">Age: </label>
<input type="text" name="text2" placeholder="Enter Age" />
</br>
<input type="submit" value="submit" />
</form>
</body>
</html>
""", content_type="text/html; charset=utf-8")
@SH.on_req('POST')
def default_post(self: SH, *args, **kwargs):
"""
Handles all the POST requests
"""
# you can use the DealPostData class to deal with post data
post = DPD(self)
post.start() # start the post data processing
# this will gather content_length, content_type, boundary from the request headers and reach the end of the headers (and the 1st boundary at line 0)
n = 1
while True:
line = post.get()
# you can also handle form fields using `post.get_part(verify_name=None, varify_msg=None)`
# optional `verify_name` and `verify_msg` args can be used to verify the name of the field and the message
# if not varified, raise `PostError` (this will also cancel the post connection. So you can actually block requests before they even complete)
if line is None:
break
# do something with the line
print(f"Line {n}: {line}")
n += 1
print("The post data is over")
# you can also send a file/text/json response
return self.send_text(HTTPStatus.OK, "<b>Post data received</b>", content_type="text/html; charset=utf-8")
# you can also post process in the function if you just don't want to return anything yet
def run():
run_server(handler=SH, port=8080)
# this will run the server in current directory at port 8080
if __name__ == '__main__':
run()
Check