Check out the Red programming language from the same author
Rsp /

Webapp

What is a webapp?

A webapp is an application container for RSP scripts. It is a way to group together some RSP scripts and static files, and provide them with several useful services. A webapp is defined in the configuration file, in Host sections. It basically associates a virtual path with a root folder in the filesystem, everything inside that folder becomes part of the webapp.

A minimal webapp definition would look like this:

 webapp [
     virtual-root "/app"
     root-dir %www/app/
 ]

This webapp will be further referenced in Cheyenne by its virtual-root? value, so this value have to be unique inside a given virtual-host definition. You can have as many webapps as you want in the same virtual-host (even pointing at the same root folder to make multiple instances of the same webapp using different settings, like using a different database instance).

Webapp folders structure

A webapp uses a specific filesystem folder structure:

 app/                   ;-- webapp root folder
     private/           ;-- private folder, not visible for clients
     public/            ;-- folder always accessible for clients
     app-init.r         ;-- mandatory file for events definition
     ...                ;-- put there all the protected files (RSP, static files)

The only mandatory part is the %app-init.r file (see Events section below). This file is private to the webapp and can't be served to clients (they will get a 404 HTTP code if they try).

Private folder

This is an optional folder, but will be used by most webapps. It is the most secured part of the webapp files hierarchy as it can't be accessed by client requests. Its purpose is to contain all the backend code of your web application: utility functions, libraries, frameworks, SQL files, localizations data, ...

Public folder

This is an optional folder used to store public files that have to be accessible by clients in all cases. Even if the webapp authentication? protection is active, the resources stored in this folder can still be served to the client. The main use-case is storing static resources required by a login page.

Protected access

Everything that is not in public/ or private/ folders can be freely accessed by the clients unless the webapp authentication? is activated (see Session management below). In such case, every attempt to access a resource will result in a redirection to the authentication page, if the user hasn't logged-in yet (controlled by the state of session/content/login special variable).

Session management

One of the main benefit from using a webapp container is the automatic session management. Every new client requesting any RSP script inside your webapp, will open a new session. The session is opened for 20 minutes by default (timeout delay) and can be extended using the timeout? configuration directive in the webapp definition block.

A special login word is added to session/content, with a value of false. If the auth? configuration directive is present in the webapp definition, this value indicates the state of the user authentication. It is used internally by the webapp to secure access to all its files, until the user logs in and an RSP script sets the login value to true, giving access to all the files. So a webapp protected by authentication would be defined like this:

 webapp [
     virtual-root "/app"
     root-dir %www/app/
     auth "/app/login.rsp"
 ]

Events

A webapp exposes several events that can be caught by implementing custom handlers in the special %app-init.r file (located in the root folder of the webapp). This file is mandatory for all webapps, even if you don't use it. Here's a template that you can copy/paste (you can safely remove the handler functions you don't need):

 REBOL [
     File: %app-init.r
     Purpose: "Events definition for webapp /app"
 ]
 on-application-start: does [
     ;--- add here your library / modules loading
 ]
 on-application-end: does [
     ;--- add here your library / modules proper closing
 ]
 on-database-init: does [
     ;--- add here instance specific init code
 ]
 on-session-start: does [
     ;--- add here your per session init code
 ]
 on-session-end: does [
     ;--- add here your per session closing/cleanup code
 ]
 on-page-start: does [
     ;--- add here processing code run before a RSP page is evaluated
 ]
 on-page-end: does [
      ;--- add here processing code run after a RSP page is evaluated
 ]
  • on-application-start: this event is raised once, when the first request is made on a webapp, for a given worker process. It will be raised once per worker process, to be sure that the application context is always loaded. This is the place to load your webapp's utility code and libraries stores in the private folder.
  • on-application-end: this event is raised when a worker process is closed by Cheyenne, so can happen several times, depending on the number of workers that have loaded the webapp.
  • on-database-init: this event is raised when first database access is made using DO-SQL. So, the typical usage is database cache initialization when multiple instances of the same webapp are running on the same Cheyenne instance.
  • on-session-start: this event is raised when a new session is started for a new client. This is the place where you'll define all the session content words you'll need in your webapp (using session/add).
  • on-session-end: this event is raised when a session expires. The support for this event is pending, so don't rely on it for now.
  • on-page-start: this event is raised when just before a RSP script is run. It is a good place for last minute checks like fine-grained access rights, or requests pre-processing.
  • on-page-end: this event is raised when just after a RSP script is run. Typical usage would be response post-processing.

Note: the %app-init.r file content is cached in memory in worker processes. If you modify its content, your changes will not be taken into account, you need to reset workers? processes to apply your changes or run Cheyenne with a non-persistent? worker ("-w 0" command-line option).

Locals values

When using several instances of the same webapp, you often need a way to pass them some parameters that are instance-specific. You can achieve that easily by adding a locals? block to your webapp definitions:

 webapp [
     virtual-root "/app1"
     root-dir %www/app/
     locals [
         title    "App1"
         data-dir %private/app1/
     ]
 ]
 webapp [
     virtual-root "/app2"
     root-dir %www/app/
     locals [
         title    "App2"
         data-dir %private/app2/
     ]
 ]

You can access these locals values in your RSP code using request/config/locals.

Note: there is a performance impact when using locals blocks, so keep them as small as possible.

Possible future improvements

  • webapp archive: create an archive file format for webapp allowing to version them and deploy them on production server in single step (with ability to rollback to previous version).
  • RSP/webapp virtual filesystem: encap webapps with cheyenne sources in a single binary.


Page last modified on April 19, 2011, at 02:48 PM
Powered by Cheyenne Web Server - © Softinnov