NAME App::MFILE::WWW - Generic web front-end with demo app VERSION Version 0.088 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. DESCRIPTION This distro contains a generic framework for developing web front-ends to REST resources. The framework consists of a web server based on Plack and Web::Machine, CSS and HTML for the "app frame" (on-screen area where the application's "screens" are displayed), and "widgets" for defining the application's login dialog, menus, forms, and actions. For illustration, the distro contains a demo app that authenticates against App::Dochazka::REST and contains a single menu, a simple form, and a sample action. INTRODUCTION The full stack, of which App::MFILE::WWW is a part, consists of the following components: * Database engine For storing application data. * Perl DBI For interfacing between the Perl code and the database engine. * REST server A REST server, such as App::Dochazka::REST, implements a data model and provides a HTTP interface to that model. * optional CLI client/frontend An optional Command Line Interface (frontend) can provide a command line interface to the REST server. * WWW client/frontend The WWW frontend, built based on this distro, is a web server that serves HTML, CSS, and JavaScript code to users to provide them with a menu-driven "browser experience" of the application. Conceptually, the clients act as proxies between the user and the REST server. Taking this one step further, the REST server itself is a proxy between the client and the database engine. The philosophy behind this RESTful design is that you, the user, have the freedom and the flexibility to write your own client, on any platform, in any language -- however you see fit. From a technical perspective, the strict separation between the server and clients makes the application as a whole more robust. 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/', 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. * 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 assumed to be AJAX calls and are directed to the `process_post' routine, which first examines the request body, which must adhere to a simple structure: { method: "GET", path: "employee/current", body: { ... } } where 'method' is any HTTP method accepted by the REST server, 'path' is a valid path to a REST server resource, and 'body' is the content body to be sent in the HTTP request to the REST server. Provided the request is properly authorized and the body is well-formed, the request is forwarded to the REST server via the App::MFILE package's `rest_req' routine and the REST server's response is sent back to the user's browser, where it is processed by the JavaScript code. * 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 REST server via AJAX calls. Development notes 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.