Better docstrings

This commit is contained in:
Michael Lazar 2020-01-12 20:36:00 -05:00
parent 42a5b6b65b
commit c7f0e1e4fb
2 changed files with 71 additions and 16 deletions

View File

@ -5,30 +5,30 @@
#### Features #### Features
- Added support for python 3.8. - Added support for python 3.8.
- Added a new server diagnostics tool ``jetforce-diagnostics``. - Added a new server diagnostics tool, ``jetforce-diagnostics``.
- Added ability to binding to IPv6 addresses (if supported by your OS): - Added ability to binding to IPv6 addresses (if supported by your OS):
- For IPv4 : --host "0.0.0.0" - For IPv4 : ``--host "0.0.0.0"``
- For IPv6 : --host "::" - For IPv6 : ``--host "::"``
- For IPv4 + IPv6 : --host "" - For IPv4 + IPv6 : ``--host ""``
- Various improvements have been made to the project documentation. - Various improvements have been made to the project documentation.
#### Bugfixes #### Bugfixes
- A URL missing a scheme will now be interpreted as "gemini://". - A URL missing a scheme will now be interpreted as "gemini://".
- A request to the root URL without a trailing slash will now return a 31 - A request to the root URL without a trailing slash will now return a
permanent redirect. ``31 PERMANENT REDIRECT``.
- Requests containing an invalid or unparsable URL format will now return a - Requests containing an invalid or unparsable URL format will now return a
status of 59 Bad Request instead of 50 Permanent Failure. status of ``59 BAD REQUEST`` instead of ``50 PERMANENT FAILURE``.
- Files starting with ``~`` will now be included in directory listings. - Files starting with ``~`` will now be included in directory listings.
- Requests containing an incorrect scheme, hostname, or port will now return a - Requests containing an incorrect scheme, hostname, or port will now return a
53 Proxy Refused instead of a 50 Permanent Failure. ``53 PROXY REFUSED`` instead of a ``50 PERMANENT FAILURE``.
- The port number in the URL (if provided) is now validated against the - The port number in the URL (if provided) is now validated against the
server's port number. server's port number.
- OS errors when attempting to read a file will return a 51 NOT FOUND status - OS errors when attempting to read a file will return a ``51 NOT FOUND``
instead of a 42 CGI Error. This is a precaution to prevent leaking sensitive status instead of a ``42 CGI Error``. This is a precaution to prevent leaking
information about the server's filesystem. sensitive information about the server's filesystem.
- For security, unhandled exceptions now display a generic error message - For security, unhandled exceptions will now display a generic error message
instead of the specific exception string. instead of the plain exception string.
### v0.1.0 (2019-09-22) ### v0.1.0 (2019-09-22)

View File

@ -1,4 +1,37 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
Jetforce, an experimental Gemini server.
Overview
--------
GeminiServer:
An asynchronous TCP server built on top of python's asyncio stream
abstraction. This is a lightweight class that accepts incoming requests,
logs them, and sends them to a configurable request handler to be processed.
GeminiRequestHandler:
The request handler manages the life of a single gemini request. It exposes
a simplified interface to read the request URL and write the gemini response
status line and body to the socket. The request URL and other server
information is stuffed into an ``environ`` dictionary that encapsulates the
request at a low level. This dictionary, along with a callback to write the
response data, and passed to a configurable "application" function or class.
JetforceApplication:
This is a base class for writing jetforce server applications. It doesn't
anything on its own, but it does provide a convenient interface to define
custom server endpoints using route decorators. If you want to utilize
jetforce as a library and write your own server in python, this is the class
that you want to extend. The examples/ directory contains some examples of
how to accomplish this.
StaticDirectoryApplication:
This is a pre-built application that serves files from a static directory.
It provides an "out-of-the-box" gemini server without needing to write any
lines of code. This is what is invoked when you launch jetforce from the
command line.
"""
from __future__ import annotations from __future__ import annotations
import argparse import argparse
@ -150,6 +183,13 @@ class RoutePattern:
class JetforceApplication: class JetforceApplication:
""" """
Base Jetforce application class with primitive URL routing. Base Jetforce application class with primitive URL routing.
This is a base class for writing jetforce server applications. It doesn't
anything on its own, but it does provide a convenient interface to define
custom server endpoints using route decorators. If you want to utilize
jetforce as a library and write your own server in python, this is the class
that you want to extend. The examples/ directory contains some examples of
how to accomplish this.
""" """
def __init__(self): def __init__(self):
@ -216,7 +256,12 @@ class JetforceApplication:
class StaticDirectoryApplication(JetforceApplication): class StaticDirectoryApplication(JetforceApplication):
""" """
Serve a static directory over Gemini. Application for serving static files & CGI over gemini.
This is a pre-built application that serves files from a static directory.
It provides an "out-of-the-box" gemini server without needing to write any
lines of code. This is what is invoked when you launch jetforce from the
command line.
If a directory contains a file with the name "index.gmi", that file will If a directory contains a file with the name "index.gmi", that file will
be returned when the directory path is requested. Otherwise, a directory be returned when the directory path is requested. Otherwise, a directory
@ -388,11 +433,18 @@ class GeminiRequestHandler:
""" """
Handle a single Gemini Protocol TCP request. Handle a single Gemini Protocol TCP request.
The request handler manages the life of a single gemini request. It exposes
a simplified interface to read the request URL and write the gemini response
status line and body to the socket. The request URL and other server
information is stuffed into an ``environ`` dictionary that encapsulates the
request at a low level. This dictionary, along with a callback to write the
response data, and passed to a configurable "application" function or class.
This design borrows heavily from the standard library's HTTP request This design borrows heavily from the standard library's HTTP request
handler (http.server.BaseHTTPRequestHandler). However, I did not make any handler (http.server.BaseHTTPRequestHandler). However, I did not make any
attempts to directly emulate the existing conventions, because Gemini is an attempts to directly emulate the existing conventions, because Gemini is an
inherently simpler protocol than HTTP and much of the boilerplate could be inherently simpler protocol than HTTP and much of the boilerplate could be
removed or slimmed-down. removed.
""" """
TIMESTAMP_FORMAT = "%d/%b/%Y:%H:%M:%S %z" TIMESTAMP_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
@ -551,7 +603,10 @@ class GeminiRequestHandler:
class GeminiServer: class GeminiServer:
""" """
An asynchronous TCP server that understands the Gemini Protocol. An asynchronous TCP server that uses the asyncio stream abstraction.
This is a lightweight class that accepts incoming requests, logs them, and
sends them to a configurable request handler to be processed.
""" """
request_handler_class = GeminiRequestHandler request_handler_class = GeminiRequestHandler