NAME
App::MFILE::WWW - Web UI development toolkit with prototype demo app
VERSION
Version 0.143
LICENSE
This software is distributed under the "BSD 3-Clause" license, the text of which can be found in the file named COPYING
in the top-level distro directory. The license text is also reprodued at the top of each source file.
SYNOPSIS
$ man mfile-www
$ mfile-www
$ firefox http://localhost:5001
DESCRIPTION
This distro contains a foundation/framework/toolkit for developing the "front end" portion of web applications.
App::MFILE::WWW is a Plack application that provides a HTTP request-response handler (based on Web::Machine), CSS and HTML source code for an in-browser "screen", and JavaScript code for displaying various "widgets" (menus, forms, etc.) in that screen and for processing user input from within those widgets.
In addition, infrastructure is included (but need not be used) for user authentication, session management, and communication with a backend server via AJAX calls.
Front ends built with App::MFILE::WWW will typicaly be menu-driven, consisting exclusively of fixed-width Unicode text, and capable of being controlled from the keyboard, without the use of a mouse. The overall look-and-feel is reminiscent of the text terminal era.
The distro comes with a prototype (demo) application to illustrate how the various widgets are used.
QUICK START (DEMO)
App::MFILE::WWW can be run as a standalone HTTP server providing a self-contained demo web application, or "web frontend".
Assuming App::MFILE::WWW has been installed properly, this mode of operation can be started by running mfile-www
, as a normal user (even 'nobody'), with no arguments or options:
$ mfile-www
The start-up script will write information about its state to the standard output. This includes the location of its log file, the port where the HTTP server is listening (default is 5001), etc. For a detailed description of what happens when the start-up script is run, see the POD of mfile-www
itself - e.g. "man mfile-www".
DERIVED WWW CLIENTS
When you write your own web frontend using this distro, from App::MFILE::WWW's perspective it is a "derived client" and will be referred to as such in this document.
Derived client operation
In a derived-client scenario, App::MFILE::WWW is basically used as a library, or framework, upon which the "real" application is built.
The derived-client handling is triggered by providing the --ddist
command-line option, i.e.
$ mfile-www --ddist=App-Dochazka-WWW
Where 'App-Dochazka-WWW' refers to the Perl module App::Dochazka::WWW, which is assumed to contain the derived client source code.
So, in the first place it is necessary to create such a Perl module. It should have a sharedir configured and present. One such derived client, App::Dochazka::WWW, is available on CPAN.
IMPLEMENTATION DETAILS
HTTP request-response cycle
The HTTP request-response cycle is implemented as follows:
nginx listens for incoming connections on port 80/443 of the server
When a connection comes in, nginx decrypts it and forwards it to a high-numbered port where a PSGI-compatible HTTP server (such as Starman) is listening
The HTTP server takes the connection and passes it to the Plack middleware. The key middleware component is Plack::Middleware::Session, which assigns an ID to the session, stores whatever data the server-side code needs to associate with the session, links the session to the user's browser via a cookie, and provides the application a hook (in the Plack environment stored in the HTTP request) to access the session data
if the connection is asking for static content (defined as anything in
images/
,css/
, orjs/
), that content is served immediately and the request doesn't even make it into our Perl codeany other path is considered dynamic content and is passed to Web::Machine for processing -- Web::Machine implements the HTTP standard as a state machine
the Web::Machine state machine takes the incoming request and runs it through several functions that are overlayed in App::MFILE::WWW::Resource - an appropriate HTTP error code is returned if the request doesn't make it through the state machine. Along the way, log messages are written to the log.
as part of the state machine, all incoming requests are subject to "authorization" (in the HTTP sense, which actually means authentication). First, the session data is examined to determine if the request belongs to an existing authorized session. If it doesn't, the request is treated as a login/logout attempt -- the session is cleared and control passes to the JavaScript side, which, lacking a currentUser object, displays the login dialog.
once an authorized session is established, there are two types of requests: GET and POST
incoming GET requests happen whenever the page is reloaded - in an authorized session, this causes the main menu to be displayed, but all static content (CSS and JavaScript modules) are reloaded for a "clean slate", as if the user had just logged in.
Note that App::MFILE::WWW pays no attention to the URI - if the user enters a path (e.g. http://mfile.site/some/bogus/path), this will be treated like any other page (re)load and the path is simply ignored.
if the session is expired or invalid, any incoming GET request will cause the login dialog to be displayed.
well-formed POST requests are directed to the
process_post
routine in App::MFILE::WWW::Dispatch. In derived-distro mode, the derived distro must provide its own dispatch module.under ordinary operation, the user will spend 99% of her time interacting with the JavaScript code running in her browser, which will communicate asynchronously as needed with the back-end (which must be implemented separately) via AJAX calls.
DEVELOPMENT NOTES
The App::MFILE::WWW codebase has two parts, or "sides": the "Perl side" and the "JavaScript side". Control passes from the Perl side to the JavaScript side
synchronously whenever the user (re)loads the page
asynchronously whenever the user triggers an AJAX call
JavaScript side
Modular (RequireJS)
The JavaScript code is modular. Each code module has its own file and modules are loaded asynchronously by RequireJS.
Unit testing (QUnit)
The JavaScript code included in this package is set up for unit testing using the QUnit http://qunitjs.com/ library.
UTF-8
In conformance with the JSON standard, all data passing to and from the server are assumed to be encoded in UTF-8. Users who need to use non-ASCII characters should check their browser's settings.
Deployment
To minimize latency, App::MFILE::WWW can be deployed on the same server as the back-end (e.g. App::Dochazka::REST), but this is not required.
PACKAGE VARIABLES
For convenience, the following variables are declared with package scope:
FUNCTIONS
init
Initialization routine - run from bin/mfile-www
, the server startup script. This routine loads configuration parameters from files in the distro and site configuration directories, and sets up logging.