A tiny, programmable http-server crafting-framework that is built with security and simplicity in mind.
Project description
Sonoma
A tiny, programmable http-server crafting-framework that is built with security and simplicity in mind.
Setup
pip install sonoma
Basic Usage
Server
from sonoma import httpServer
server = httpServer('127.0.0.1', 8888)
server.run()
Browser
Hello World!
This is the default webpage for Sonoma/1.0.x.
Basic Usage: Custom Response
Server
from sonoma import defaults, httpServer
server = httpServer('127.0.0.1', 8888)
defaults['defaultResponse'] = """
<!DOCTYPE html><html><head>
<style>html, body{ margin: 0 auto;text-align:center; }</style>
</head><body>
<h1 style=\"text-align:center;\">Hello World!</h1>
<span>This is a modified version of the default webpage for %s.</span>
</body></html>
""" % defaults['serverName']
server.run()
Browser
Hello World!
This is a modified version of the default webpage for Sonoma/1.0.12.
Advanced Usage: Custom Handler
Server
from sonoma import httpServer, defaults, sonomaPrint
from sonoma import setCookie, parseCookies
from http import HTTPStatus
# DEFINES CUSTOM HANDLER
def myHandler(self, REQUEST, CONNECTION):
"""
## Supported Methods:
- GET
- HEAD
"""
# UNPACK "REQUEST" TUPLE
requestStatusLine, requestHeaders, requestBody = REQUEST
# UNPACK CONNECTION TUPLE
client_connection, client_address = CONNECTION
# LOG THE REQUEST TO STDOUT
sonomaPrint("%s -> %s Request: %s" % (str(self.vector), str(client_address), str(requestStatusLine),))
#
# RESOLVE THE REQUEST METHOD AND RESPOND ACCORDINGLY:
#
# SERVE GET
if requestStatusLine.split()[0].lower() == "get":
# GET OUR DEFAULT HEADERS + STATUS LINE
responseStatusLine, responseHeaders = self.httpHeaders(HTTPStatus.OK, contentType="html")
# CREATE A LIST OF STRINGS OF EACH REQUEST HEADER FOR USE IN OUR EXAMPLE
headerStrings = ["%s: %s\n" % (header[0], header[1]) for header in requestHeaders]
# HERES HOW WE CAN WORK WITH COOKIES, BOTH REQUEST AND RESPONSE:
requestCookies = parseCookies(requestHeaders) # GET REQUEST COOKIES
#sonomaPrint(requestCookies)
setCookie(responseHeaders, "cookieName", "cookieValue", ['Secure', 'HttpOnly']) # SET A RESPONSE COOKIE
#sonomaPrint(responseHeaders)
# CREATE A CUSTOM RESPONSE
responseBody = ("""
<!DOCTYPE html><html><head>
<style>html, body{ margin: 0 auto;text-align:center; }</style>
</head><body>
<h1 style=\"text-align:center;\">Hello World!</h1>
<span>This is a custom response from %s.</span>
<br/><br/>
<span>Request Headers:</span>
<br/>
<textarea cols="100" rows="100" style="width: 75%%;height: 100%%;margin: 0 auto;">%s</textarea>
</body></html>
""" % (defaults['serverName'], "".join(headerStrings))).encode()
return (responseStatusLine, responseHeaders, responseBody)
# RESPOND WITH 405 STATUS - METHOD NOT ALLOWED
else:
responseStatusLine, responseHeaders = self.httpHeaders(HTTPStatus.METHOD_NOT_ALLOWED, contentType="text")
return (responseStatusLine, responseHeaders, "")
# INITIALIZE THE SERVER BUT SET OUR CUSTOM HANDLER BEFORE RUNNING.
server = httpServer('127.0.0.1', 8888)
server.set_handler(myHandler)
server.run()
Browser
Advanced Handler: JSON API
Server
from sonoma import httpServer, HTTPStatus, sonomaPrint, serverGmtTime
from json import dumps
from urllib.parse import urlparse, parse_qs
# DEFINES CUSTOM HANDLER
def myHandler(self, REQUEST, CONNECTION):
"""
## Supported Methods:
- GET
- HEAD
"""
# UNPACK "REQUEST" TUPLE
requestStatusLine, requestHeaders, requestBody = REQUEST
# UNPACK CONNECTION TUPLE
client_connection, client_address = CONNECTION
# LOG THE REQUEST TO STDOUT
sonomaPrint("%s -> %s Request: %s" % (str(self.vector), str(client_address), str(requestStatusLine),))
#
# RESOLVE THE REQUEST METHOD AND RESPOND ACCORDINGLY:
#
# SERVE GET-JSON
if requestStatusLine.split()[0].lower() == "get":
# GET OUR JSON HEADERS + STATUS LINE
responseStatusLine, responseHeaders = self.httpHeaders(HTTPStatus.OK, contentType="json")
# PARSE THE GET QUERY
try:
clientQuery = parse_qs(urlparse(requestStatusLine.split()[1]).query)
except:
# IF QUERY CANNOT BE PARSED THEN RESPOND WITH AN ERROR MESSAGE
return (responseStatusLine, responseHeaders, dumps({'error': 'Invalid url query!'}))
# GET TIME FOR ONE OF OUR SERVERSIDE PROCESSING EXAMPLES
tstamp = serverGmtTime()
responseBody = dumps({
'query': clientQuery,
'time_gmt': tstamp
}, indent=4)
return (responseStatusLine, responseHeaders, responseBody)
# RESPOND WITH 405 STATUS - METHOD NOT ALLOWED
else:
responseStatusLine, responseHeaders = self.httpHeaders(HTTPStatus.METHOD_NOT_ALLOWED, contentType="text")
return (responseStatusLine, responseHeaders, "")
# INITIALIZE THE SERVER BUT SET OUR CUSTOM HANDLER BEFORE RUNNING.
server = httpServer('127.0.0.1', 8888)
server.set_handler(myHandler)
server.run()
Browser
{
"query": {
"testQuery": [
"1"
]
},
"time_gmt": "Sat, 20 Feb 2021 20:18:51 GMT"
}
Conclusion
- Adding better documentation soon!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
sonoma-1.0.12.tar.gz
(9.7 kB
view details)
Built Distribution
File details
Details for the file sonoma-1.0.12.tar.gz
.
File metadata
- Download URL: sonoma-1.0.12.tar.gz
- Upload date:
- Size: 9.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.56.1 CPython/3.9.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3da022911746924f23f591290d090fa550f21c5d3d89cec3a3e8efc2f6f7b259 |
|
MD5 | b347f2c5adbfedaae23bdb0d5f0edb0e |
|
BLAKE2b-256 | 9f56e874d6e3cecde2555204194b4dbf312e281f13a203a5c5e34c396029549d |
File details
Details for the file sonoma-1.0.12-py3-none-any.whl
.
File metadata
- Download URL: sonoma-1.0.12-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.56.1 CPython/3.9.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3fa987cdee5ba5bec33d4a493f652fed2e56146c1a3ea16db902abd485e37ea1 |
|
MD5 | 52ed5c7dd873f49ec5a4b78509f95089 |
|
BLAKE2b-256 | 97f4150737ec532042c88a94496102688df6665c44bc5800d9066d20cc174179 |