-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Benjamin Haegenlaeuer
committed
Feb 3, 2020
1 parent
b554ff1
commit c7e5736
Showing
5 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
dist | ||
build | ||
*.egg-info/ | ||
__pycache__/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# ksalf | ||
|
||
[![PyPI](https://img.shields.io/pypi/v/ksalf.svg)](https://pypi.org/project/ksalf/) | ||
|
||
A lightweight experimental HTTP webserver inspired by flask. | ||
**! This is just a experimental (fun) project, please don't use it in production !** | ||
|
||
## Implemtation | ||
Ksalf is a lightweight extension of the [python (base) http server](https://docs.python.org/3/library/http.server.html) . | ||
It provides new feature like **url parsing and html responses**, to the python in-build http server. | ||
Ksalf currently only supports **GET** requests. | ||
The project was inspired by the [flask python project](https://github.com/pallets/flask). | ||
|
||
## Installtion | ||
``` | ||
pip install ksalf | ||
``` | ||
|
||
## Example | ||
``` | ||
from http.server import HTTPServer | ||
from ksalf import HTTPHandler | ||
class Handler(HTTPHandler): | ||
@HTTPHandler.route("/health") | ||
def GET(self): | ||
self.respond(b'healthy') | ||
if __name__ == "__main__": | ||
PORT = 8080 | ||
httpd = HTTPServer(('0.0.0.0', PORT), Handler) | ||
print("Server running on http://localhost:" + str(PORT)) | ||
httpd.serve_forever() | ||
``` | ||
|
||
This example would serve a simple web app on your localhost:8080. | ||
You can register a route with @HTTPHandler.route("/<your_route>"). | ||
*GET* requests always get processed by the `def GET(self):` implementation. | ||
**curl** | ||
``` | ||
curl localhost:8080/health | ||
``` | ||
**Response** | ||
``` | ||
healthy | ||
``` | ||
|
||
|
||
## Future Development | ||
* Implement tests | ||
* Support other request methods than just *GET* | ||
* Advanced URL parsing | ||
* Enhance HTML Responses |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .handler import HTTPHandler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from http.server import BaseHTTPRequestHandler | ||
from http import HTTPStatus | ||
import re | ||
from os import curdir, sep | ||
|
||
class HTTPHandler(BaseHTTPRequestHandler): | ||
endpoints = {} | ||
|
||
def route(route_path = "/"): | ||
""" | ||
Registers a GET route for the handler. | ||
Keyword Arguments: | ||
route_path: request route -> string (default: "/") | ||
""" | ||
def decorate(func): | ||
# Gets called on init | ||
# Registers a function for the given route. | ||
arguments = func.__code__.co_varnames[:func.__code__.co_argcount] | ||
HTTPHandler.endpoints[route_path] = func | ||
def call(self, *args, **kwargs): | ||
# Gets called when the function gets called | ||
# Returns method, which is associated with the requests route | ||
if self.request_path in self.endpoints: | ||
result = self.endpoints[self.request_path](self, *args, **kwargs) | ||
elif self.request_path.endswith(".css"): | ||
f = open(curdir + sep + self.request_path) | ||
self.respond(f.read().encode(), "text/css") | ||
f.close() | ||
return | ||
else: | ||
return | ||
return result | ||
return call | ||
return decorate | ||
|
||
|
||
def do_GET(self): | ||
""" | ||
Gets called on a GET request and parses the url paramters of the request. | ||
It then calls the GET() method. | ||
""" | ||
self.parameters = self.__parse_request() | ||
self.request_path = self.parameters.get("path") | ||
self.GET() | ||
|
||
|
||
def __parse_request(self): | ||
""" | ||
Parses the arguements(after the ?) in the url. | ||
Example: | ||
localhost:8080?name=peter&year=2020 | ||
paramter["name"] = "peter" | ||
paramter["year"] = "2020" | ||
Return: | ||
parameters: arguments -> dict | ||
""" | ||
parameters = {} | ||
splitted_path = self.path.split("?") | ||
parameters["path"] = splitted_path[0] | ||
params = re.findall(r"[\w']+", ' '.join(map(str, splitted_path[1:]))) | ||
if len(params) % 2: | ||
params.pop() | ||
if len(params) > 1: | ||
for i in range(0, len(params), 2): | ||
parameters[params[i]] = params[i+1] | ||
return parameters | ||
|
||
|
||
def respond(self, response_blob, mimetype = "text/html"): | ||
""" Create a http response. | ||
Keyword arguments: | ||
response_blob: content -> bytes | ||
mimetype: Returntype, please specify -> string (default: text/plain) | ||
""" | ||
self.send_response(200) | ||
self.send_header('Content-type', mimetype) | ||
self.end_headers() | ||
self.wfile.write(response_blob) | ||
return | ||
|
||
def GET(self): | ||
""" | ||
Default method for a GET request. | ||
Override with own implementation. | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import setuptools | ||
|
||
with open("README.md", "r") as fh: | ||
long_description = fh.read() | ||
|
||
setuptools.setup( | ||
name="ksalf", | ||
version="0.0.2", | ||
author="Benjamin Haegenlaeuer", | ||
author_email="[email protected]", | ||
description="A lightweight webserver implementation [inspired by flask]", | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
url="https://github.com/Haegi/ksalf", | ||
packages=setuptools.find_packages(), | ||
classifiers=[ | ||
"Programming Language :: Python :: 3", | ||
"License :: OSI Approved :: MIT License", | ||
"Operating System :: OS Independent", | ||
], | ||
python_requires='>=3.6', | ||
) |