SimpleHttpServer, except SoyWeb serves a Soy file by rendering a template in the file as HTML.Unlike other templating languages like PHP and JSP, Soy gives users just enough programming logic to eliminate duplicate HTML across pages (using template calls and loops), but not so much programming power that business logic will leak into the template.
tasks.soy, in a directory js that defines three templates: the UI for a task list, the boilerplate for a demo page, and an instance of the task list on a demo page:{namespace tasks}
/**
* @param title
* @param items
*/
{template .list}
<h1>{$title}</h1>
<div>
{foreach $item in $items}
<div class="{css task-item}">
<div style="margin-left: {$item.indent * 24}px">
{$item.name}
</div>
</div>
{ifempty}
<div class="{css tasks-complete}">
Nothing to do!
</div>
{/foreach}
</div>
{/template}
/**
* @param content
*/
{template .demoPage}
<!doctype>
<html>
<head>
<link rel="stylesheet" href="tasks.css">
</head>
<body>
{$content|noAutoescape}
</body>
</html>
{/template}
/**
* This template will be rendered by SoyWeb when the user loads tasks.soy.
* It deliberately includes dummy data so the designer can get a feel for how
* the task list will appear with real data rather with minimal copy and paste.
*/
{template .soyweb}
{call .demoPage}
{param content}
{call .list}
{param title: 'Food Shopping' /}
{param items: [
['indent': 0, 'name': 'cheese' ],
['indent': 0, 'name': 'crackers' ],
['indent': 0, 'name': 'condiments' ],
['indent': 1, 'name': 'ketchup' ],
['indent': 1, 'name': 'mayo' ],
] /}
{/call}
{/param}
{/call}
{/template}To see how the rendered template looks using SoyWeb, run the following command:java -jar plovr.jar soyweb --dir jsThen point your browser to
http://localhost:9811/tasks.html to see the task list populated with the data specified by the .soyweb template.Now creating another template with a different set of mock data is much less work, as js/tasks2.soy can reuse the existing templates:
{namespace tasks2}
/**
* This template will be rendered by SoyWeb when the user loads tasks2.soy.
* This makes it possible to see how an empty task list will be rendered.
*/
{template .soyweb}
{call tasks.demoPage}
{param content}
{call tasks.list}
{param title: 'Food Shopping' /}
{param items: [] /}
{/call}
{/param}
{/call}
{/template}With SoyWeb is running, the rendered version of this template can be seen at http://localhost:9811/tasks2.html.--unsafe option when starting SoyWeb. This makes it easier to see what your template will look like with different inputs. Consider the following Soy file, js/settings.soy, for a settings page that shows a user whether or not he has granted an application access to Facebook:{namespace settings}
/**
* @param? accessToken
*/
{template .facebook}
<div>
{if $accessToken}
You have granted access to Facebook.
Your access token is <b>{$accessToken|id}</b>.
{else}
This application does not have access to Facebook.
{sp}
<button>Grant Access</button>
{/if}
</div>
{/template}
/**
* Demo the settings UI using SoyWeb.
*/
{template .soyweb}
<body>
{call .facebook data="all" /}
</body>
{/template}Normally, if you loaded settings.soy with SoyWeb, accessToken would be null, so you would see the "This application does not have access to Facebook" UI. If you wanted to see the "You have granted access to Facebook" UI, then you would have to edit facebook.soy to set {param accessToken: 'someToken' /} in the .soyweb template, and then reload the page.It would be much more convenient to be able to edit the query parameters of the URL to SoyWeb to toggle these parameters so that:
http://localhost:9811/settings.html?accessToken=someTokenwould show the "access granted" UI with whereas
http://localhost:9811/settings.html?accessToken=nullwould show the "no access" UI. Fortunately, SoyWeb makes this possible when the
--unsafe option is specified as follows:java -jar plovr.jar soyweb --dir js --unsafeWhen specified, SoyWeb takes each query parameter and makes a best effort to convert it to the appropriate datatype, and then passes each name/value pair as a parameter to the
.soyweb template when rendering it. Here are some examples of the types of conversions that SoyWeb will do for a query string:?option=true becomes the pair {option: true}?option=TRUE becomes the pair {option: "TRUE"}?option1=true&option2=false becomes the pair {option1: true, option2: false}, as multiple parameters may be defined in the query string.?option=null becomes the pair {option: null}?option=foo becomes the pair {option: "foo"}?option=%22foo%22 becomes the pair {option: "foo"}?option=true&option=10 becomes the pair {option: 10} because SoyWeb chooses the rightmost value for a repeated query parameter. This makes it easier to tack on a new value to the end of a URL to update it rather than finding the existing assignment and editing it.This option is disabled by default because it could enable a malicious user to to inject his own JavaScript into your page. For example, the user could construct the following URL that alerts gotcha when the user visits the page:
http://localhost:9811/settings.html?accessToken=%3Cscript%3Ealert('gotcha')%3C/script%3EThis particular exploit works because the author of facebook.soy used {$accessToken|id} instead of {$accessToken}, which disabled autoescaping for that variable. (Incidentally, Chrome refuses to run this JavaScript, noting: Refused to execute a JavaScript script. Source code of script found within request. in the developer tools console.)For this reason, this feature is disabled by default and is named --unsafe to raise awareness of the security implications of enabling this option. Nevertheless, this is an effective feature for developing HTML UIs, as it makes it possible to view the interface in different states with little overhead. It is highly recommended for prototyping and for demoing to trusted users.
--dir is the only required option: it specifies the directory of files to serve. No files in parent directories of --dir will be served by SoyWeb.--unsafe makes it possible to specify Soy parameters using query parameters from the URL. This parameter is named "unsafe" because it opens up the possibility for XSS attacks. This is not a sensible thing to do if SoyWeb is used in production, but it is incredibly useful when prototyping internally. See Setting template parameters with URL query parameters for details.--port is the port on which SoyWeb will handle requests. The default is 9811 (which is one more than plovr's default port, 9810).--template is the name of the template that SoyWeb will use in a .soy file when it is requested. As shown in the example, the default value is soyweb. Note that this template generally does not have any parameters unless it is intended to be used with --unsafe such that parameter values will be supplied via the query string.--globals refers to a JSON file containing a map of global variable names to values. If supplied, SoyWeb will supply these values as globals when rendering a template. See www-globals.js for an example of this.--static if specified, disables SoyWeb's default serving behavior, which is to reload a template each time it is requested. This option is not generally recommended for use, though admittedly it is used to serve the static content on plovr.com.--noindexes disables listing the files in a directory, much like the "-Indexes" directive in an Apache config.