DAIRGram Python integrated web server project
OverviewDAIRGram is a http/https server with the objective of making combining Python and html as convenient as embedding PHP in html.
Hello programLet's construct a web page which we invoke by calling http://dairgram.com/hello.py. We need to create a file called hello.py in the server's WWW/../../Identity/www/ directory with an entry point of hello:
def hello(): return "<html><body>Hello DAIRGram</body></html>"This is the entire page, not a page fragment. This simple example takes advantage of default behavior, omitting an object parameter passed to hello and an http status code. The example could be written equivalently as:
def hello(wwwob): return 200, "<html><body>Hello DAIRGram</body></html>"Normally, Python does not allow for omitting parameters on call or return. DAIRGram tries the call to hello with each of 0 and 1 parameters, making the passing of the object parameter optional. It tests to resolve the return from hello into 1 or 2 parameters, making the return of the 200 http status code optional as well.
StructuringIn the hello program, we created a one-line web program. A more practical structure allows for larger bodies of html. Let us recast our Hello Program into a structure which is scalable:
mysite = "DAIRGram" def timestamp(wwwob): import time return time.asctime() ht = """ <html><body> Hello #(mysite)#. Today is #(timestamp)# </body></html> """ def hello(wwwob): return 200, wwwob.eval_proto(ht)The html is introduced as a single block of text between triple quotes. It could just as well have been read into the ht variable from a file.
The wwwob.eval_proto(ht) wraps ht in decorative chrome (see below) and makes substitutions of "#(...)#" marked variables.
Substitutions into the ht text string are made from the module by surrounding names used in the module with "#(...)#". The substitution for simple variable #(mysite)# is fairly obvious with the text value being substituted in place. The Python variable need not be a string. It merely must be capable of being evaluated as a string.
The substitution of routine #(timestamp)# is more involved. First, timestamp must be a 0 or 1 parameter routine. If 1 parameter, it will be passed the so-far undefined wwwob object parameter.
Suppose we have used a name not defined in the module, such as #(not_defined)# in the html prototype? or used unbalanced "#(...)#"? The wwwob.eval_proto routine finds the global names and then substitutes global name value for #(...)#.
Thus, no substitution occurs if either "#(" or ")#" end is missing or the name is not defined globally in the module. This substitution or non-substitution is error free (never generates an error): we are not parsing the html prototype but merely running through the identified module global names making substitutions. Having a global "python_name" in Python name space does not require a "#(python_name)#" substitution in the html. Multiple occurrences of "#(...)#" in the html are all substituted.
The wwwob objectThere is a separate wwwob object for each connected remote IPV4 IP address. The object is persistent during the time period when the server is running and is reset at boot time for the server.
One intended use of wwwob is as a session object. For example, when you identify a user, set a variable such as wwwob.user_name and this name is available throughout the session.
A second intended use of wwwob is as a object oriented replacement for Common Gateway Interface (CGI) provided by other web servers. For example, the remote ip address used to distinguish sessions is at wwwob.htob.rmtip. A more comprehensive discussion is (under development) at wwwob attributes and methods
A conventional web server architecture offers an isolated interface and the server program synthesizes a session cookie. The persistent wwwob replaces the cookie. Persistence is built in.
Window ChromeChrome in a window context (not the browser) refers to the wrapper around the client area of the window. On the page you are reading now, the client area starts with the headline "#headline#" and consists of the content in the light blue area. The rest of the page is chrome.
The chrome for any page resides at approximately lines 20 to 140 or so in the dairgram.py module. You may edit to suit your needs.
PicturesDAIRGram simplifies html by exporting its complexity to Python. Suppose we have a picture called pict_14.png. To display that in html requires specifying "<a>" and "<img>" tags with complex parameters. If a caption exists, the entire thing normally is wrapped in "<table>" or "<div>". This often spans several lines of coding and makes reading the html difficult.
With DAIRGram, you might drop the string "#(pict_14)#" into the html prototype and then have the pict_14(wwwob) routine generate all this html complexity. Alternatively, define the pict_14 string as a Python string, allowing you to build up the html as a text string with embedded objects. This makes building up and isolating html mistakes easier.
To aid the conjectured pict_14(wwwob) routine in generating html, here is the Python code handling the "#(dennis)#" in this page's prototype
def dennis(wwwob): caption = "I am Dennis Reinhardt, developer of DAIRGram. " ht = wwwob.pic_frame("dennis.png", caption, align="right", valign="top") return ht
pic_frame takes as arguments the file name and caption with optional positioning parameters.
DAIRGram searches out file locations within the server's file system so it is not necessary (or permitted) to specify directory path. You can allocate image files within server's file system using whatever structure helps you organize them.
If two files share the same name despite being in different directory paths, it is undefined which one will be discovered first and used. Best practice is give every file a unique name.