Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Haegenlaeuer committed Feb 3, 2020
1 parent b554ff1 commit c7e5736
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
build
*.egg-info/
__pycache__/
54 changes: 54 additions & 0 deletions README.md
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
1 change: 1 addition & 0 deletions ksalf/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .handler import HTTPHandler
90 changes: 90 additions & 0 deletions ksalf/handler.py
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
22 changes: 22 additions & 0 deletions setup.py
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',
)

0 comments on commit c7e5736

Please sign in to comment.