405 lines
28 KiB
HTML
405 lines
28 KiB
HTML
<!-- BeginDsi "dsi/head.html" -->
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Embedthis Appweb 4.3.4 Documentation</title>
|
|
<meta name="keywords" content="embedded web server, web server software, embedded HTTP, application web server,
|
|
embedded server, small web server, HTTP server, library web server, library HTTP, HTTP library" />
|
|
<meta name="description" content="Embedthis Sofware provides commercial and open source embedded web servers for
|
|
devices and applications." />
|
|
<meta name="robots" content="index,follow" />
|
|
<link href="../../doc.css" rel="stylesheet" type="text/css" />
|
|
<link href="../../print.css" rel="stylesheet" type="text/css" media="print"/>
|
|
<!--[if IE]>
|
|
<link href="../../iehacks.css" rel="stylesheet" type="text/css" />
|
|
<![endif]-->
|
|
<link href="http://www.google.com/cse/style/look/default.css" type="text/css" rel="stylesheet" />
|
|
</head>
|
|
|
|
<body>
|
|
<div class="top">
|
|
<a class="logo" href="http://appwebserver.org/"> </a>
|
|
<div class="topRight">
|
|
<div class="search">
|
|
<div id="cse-search-form"></div>
|
|
<div class="version">Embedthis Appweb 4.3.4</div>
|
|
</div>
|
|
</div>
|
|
<div class="crumbs">
|
|
<a href="../../index.html">Home</a>
|
|
<!-- EndDsi -->
|
|
><a href="../appweb/index.html">Programmer Reference</a>> ESP Architecture
|
|
</div>
|
|
</div>
|
|
<div class="content">
|
|
<div class="contentRight">
|
|
<h1>Quick Nav</h1>
|
|
<ul>
|
|
<li><a href="#webServerInterface">Web Server Interface</a></li>
|
|
<li><a href="#generator">Application Generator</a></li>
|
|
<li><a href="#parser">Web Page Parser</a></li>
|
|
<li><a href="#mvc">MVC</a></li>
|
|
<li><a href="#models">Models</a></li>
|
|
<li><a href="#views">Views</a></li>
|
|
<li><a href="#viewPipeline">View Pipeline</a></li>
|
|
<li><a href="#controllers">Controllers</a></li>
|
|
<li><a href="#routing">Routing</a></li>
|
|
<li><a href="#actions">Actions</a></li>
|
|
<li><a href="#deployment">Developing</a></li>
|
|
<li><a href="#deployment">Deployment</a></li>
|
|
</ul>
|
|
<!--
|
|
<h1>See Also</h1>
|
|
<ul>
|
|
<li><a href="architecture.html">Language Architecture</a></li>
|
|
<li><a href="../../api/ejscript/index.html">Script Library</a></li>
|
|
<li><a href="../../api/native.html">Native APIs</a></li>
|
|
<li><a href="../../guide/ejs/solutions/index.html">Solution Guide</a></li>
|
|
<li><a href="../../guide/ejs/programmers/index.html">Programmers Guide</a></li>
|
|
<li><a href="../../guide/ejs/users/index.html">User Guide</a></li>
|
|
<li><a href="../../api/ejscript/index.html" target="new">ESP Library</a></li>
|
|
</ul>
|
|
-->
|
|
</div>
|
|
<div class="contentLeft">
|
|
<h1>ESP Architecture</h1>
|
|
<p>The ESP Web Framework was designed to make it dramatically easier to create dynamic web
|
|
applications. The web framework provides an application generator, templating engine, a powerful
|
|
Model/View/Controller framework and a library of Ajax view controls to take the tedium out of creating web
|
|
applications. Via this framework, ESP drastically reduces the number of lines of code you need to
|
|
write for a compelling, dynamic web application.</p>
|
|
<p>This document describes the ESP Web Framework and how ESP is embedded in web servers to run
|
|
web applications and respond to web requests. It describes the flow of execution and the main processing
|
|
components.</p>
|
|
<h2>ESP Web Framework Architecture</h2>
|
|
<p>The Web Framework embeds the ESP language into leading web servers such as <a href=
|
|
"http://www.appwebserver.org">Appweb</a> and <a href="http://www.apache.org">Apache</a> to provide a
|
|
hosting environment for web applications. ESP learns from other web frameworks like Rails and PHP, to
|
|
deliver a web framework that uses the "C" language for server side web programming.</p>
|
|
<p>The Web Framework builds upon the ESP core language and provides a web request handler, a
|
|
Model/View/Controller application framework and an edit-and-continue development model.</p><img src=
|
|
"../../images/ejsArchitecture.jpg" alt="ESP Web Framework Architecture" />
|
|
<p>The main components of the ESP Web Framework:</p>
|
|
<ul>
|
|
<li><a href="#webServerInterface">Web Server Interface</a> - Framework hosting and request handler</li>
|
|
<li><a href="#generator">Application Generator</a> - for applications, scaffolds and stubs</li>
|
|
<li><a href="#parser">Web Page Parser</a> - Parses web pages and applies view layouts and emits pure HTML</li>
|
|
<li><a href="#mvc">Framework Classes</a> - MVC, Http Request and Ajax view classes</li>
|
|
<li>ESP compiler - Creates and caches application byte code</li>
|
|
<li>ESP Virtual Machine - executes the byte code and formats the response</li>
|
|
</ul><a id="webServerInterface"></a>
|
|
<h2 class="section">Web Server Interface</h2>
|
|
<p>The ESP Web Server Interface (or web interface) provides the interface and coupling between
|
|
ESP and the web server. It accepts incoming web requests from the web server, routes the request to
|
|
the appropriate application or ejscript web page, processes the output and passes it back to the web server
|
|
for transmission to the client.</p>
|
|
<h3>Hosting Alternatives</h3>
|
|
<p>ESP offers three possible hosting paradigms:</p>
|
|
<ul>
|
|
<li>CGI</li>
|
|
<li>FastCGI</li>
|
|
<li>Custom in-memory module</li>
|
|
</ul>
|
|
<p>The <a href="http://en.wikipedia.org/wiki/Common_Gateway_Interface">Common Gateway Interface</a> (CGI)
|
|
is a standard protocol for hosting applications in a web server. CGI offers good stability but low
|
|
performance.</p>
|
|
<p><a href="http://www.fastcgi.com/">FastCGI</a> is a replacement for CGI. It provides higher performance
|
|
than CGI by supporting multiple Http requests per FastCGI instance. It also offers improved stability by
|
|
isolating application instances.</p>
|
|
<p>Custom in-memory modules offer the highest performance. ESP provides modules for <a href=
|
|
"http://www.appwebserver.org/">Appweb</a> and <a href="http://www.apache.org/">Apache</a>. The custom
|
|
module, <b>mod_ejs</b>, provides excellent performance but less application isolation than FastCGI.</p>
|
|
<p>When using a custom in-memory module, each ESP application will typically define a URL alias using
|
|
the EjsAppAlias directive. For example:</p>
|
|
<pre>
|
|
EjsAppAlias /myAppName/ "/Directory/to/myApp"
|
|
</pre>
|
|
<p>This instructs the web server to send all requests with the URL prefix "myAppName" to ESP for
|
|
routing and processing.</p><a id="formData"></a>
|
|
<h3>Form Data</h3>
|
|
<p>The web interface converts incoming post and form data into a format suitable for easy processing by
|
|
ESP applications. Traditionally, form data is passed to web applications by environment variables. But
|
|
this format is often clumsy, doesn't scale, and does not map well onto an object-oriented language such as
|
|
Javascript.</p>
|
|
<p>ESP replaces environment variables with a params[] collection object and it transparently converts
|
|
form data into a nested collection of objects. It automatically converts dot separated form names into
|
|
objects that are addressable by dot notation.</p><a id="requestState"></a>
|
|
<h3>Request State</h3>
|
|
<p>The web interface will construct request, response, and host objects that store request state. ESP
|
|
avoids the normal overhead in creating and populating these objects by using virtual, lazy construction.
|
|
Consequently, ESP applications incur minimal overhead when accessing request state.</p><a id="hosting"></a>
|
|
<h3>Interpreter Hosting</h3>A high performance web server must accept incoming requests, route to the
|
|
appropriate request handler, initialize the handler including necessary interpreters, gather response data,
|
|
transmit to the client, and then tear down the handler. And this must be done many times per second, ideally
|
|
hundreds of times per second for dynamic content.
|
|
<p>To do this effectively, ESP pre-creates a master interpreter instance replete with all the
|
|
requisite system classes and web framework. When incoming requests arrive, the web interface quickly clones
|
|
this master interpreter to create a light-weight copy that is dedicated to the new request. The clone
|
|
leverages the system types and web framework in the master, and so needs minimal initialization before it
|
|
can start servicing the web request.</p>
|
|
<p>Clone interpreters are not completely isolated. Controlled session state sharing is accomplished by
|
|
sharing session[] and application[] objects.</p>
|
|
<p><a id="generator"></a></p>
|
|
<h2 class="section">Application Generator</h2>
|
|
<p>The web framework supports two kinds of ESP web applications.</p>
|
|
<ul>
|
|
<li>Simple stand-alone web pages</li>
|
|
<li>ESP Model/View/Controller Applications</li>
|
|
</ul>
|
|
<p>Stand-alone web pages use embedded ESP code but do not use the full Model View Controller paradigm,
|
|
nor do they use the application generator. They typically use a "Post-Back" paradigm where form data is
|
|
posted back to the same page. The do not have controllers, models or view layouts.</p>
|
|
<p>MVC applications are more powerful. They have database models, controllers, views and layouts and
|
|
typically start life by using the application generator. This creates an application directory and
|
|
populates it with the necessary directories, configuration files and stubs to begin the application.</p>
|
|
<p>The application generator is a program named <b>ejsweb</b>. To create a new application called test:</p>
|
|
<pre>
|
|
ejsweb -v generate app test
|
|
</pre>
|
|
<p>This will create the following directories:</p>
|
|
<ul>
|
|
<li>test/config</li>
|
|
<li>test/controllers</li>
|
|
<li>test/db</li>
|
|
<li>test/models</li>
|
|
<li>test/src</li>
|
|
<li>test/views</li>
|
|
<li>test/views/layouts</li>
|
|
<li>test/web</li>
|
|
</ul>
|
|
<p>It will also create the following files:</p>
|
|
<ul>
|
|
<li>test/config/config.ecf</li>
|
|
<li>test/config/compiler.ecf</li>
|
|
<li>test/config/database.ecf</li>
|
|
<li>test/config/view.ecf</li>
|
|
<li>test/views/layouts/default.ejs</li>
|
|
<li>test/src/Test.es</li>
|
|
<li>test/controllers/Application.es</li>
|
|
<li>test/README</li>
|
|
</ul>
|
|
<p>The ejsweb program can also generate controllers. It is currently being enhanced to generate models,
|
|
views, and entire scaffolds. To compile your application, use the ejsweb program:</p>
|
|
<pre>
|
|
ejsweb -v compile
|
|
</pre>
|
|
<p>During development time, the web framework uses <b>ejsweb</b> behind the scenes to transparently
|
|
recompile all, or portions, of the application if the developer modifies any model, view, or
|
|
controller.</p><a id="mvc"></a>
|
|
<h2 class="section">Model, View, Controller Framework</h2>
|
|
<p>A Model View Controller framework, also known as MVC, is a proven paradigm for organizing web
|
|
applications. The model manages the state of the application including the database. The controller manages
|
|
the application, responding to inputs and invoking the relevant views to generate the user interface.</p>
|
|
<p>Originally developed in the '70s, it has been more recently adapted for web applications and been
|
|
popularized by frameworks such as <a href="http://www.rubyonrails.org">Ruby on Rails</a>. ESP uses the
|
|
same paradigm with a "C" language and embedded spin.</p><a id="models"></a>
|
|
<h2 class="section">Models</h2>
|
|
<p>For object-oriented languages such as ESP, there is sometimes a mismatch between relational
|
|
database data and the JavaScript objects that are used to represent and manage that data. To solve this
|
|
problem, ESP provides an Object Relational Mapping (ORM) layer to make it easy to read, modify, and
|
|
write database data. ORM layers map database tables to classes, rows to object instances, and columns to
|
|
properties of the classes and objects. If a database has a table named Users, then there would be a model
|
|
class named User.</p>
|
|
<p>When ESP reads records from a database table it constructs an instance of the model class and
|
|
dynamically creates properties for each of the columns in the table. It also maps the SQL data types into
|
|
equivalent JavaScript types. This allows a natural access and update paradigm where the application can
|
|
deal with JavaScript objects while the ORM takes care of reading, querying and updating the database.</p>
|
|
<p>The web framework provides a powerful set of access methods to query, join, update, and deal with SQL
|
|
tables. You can use higher level functions where the ORM generates appropriate SQL statements or you can
|
|
construct and issue your own SQL.</p>
|
|
<p>The ORM Methods include: belongsTo, find, findAll, findOneWhere, findWhere, getColumnNames,
|
|
getColumnTitles, getDb, getKeyNme, getNumRows, getTableName, hasAndBelongsToMany, hasMany, remove, save,
|
|
saveUpdate, setKeyName, setTableName, sql and trace.</p>
|
|
<p>The ESP ORM currently only provides one database connector for SQLite. It is expected that a future
|
|
release will add support for other major database engines.</p><a id="views"></a>
|
|
<h2 class="section">Views</h2>
|
|
<p>The View part of the ESP web framework is responsible for generating the user interface. It
|
|
typically takes an input HTML web page with embedded ESP and generates the HTML response to send back
|
|
to the client. However, views can also be generated by controllers and thus require no HTML page.</p>
|
|
<p>The ESP View framework provides:</p>
|
|
<ul>
|
|
<li>A templating engine for master layout pages</li>
|
|
<li>Embedded server-side JavaScript in HTML</li>
|
|
<li>A rich library of methods to render output</li>
|
|
<li>A consistent interface to Ajax libraries</li>
|
|
<li>A suite of view dynamic user controls such as table, chart, tab, tree, ...</li>
|
|
</ul><a id="viewPipeline"></a>
|
|
<h3>View Pipeline</h3>
|
|
<p>The View mechanism consists of a processing pipeline that progressively transforms the web page. Views
|
|
start with a partial HTML view page which typically contains embedded ESP. This is parsed by the Web
|
|
Page Parser and combined with layout views to create a composite web page. It is then parsed and
|
|
converted to pure ESP code which is compiled and cached in a module file (.mod). The module file can
|
|
be run repeatedly by the VM to generate the required HTML for the user view. <img src=
|
|
"../../images/ejsWebView.jpg" alt="View Pipeline" /></p>
|
|
<p>The time-intensive part of this pipeline processing occurs once, at development time. This is comprised
|
|
of the pipeline stages up to and including compilation. The often less costly run-time processing for each
|
|
request consists of reading the module file and executing it in the VM.</p><a id="parser"></a>
|
|
<h3>Web Page Parser</h3>
|
|
<p>The Web Page Parser is a templating engine and embedded script parser. It understands and processes
|
|
embedded javascript and layout directives to expand the view content pages and create a composite page that
|
|
represents an entire web page that the user will see.</p>
|
|
<p>A <b>templating engine</b> is an important part of a view framework. It allows you to specify the "look
|
|
and feel" and standard components of a web application in one place, and then reuse the "look and feel" in
|
|
content pages by simply referencing a layout page. The layout page typically contains the top level HTML
|
|
structure, style sheets, and graphic content that is standard on every page. It also specifies the location
|
|
to insert content from content pages. The content pages focus on the content and data unique to that page.
|
|
They do not replicate the standard content specified in the master page. In this way, changing the
|
|
layout page in one place will automatically change every web page in the application.</p>
|
|
<p>The web page parser reads the content view pages that contain embedded ejscript code (with .ejs
|
|
extension). It blends the content page with the layout pages and converts it to a pure ESP program
|
|
(with .es extension) which represents the composite web page that the user will see.</p>
|
|
<p>Here is a simple layout page</p>
|
|
<pre>
|
|
<html>
|
|
<head>
|
|
<title>@@title</title>
|
|
<link rel="stylesheet" type="text/css" href="@@style"/>
|
|
</head>
|
|
<body>
|
|
<img src="banner.jpg">
|
|
<%@ content %>
|
|
</body>
|
|
</html>
|
|
</pre>
|
|
<p>The <b><%@ content %></b> directive instructs the web page parser to insert the content page at
|
|
this location. The @@title and @@style directives access ESP variables set to the required content
|
|
title and style sheet at run-time.</p>
|
|
<p>Here is a simple content page:</p>
|
|
<pre>
|
|
<h1>Hello World</h1>
|
|
<p>Today is <%= new Date %>
|
|
</pre>
|
|
<p>The web parser supports the following web page directives. These can be used in layout or content
|
|
pages.</p>
|
|
<ul>
|
|
<li><%= ejscript expression %></li>
|
|
<li>@@variable</li>
|
|
<li><% ejscript code %></li>
|
|
<li><% include "filename" %></li>
|
|
<li><%@ layout "file" %></li>
|
|
</ul>
|
|
<p>The <%= ejscript expression %> directive will evaluate the expression and substitute the resulting
|
|
expression value.</p>
|
|
<p>The @@variable directive is a shortcut for <%= expression %>.</p>
|
|
<p>The <% ejscript code %> directive will invoke the given code. No automatic substitution of output
|
|
occurs. However, the code can call "write()" to generate output in the place of the directive.</p>
|
|
<p>The <% include "filename" %> directive will include the given file name at the location of the
|
|
directive when parsing the web page. The Include directives can be nested.</p>
|
|
<p>The <%@ layout "file" %> directive specifies the name of the layout page. By using this directive
|
|
in layout pages, you can build up the web page layout by nesting layout pages. If omitted in content pages,
|
|
which is usually the case, the default layout is views/layouts/default.ejs. If omitted in layout pages, it
|
|
is assumed the layout page is the top level layout page.</p>
|
|
<p>The web parser supports the following web page directive in layout pages:</p>
|
|
<ul>
|
|
<li><%@ content %></li>
|
|
</ul>
|
|
<p>This specifies the location for the content page data.</p>
|
|
<p><b>NOTE:</b> you do not have to use layout pages. Simple stand-alone web pages without layouts code are
|
|
supported. To disable templating, use a <%@ layout="" %> directive.</p>
|
|
<h3>View Controls</h3>
|
|
<p>The web framework provides a suite of view controls for common UI elements. These include button, chart,
|
|
checkbox, form, image, label, link, list, progress bar, radio button, table, tabs, text, textarea and tree.
|
|
The purpose of the controls is to be a themeable and skinnable set of UI controls that provides a higher
|
|
level of functionality than bare HTML. For example, the table control allows the easy display of database
|
|
data with sortable rows and selectable columns.</p>
|
|
<p>The view controls are implemented via View connector modules that communicate with the web framework's
|
|
View connector interface. This is a modular interface for industry Ajax and UI toolkits. The ESP web
|
|
framework provides a HTML view connector, and a Google Ajax Visualizer connector. Users can select which
|
|
connector module to use for a specific control on a control by control basis. Additional Ajax connector
|
|
libraries will be supported in the future.</p>
|
|
<p>The controls are bindable to data stored in models and many controls can dynamically refresh their
|
|
content using Ajax techniques without redisplaying the entire page.</p>
|
|
<p>Views can also use a library of view methods to generate and manage HTML output and responses. These
|
|
include: redirect, render, setCookie, setHeader, write, writeHtml and writeRaw.</p><a id="controllers"></a>
|
|
<h2 class="section">Controllers - Responding to Requests</h2>
|
|
<p>The role of the controllers is to manage the application and respond to inputs so controllers form the
|
|
heart of the web application. Controllers are typically bound to various URLs so that user input is routed
|
|
to specific actions within the controls. When a controller receives an incoming Http message, the requested
|
|
action is run. The action will typically mutate the state of the application in some manner and then render
|
|
a response view to the user.</p><a id="routing"></a>
|
|
<h3>Routing</h3>
|
|
<p>The ESP web framework routes incoming URL requests by tokenizing the request URL. The format used
|
|
is:</p>
|
|
<blockquote>
|
|
<p>http://site/APP/CONTROLLER/ACTION</p>
|
|
</blockquote>
|
|
<p>Where APP is the name of the application, CONTROLLER the name of the controller and ACTION is the name
|
|
of an action method within the controller. When such a URL request is received by ESP, it routes the
|
|
request to the specified controller and invokes the action method. The routing format is currently fixed
|
|
and not configurable but it is anticipated that user controlled routing will be added in a future
|
|
release.</p><a id="actions"></a>
|
|
<h3>Actions</h3>
|
|
<p>When a controller receives a request to service, it is dispatched to the action method specified in the
|
|
URL. The action is a simple function defined with an "action" namespace qualifier. The job of the action
|
|
method is:</p>
|
|
<ol>
|
|
<li>Respond to the request</li>
|
|
<li>Render a response view back to the client</li>
|
|
</ol>
|
|
<p>The action responds to the request by examining the request form parameters, query string, and other Http
|
|
and application state information.</p>
|
|
<p>Here is a sample action method that updates a database table based on user submitted form data in
|
|
"params".</p>
|
|
<pre>
|
|
action function update() {
|
|
/* Update */
|
|
portfolio = Portfolio.find(params.id)
|
|
if (portfolio.saveUpdate(params.portfolio)) {
|
|
inform("Portfolio updated successfully.")
|
|
redirect("list")
|
|
}
|
|
}
|
|
</pre>
|
|
<p>An action method can explicitly render data by calling one of the render() methods. It can redirect the
|
|
client to a new URL via the redirect() method. Manual rendering is ideal for "RESTful" web services,
|
|
particularly when coupled with the XML/E4X capabilities of ESP.</p>
|
|
<p>If the action method does not explicitly render any data, the web framework will automatically render a
|
|
view page of the same name as the action method. That view has access to the controller and request
|
|
state.</p>
|
|
<p>Other methods used by Controller actions include: cache, createSession, destroySession, escapeHtml,
|
|
html, inform, keepAlive, makeUrl, render, renderFile, renderXml, reportError, setCookie, setHeader,
|
|
setHttpCode, setMimeType, warn and write.</p><a id="deployment"></a>
|
|
<h2 class="section">Development and Deployment</h2>
|
|
<p>There are two phases of use for ESP: Development and Deployment. When developing, developers need
|
|
quick turn-around with rapid test-modify-build cycles. Interpreted languages have a distinct advantage over
|
|
traditional compiled languages when used for such iterative or <a href=
|
|
"http://en.wikipedia.org/wiki/Agile_software_development">Agile Web Development</a>. ESP offers the
|
|
best of both. When developing, ESP runs as an interpreted environment. Changes made to web pages or
|
|
scripts cause the files to be parsed and compiled without restarting the web server. Simply reloading the
|
|
web pages in the browser will trigger the changed page to be rebuilt.</p>
|
|
<p>When ready for deployment, the entire application can be compiled into a single module file for easy
|
|
deployment.</p>
|
|
</div>
|
|
</div>
|
|
<!-- BeginDsi "dsi/bottom.html" -->
|
|
<div class="bottom">
|
|
<p class="footnote">
|
|
<a href="../../product/copyright.html" >© Embedthis Software LLC, 2003-2013.
|
|
All rights reserved. Embedthis, Appweb, ESP, Ejscript and Embedthis GoAhead are trademarks of Embedthis Software LLC.</a>
|
|
</p>
|
|
</div>
|
|
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
|
|
<script type="text/javascript">
|
|
google.load('search', '1', {language : 'en'});
|
|
google.setOnLoadCallback(function() {
|
|
var customSearchControl = new google.search.CustomSearchControl(
|
|
'000262706376373952077:1hs0lhenihk');
|
|
customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
|
|
var options = new google.search.DrawOptions();
|
|
options.enableSearchboxOnly("http://appwebserver.org/search.html");
|
|
customSearchControl.draw('cse-search-form', options);
|
|
}, true);
|
|
</script>
|
|
<script type="text/javascript">
|
|
var _gaq = _gaq || [];
|
|
_gaq.push(['_setAccount', 'UA-179169-2']);
|
|
_gaq.push(['_trackPageview']);
|
|
(function() {
|
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|