App::MFILE::WWW - Web UI development toolkit with prototype demo app
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.
$ man mfile-www
$ firefox http://localhost:5001
This distro contains a foundation/framework/toolkit for developing the "front end" portion of web applications.
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.
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:
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".
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.
In a derived-client scenario, App::MFILE::WWW serves as the foundation 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.
synchronously whenever the user (re)loads the page
asynchronously whenever the user triggers an AJAX call
The HTTP request-response cycle implemented by the Perl side is designed to work approximately like this:
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 embedded 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/, or js/), that content is served immediately and the request doesn't even make it into our Perl code
any 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.
once an authorized session is established, there are two types of requests: GET and POST
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.
Developing a front-end application with App::MFILE::WWW currently assumes that you, the developer, will want to use RequireJS, jQuery, and QUnit.
In addition to the above, App::MFILE::WWW provides a number of primitives, also referred to as "targets", that can be used to quickly slap together a web application. The next chapter explains what these widgets are and how to use them.
The daction primitive is a generalized widget that can do anything.
The dbrowser primitive is like dform, except that it displays a set of data objects and enables the user to "browse" the dataset using arrow keys. Like dform, the primitive includes "miniMenu" functionality through which the user can potentially trigger actions that take the current object as input.
The dcallback primitive is useful for cases when none of the other primitives are appropriate for displaying a given type of object, and no interactivity is needed beyond that provided by miniMenu. The dcallback primitive writes the target title and miniMenu to the screen, along with a "dcallback" div in between, which it populates by calling the callback function. Since the callback function part of the target definition, it can be app-specific.
The dform primitive is used to implement forms consisting of read-only fields (for viewing data), read-write fields (for entering data), or a combination of both. A "miniMenu" can be defined, allowing the user to trigger actions that take the current object as input.
The dmenu primitive is used to implement menus.
The dnotice primitive takes an HTML string and displays it. The same functionality can be accomplished with a daction, of course, but using the dnotice primitive ensures that the notice will have the same "look and feel" as the other widgets.
The drowselect primitive takes an array of strings, displays them vertically as a list, and allows the user to choose one and perform an action on it. Actions are defined via a miniMenu. The currently-selected item is displayed in reverse-video.
The dtable primitive is similar to dbrowser in that it takes a set of objects and allows the user to choose one and perform actions on it via a miniMenu. Unlike dbrowser, however, it display the objects in table form. The currently-selected object is displayed in reverse video.
The tests are implemented using QUnit. A good source of practical advise on the use of QUnit is the QUnit Cookbook, available here:
The QUnit API itself is documented here:
To add a new test case, go to the appropriate tests/ directory (in mfile-www core, in the mfile-www demo app, or in your derived application, as appropriate) and create a js file (use one of the other tests/*.js files as a model). Then add this file to the test.js file in the parent directory.
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.
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.
For convenience, the following variables are declared with package scope:
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.
FIXME: This code could be moved into the startup script.
To install App::MFILE::WWW, copy and paste the appropriate command in to your terminal.
perl -MCPAN -e shell
For more information on module installation, please visit the detailed CPAN module installation guide.