Skip to main content

Sonoma

PyPI version

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

http://127.0.0.1:8888/?testQuery=1

{
    "query": {
        "testQuery": [
            "1"
        ]
    },
    "time_gmt": "Sat, 20 Feb 2021 20:18:51 GMT"
}

Conclusion

  • Adding better documentation soon!

Metadata

Release files for sonoma 1.0.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sonoma 1.0.12
File Size Uploaded
sonoma-1.0.12.tar.gz 9.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sonoma 1.0.12
File Interpreter ABI Platform
sonoma-1.0.12-py3-none-any.whl Python 3 none any Details

Total release size: 18.5 kB

Release files / sonoma-1.0.12.tar.gz

Download URL sonoma-1.0.12.tar.gz
Size 9.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3da022911746924f23f591290d090fa550f21c5d3d89cec3a3e8efc2f6f7b259
BLAKE2b-256 checksum
How to use checksums
9f56e874d6e3cecde2555204194b4dbf312e281f13a203a5c5e34c396029549d
Upload date
Uploaded using Trusted Publishing?
What is 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

Release files / sonoma-1.0.12-py3-none-any.whl

Download URL sonoma-1.0.12-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3fa987cdee5ba5bec33d4a493f652fed2e56146c1a3ea16db902abd485e37ea1
BLAKE2b-256 checksum
How to use checksums
97f4150737ec532042c88a94496102688df6665c44bc5800d9066d20cc174179
Upload date
Uploaded using Trusted Publishing?
What is 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

Release history Release notifications | RSS feed

This release

1.0.12 This release

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page