Serverless Deployment
From OpenLaszlo
Contents |
Overview
A Laszlo application compiled with LPS 2.2 (or earlier) requires access to a running copy of the Laszlo Presentation in order to make data (XML over HTTP), media, SOAP, Java Direct, and XML-RPC requests. LPS 3.0 will remove this requirement for applications that make data and media requests.
With LPS 3.0, Laszlo applications can be "statically" compiled to binary form and served outside the LPS. The binary object files can be placed on any web server (e.g., apache, IIS, and so on). No servlet container is required.
The LZX compiler in LPS 3.0 can compile to the SWF Version 6 and/or 7 (Macromedia Flash) file format. The LPS also provides HTML and JavaScript support files that are needed to serve the application outside of the LPS.
With current plans, access to a server will still be required for SOAP and XML-RPC requests. (Java Direct may not make sense in a serverless setting.) Contributions from the development community could remove any or all of these last restrictions, by providing non-viral OSI-approved runtime libraries that handle these protocols.
Status Quo
Static Applications
Even in LPS 2.2, applications that *do not* make HTTP requests during execution can be deployed statically. This doesn't cover very many cases, but may have some utility. Use the curl or wget tools, the lzc command line tool, or open your browser's cache, to retrieve a copy of the swf file that the server serves in response to an ?lzt=swf request, and copy this file to a web directory on your server. Voila! A Laszlo application deployed without the presentation server.
Serverless Data
Serverless data requests are actually possible in 3.0a2 and later, although they have not been extensively tested and the API is subject to change. Use <dataset transport="direct"> to make a serverless request.
Discussion Starter
David Temkin, CTO for Laszlo Systems, wrote on October 8th of 2004 Coming soon: Laszlo (presentation server optional) :
If you've developed using Laszlo, you've seen that the server is invoked during the edit-compile-debug cycle. That means that the server is here to stay -- as a developer tool. But it won't need to be installed on a deployment server unless you require certain specific runtime features. That's a big deal if you have complex/high-scale infrastructure to manage, if you don't want to run Java application servers, or if you have a simple site and are not in a position to install server software.( source: http://www.davidtemkin.com )
We're expecting that serverless deployment, coupled with open source, will go a long way toward making it easier to deploy rich Internet applications, particularly at high scale. And it's yet another reason to select Laszlo as a platform, compared to the presentation-server-required competition.
Notes
Development/deployment workflow with Static Compilation:
- Develop application as in LPS 2 (dynamic compilation).
- Compile static files
- Place app files on web server
Notes:
- media types supported: SWF, JPG, MP3 (command line conversion utility available for other formats)
- unsupported features: persistent connection, SOAP, XML-RPC (none of these features are used by RWM)
- The data transfer size and run-time performance have not yet been characterized (could be bigger or smaller, faster or slower). If gzipped data is desired, the XML services will need to gzip the data (since LPS will no longer be in the picture).
- It's not necessary to gzip the swf file, swf6 and swf7 files are internally gzip compressed by the compile process. It would be redundant to have the web server compress them as well.
Requirements
Problem
The problem that unproxied operation is intended to solve is that deploying a Laszlo application to the client, currently requires deploying the LPS servlet on the server. Requiring the LPS servlet during deployment is a problem because: - A particular server may not be running Java. This is the case for many ISPs, for example. - A particular server's servlet container may not be qualified against the LPS jar. Today, this is the case with JRun (which currently has class loader conflicts). - It is more difficult for a development organization to qualify a server+client-application, than to qualify a client application alone. There are simply more moving parts. - Deploying a server is riskier than deploying a client-only application, because server failure modes affect more users concurrently. - Lastly, the presence of a server component creates a perceived capacity issue. This has never been a problem in practice (e.g. Yahoo, Earthlink), and there is a scalability whitepaper with metrics that demonstrate scalability, but these don't address the initial perception.
Goals
This feature must allow deployment of the largest possible set of Laszlo applications --- within the constraints of implementation time and capabilities of the execution environment --- without an instance of LPS running on the server (e.g. served from an instance of Apache). An example of an implementation time constraint is SOAP: no one is currently signed up for a client-only implementation of SOAP (the current implementation relies on server transcoding), and we wouldn't hold the initial delivery of unproxied operation for that feature. An example of an execution environment constraint is support for runtime-requested PNGs. The Flash players don't support PNG as an image format, so this can't be supported without server-side transcoding.
It should be possible to use the same source files to create either proxied or unproxied executable files. This is important for two reasons. First, the decision about whether to deploy an application proxied or unproxied may happen late in the development process, possibly following performance measurement on the two modes of operation for that particular application. It is desirable to minimize the number of edits that is necessary to measure these modes operation, and to change the deployment mode. Second, it is desirable to share libraries between applications that are designed for proxied operation, and applications that are designed for unproxied operation. To the extent that these libraries can operate in either mode, it is desirable to make them usable, without source modifications, in either kind of application.
It is not a goal of this message to separate the Flash-specific and the Flash-independent portions of the Laszlo specification in general. (That's a separate project.) This message does distinguish between the requirements for any Laszlo implementation, and the requirements for the (existing) Flash Laszlo implementation, but this is just to avoid introducing any additional gratuitous challenges to the task of implementing an alternate runtime with this feature.
Definitions
- Flash Laszlo is the implementation of the Laszlo platform for the Flash player.
- An execution engine (aka execution environment, or virtual machine) is a software component that instantiates and executes a Laszlo application. The Flash player is execution engine for Flash Laszlo.
- A executable file (or executable) is the initial input to an execution engine, and encapsulates the execution-time information about the Laszlo application. The executable file for a Laszlo application compiled with LPS 2.x is swf5 file, and the executable file for an application compiled with LPS 3.0 is swf6 or swf7.
- An application instance (or instance, where this is unambiguous) is a particular instance, invocation, or execution of a Laszlo application on a particular client node. If a browser has two tabs that are open to the same HTML page, and this page embeds a Laszlo application, there is one execution engine executing one executable, but there are two application instances.
- A data request is a execution-time request for a dataset. The <dataset> and <datasource> tags and the LzDatasource.doRequest() method create data requests.
- A media request is an execution-time request for a media file: an image, animation, audio file, or movie. The <view resource> attribute and the LzView.setSource() and LzView.setResource() attributes create media requests.
- An rpc request is a JavaRPC, XML-RPC, or SOAP request.
- A request is a data, media, or rpc request.
- A proxied request is a request that is mediated by an instance of the LPS servlet. The servlet proxies the HTTP request to the endpoint that is named in the request URL, and proxies the result (possibly with caching and transcoding) back to the application instance. An unproxied request is a request that is sent directly from the application instance to the endpoint..
- A proxied application instance (or proxied instance) is an application instance that has access to an instance of the LPS servlet. For practical purposes, this means it was served from an instance of a servlet container that contains the LPS servlet. This is the mode of operation that is supported today.
- An unproxied application instance (or unproxied instance) is an application instance that does not have access to an LPS servlet instance; for example, if it was served via Apache.
- Running as a proxied application instance, or an unproxied application instance, are the two modes of operation for an LPS application.
- A declarative swf file is a swf file (swf3, swf4, swf5, or swf6) that contains no ActionScript except STOP and PLAY.
Note that it is logically possible for proxied instance to make both proxied and unproxied requests. An unproxied instance may only make unproxied requests, because by definition there is no server-side instance that could perform the proxying.
Requirements
Here's a first cut; speak up if you think something should be elevated, or isn't necessary. MAY, MUST, and SHOULD are defined as in [1]. Informally:
- MUST means a design goes back to the drawing board if it doesn't satisfy this requirement.
- SHOULD is a tie-breaker between designs that satisfy MUST requirements.
- MAY is optional but desirable. It's optional either because it's less important than SHOULD; or because it's known to be unimplementable on some execution environments but may be intended to be supported on others.
General requirements:
- GR1
- Except where otherwise specified, all documented features should have the same API and behavior in proxied and unproxied mode of operation.
- GR2
- All documented features SHOULD have the same API and behavior in LPS 2.x, and in proxied operation in LPS 3.0.
- GR3
- All documented features SHOULD have the same API and behavior in LPS 2.x, and in the default operation mode in LPS 3.0. (If the default operation mode is proxied, GR2 and GR3 are the same.)
] Syntax and warnings:
- S1
- It SHOULD be possible to specify that an application or library is only intended for proxied deployment.
- S2
- It SHOULD be possible to specify that an application or library is only intended for unproxied deployment.
- E1
- Compile of an application that uses proxied-only features, to an unproxied executable, SHOULD result in compilation warnings.
- E2
- Unproxied execution of an application that uses proxied-only SHOULD result in visible warnings (e.g. the debugger, or a dialog box).
Data requests:
- DR1
- It MUST be possible for an unproxied instance to make unproxied data requests.
- DR2
- It MAY be possible for a proxied instance to make unproxied data requests.
- DR3
- It SHOULD be possible to use the same source to make unproxied data requests from an unproxied instance, and proxied data requests from a proxied instance.
- DR4
- [I had something here about acceptencodings and cacheable that I don't have the heart to figure out again, but I think some of this stuff becomes optional.]
Media requests:
- MR1
- It MUST be possible for an unproxied instance to make unproxied media requests for media types in the set of unproxied media types (below).
- MR2
- It MAY be possible for a proxied instance to make unproxied media requests.
- MR3
- It SHOULD be possible to use the same source to make unproxied media requests from an unproxied instance, and proxied media requests from a proxied instance.
- MR4
- It MAY be possible to use the same source to make media requests from an proxied instance, that are unproxied iff they are in the unproxied media request set and proxied otherwise.
- MS1
- The set of unproxied media requests SHOULD include a lossless compression format; e.g. PNG or GIF. (This is MAY because the Flash runtime doesn't support it, so requiring it would shoot down the whole feature :-(
- MS2
- The set of unproxied media requests MUST include a lossy compression format; e.g. JPEG.
- MS3
- The set of unproxied media requests MUST include a vector graphics format; e.g. declarative swf, or SVG [TBD: minimal profile]
- MS4
- The set of unproxied media requests SHOULD include a vector animation format; e.g. declarative swf.
- MS5
- The set of unproxied media requests SHOULD include a video format; e.g. H.263.
- MS6
- The set of unproxied media requests SHOULD include an audio format; e.g. MP3.
- FMS1
- The set of unproxied media requests for Flash Laszlo MUST include JPEG.
- FMS2
- The set of unproxied media requests for Flash Laszlo MUST include declarative swf.
- FMS3
- The set of unproxied media requests for Flash Laszlo SHOULD include H.263.
- FMS4
- The set of unproxied media requests for Flash Laszlo MUST include MP3, subject to the restrictions listed in the Laszlo Developers Guide.
RPC requests:
- RPC1
- JavaRPC SHOULD NOT be supported in an unproxied instance. Rationale: If LPS isn't running on the server anyway, we should encourage use of a standards-body standard instead.
- RPC2
- XML-RPC MAY be supported in an unproxied instance. (The initial implementation for unproxied operation for Flash Laszlo is unlikely to support this.)
- RPC3
- SOAP MAY be supported in an unproxied instance. (The initial implementation for unproxied operation for Flash Laszlo is unlikely to support this.)
- RPC4
- The <connection> tag MAY be supported in an unproxied instance. (LPS 3.0 will not support this, but we could document the protocol so that this is possible.)
Specification
API
The <canvas> tag has an optional attribute proxied="true|false|inherit", which defaults to "inherit". If proxied="true|false", the application can only be compiled in that mode. (It is an error to provide a request parameter with a different compiler setting, and the developer console UI disables options that generate this request.) If proxied="inherit", the application is compiled either for proxied or unproxied operation, depending upon the value of a compilation switch (which defaults to unproxied).
If an application is compiled for proxied operation, all data and media requests are proxied (the same as LPS 2.x), and the RPC tags are supported. If proxied="false", data and media requests are unproxied, and the compiler performs error detection:
- All data and media requests are unproxied.
- The presence of the <connection> or RPC tag results in a compiler warning.
- The presence of e.g. <view resource="http:logo.png"/>, where the compiler can easily infer that the value of the resource attribute will result in a runtime request for a media type that is not supported in an unproxied media request, results in a compiler warning.
- A runtime request for an unsupported service (e.g. myView.setResource('http:logo.png')) will result in a debugger warning, if debugging is enabled.
The <library> tag has an optional attribute proxied="true|false|inherit". This defaults to "inherit", which means that the library is compiled with the same proxied setting as the canvas file that includes it. It is a compilation error for the library tag specifies a proxied value of "true" or "false" and this value is different than the (explicit or implicit) proxied value of the canvas file that includes it.
In other words, a canvas file may include only library files that have the same value for their proxied attribute, or the (default) value of "inherit". You can't mix and match, and the presence of the <library proxied> attribute is a way to document to developers and to the compiler that a library can only work in one mode of operation.
Query Parameter
This is a proposal for query parameter to the application request URL (e.g. 'http://lps-3.0/hello.lzx'), to specify whether the application is compiled for proxied or unproxied operation.
Add a query parameter, 'lzproxied', to the application request URL (e.g. 'http://lps-3.0/hello.lzx?proxied=true'). Like the 'debug' query parameter, this parameter acts as a compiler option, and affects the way an application is compiled. The value of the lzproxied parameter is 'true' , 'false', or (the default).
There are two ways to specify whether an application is compiled for proxied operation: the 'lzproxied' query parameter, and the 'proxied' attribute of the <canvas> document root element. Either of these can specify that the application is proxied, that it is unproxied, or that whether it is proxied is determined by another source. If both of these mechanisms are used, they must agree, otherwise it is a compiler error (for example, a '?proxied=true' request for an application that contains <canvas proxied="false">). If neither is used, the application is proxied.
| lzproxied query parameter | <canvas proxied=> | result |
|---|---|---|
| not present | not present | proxied |
| not present | inherit | proxied |
| not present | true | proxied |
| not present | false | unproxied |
| true | not present | proxied |
| true | inherit | proxied |
| true | true | proxied |
| true | false | error |
| false | not present | unproxied |
| false | inherit | unproxied |
| false | true | error |
| false | false | unproxied |
Rationale
The existence of the query parameter is so that an application that can work in either proxied or unproxied mode, can be compiled for either mode without changes to its source code. In particular, this makes it easy to compare the proxied and unproxied operation of an application, and to hold off on committing to the deployment mode for an application.
The existence of the query parameter also makes it possible to implement an HTTP-based user interface (in the form of additional controls on the developer console) for specifying compiler options.
It is also consistent with the debug and runtime target compiler options (and with the undocumented 'profile' compiler option).
The 'lz' prefix namespace is used by convention to reduce the chance of accidental collision within an application-level query parameter. This is different from the 'debug' query parameter and some other pre-3.0 query parameters, but matches all newly introduced query parameters (e.g. 'lzr' to select a runtime target).
The 'proxied' base name is the same as the name of the <canvas> and <library> attribute.
Requesting a Proxied Application
This is a proposal for a bare-bones developer interface for creating unproxied applications, to make the serverless feature available for LPS 3.0b2. LPS 3.0 final may implement a higher-level mechanism --- for example, a button that downloads a zip file that can be unzipped in the server directory --- but this is the way a developer using LPS 3.0b2 would create a LZX application and library files.
This proposal makes use of the 'lzproxied' query parameter that is the subject of a previous proposal.
Summary
In brief, the proposal is that requesting an unproxied application /path/to/canvas.lzx has the side effect of creating a file /path/to/canvas.lzx.swf. This file, or the directory that contains this file, can be copied to the htdoc directory of a server that doesn't include LPS.
The file is called canvas.lzx.swf instead of canvas.swf to preserve Laszlo "branding" --- just as the presence of *.php or *.jsp in a URL is good for the awareness of PHP and Java, even though .htaccess can be configured not to require this filename extensions in the URL. Tthis also makes it easier to clean up after the compiler (see below). It also makes it less likely that compiling an application (logo.lzx) will overwrite a file that it includes (if logo.lzx includes logo.swf).
The file is placed in the same directory as the source file so that relative references to datasets and media requests will work; this was after considering another proposal where all files go in a 'build' subdirectory of the source directory, for ease of deletion.
This proposal does not cover the interaction of serverless deployment with dynamic libraries, which requires an additional specification (the creation of a set of library swfs, and path renaming conventions for libraries outside the application source directory).
Definitions
The canvas source file of an application is the main file, which is referenced in compilation requests and has a <canvas> root element.
An HTTP request is backed by an LZX source file S if the request is for an LZX application whose main (canvas) source file is at S. For example, a request for 'http://lps-3.0/my-apps/hello.lzx' might be backed by the source file ' /Applications/Laszlo\ Presentation\ Server\ 3.0/Server/lps-3.0/my-apps/hello.lzx'.
An HTTP request is backed by an LZX object file O if the request is for an application whose object file is O.
The application source files for an application are the XML, text, media, and font files that its canvas source file, and the library files that it recursively includes using <include> and <import>, reference via <include>, <import>, <resource>, <frame>, , and <style> elements, and through <view> and <datasource> elements that use local file references.
An HTTP request is a request for an unproxied application iff either or both of the followiing are true: the URL contains the query parameter 'lzproxied=true'; or the request is backed by a file whose document root element contains the 'proxied' attribute, e.g. <canvas proxied='true'>.
Proposal
During development, an HTTP request for an unproxied application that is backed by /path/to/canvas.lzx may cause the compiler to create a file /path/to/canvas.lzx.swf (the object file). Recompilation occurs when all of the following conditions are true:
- The allowRecompile LPS configuration property is 'true'
- The compMgrDependencyOption LPS configuration property is not 'never'
- One or more of the following conditions is true:
- The object file does not exist
- The object file is older than any of the application source files
- The value of the allowRecompile property is 'always'
An HTTP request for an unproxied application returns the object file from the source directory instead of from the LPS cache.
Use Case: Development Development of an unproxied application is the same as development of a proxied application. The object file is placed in the source directory instead of in the LPS cache, but this is transparent to the user (except by browsing the file system).
Use Case: Cleaning Up
> rm *.lzx.swf
Use Case: Serverless Deployment of a single file
- Using LPS, request the application URL.
- Copy the *.lzx.swf file to a directory on the deployment server.
Use Case: Serverless Deployment of a directory This is necessary to deploy an application that consists of several deployment files; for example, data and media files in the source directory that are requested during application execution.
- Using LPS, request the application URL.
- Copy the source directory to the deployment server.
Use Case: Serverless Sourceless Deployment Same as above, except where it is desirable to avoid the exposure of the application source files on the deployment server.
- Using LPS, request the application URL.
- Make a copy of the source directory. The copy is the "staging directory".
- Remove all *.lzx files from the staging directory. (Hey, this is far from ideal, but at least it's possible. I said this was low-level...)
- Remove any other data and media files that are not referenced during application execution.
- Copy the staging directory to the deployment server.
Pending Proposals
Pluggable Proxy Proposal
This is an amendment to the above design to allow direct media requests from within a proxied application.
Motivation
Adam: I still think that I should be able to make media requests bypass the proxy on a request-by-request basis.
Consider the case where I have some gif resources and some jpg resources. I need the server to transcode the gifs, but I would probably want to bypass the server for the jpgs.
Design
function proxyRequiredFiles(url) {
var suffix = ...;
var supportedFiles = {'jpg': 1, 'jpeg': 1, 'mp3': 1};
if (canvas.proxied && !supportedFiles[suffix])
return makeProxyRequest(url);
return url;
}
LzView.setRequestPolicy(proxyRequiredFiles);
With a pluggable policy, you can use the declarative syntax for initialization:
<view resource=""/> <view resource="
"/>
and for constraints:
<view resource="${parent.logo}"/>
A policy that directs *.jpeg and *.jpg files directly to the named host, and other files to the proxy, will have the correct result and will be applied centrally, instead of replicated at each request site. If setSource() is the only way to do this, then I think you need something like this for initialization:
<view oninit="setSource('http://media.com/logo.gif', ...)"/>
<view resource="
"/>
and constraints are considerably more complicated.
Import Tag Proposal
Henry proposes adding the proxy attribute to the <import> tag. Details TDB.
Dataset and Datasource Proposal
Henry proposes adding the proxy attribute to datasources and datasets. Details TBD.
Alternate Proposals
The specification above is a variant of the Compilation Switch + Toplevel Attribute proposal below. This is an archive of the proposals that it was selected from.
Compilation Switch
An application that is intended for unproxied operation is compiled with a compiler switch external to the application sources. I don't want to specify a user interface for this now. (It might be a checkbox, or a button that says "Create unproxied zip", that is implemented as a ?lzproxied=false request parameter --- similar to the way an application is compiled for debugging via the ?debug=true request parameter today.) In an application that is compiled with this mode:
- All data and media requests are unproxied.
- The presence of the <connection> or RPC tag results in a compiler warning.
- The presence of e.g. <view resource="http:logo.png"/>, where the compiler can easily infer that the value of the resource attribute will result in a runtime request for a media type that is not supported in an unproxied media request, results in a compiler warning.
- A runtime request for an unsupported service (e.g. myView.setResource('http:logo.png')) will result in a debugger warning, if debugging is enabled.
Pros:
- A library or application can be compiled for proxied or unproxied operation without source changes.
- There's very little to specify (and therefore that there's very little to get wrong).
Cons:
- The fact that an application is only intended for proxied (or for unproxied) operation is not documented in the sources; therefore:
- You have to remember to press the correct button when you want to test the application in its deployment mode.
- This doesn't support a mixture of proxied and unproxied requests within a single application.
Toplevel Attribute
The <canvas> tag has an optional attribute proxied="true|false". This defaults to true, for compatibility with LPS 2.x. (Default deployment mode is actually an issue that is independent of these designs; I'll send a separate message about that.) If proxied="true", all data and media requests are proxied (the same as LPS 2.x), and the RPC tags are supported. If proxied="false", data and media requests are unproxied, and the compiler performs error detection as in the Compilation Switch design, above.
The <library> tag has an optional attribute proxied="true|false|inherit". This defaults to "inherit", which means that the library is compiled with the same proxied setting as the canvas file that includes it. It is a compilation error for the library tag specifies a proxied value of "true" or "false" and this value is different than the (explicit or implicit) proxied value of the canvas file that includes it.
In other words, a canvas file may include only library files that have the same value for their proxied attribute, or the (default) value of "inherit". You can't mix and match, and the presence of the <library proxied> attribute is a way to document to developers and to the compiler that a library can only work in one mode of operation.
Pros:
- Only one attribute in the canvas file need be changed to switch between proxied and unproxied operation.
- The sources contain machine-readable documentation as to the intended deployment mode.
Cons:
- The canvas file has to be edited to switch between proxied and unproxied operation.
- This doesn't support a mixture of proxied and unproxied requests within a single application.
Compilation Switch + Toplevel Attribute
The <canvas> tag has an optional attribute proxied="true|false|inherit", which defaults to "inherit". If proxied="true|false", the application can only be compiled in that mode. (It is an error to provide a request parameter with a different compiler setting, and the developer console UI disables options that generate this request.) If proxied="inherit", the application is compiled either for proxied or unproxied operation, depending upon the value of a compilation switch (which defaults to unproxied).
The behavior for libraries is the same as specified in the Toplevel Attribute design.
Pros:
- A library or application can be compiled for proxied or unproxied operation without source changes.
- The sources contain machine-readable documentation as to the intended deployment mode.
Cons:
- Doesn't support a mixture of proxied and unproxied requests within a single application.
API Implementation
Currently, if you have an app named /path/to/myapp.lzx, the compiler will notice if either lzproxied=true in the query args or if <canvas proxied="true">, and if so it will compile the main app into a swf file at /path/to/myapp.lzx.swf
If any runtime-loadable libraries (snippets) are referenced via the <import> tag in the main app file, they are placed in a subdirectory named 'build/myapp/...' subdirectory. For example
/path/to/myapp.lzx:
<canvas>
<import stage="defer" href="mylib/library.lzx"/>
</canvas>
will place the compiled library.lzx file library file in /path/to/build/myapp/mylib/library.lzx.swf
- The compiler will notice if you have a query arg of "lzproxied=true|false" when it compiles an application.
This value is then "baked in" to the canvas, so that when you load the app at a later time (even serverless), and do not include any lzproxied arg explicitly in the URL, it will default to the value which it had at compile time.
Deployment Example
Say you want to deploy the Amazon demo as a serverless application.
- You would first compile it with lzproxied="false" in the query args
(or you could modify the source to say <canvas proxied="false">)
lzc -Dlzproxied=false amazon.lzx
or
wget -O amazon.swf http://localhost:8080/lps-dev/demos/amazon/amazon.lzx
In both cases, a compiled file named amazon.lzx.swf will be written to the app directory. (lzc will also write out amazon.swf, at the moment, which will be identical).
- Copy this swf file, along with any needed runtime resources, to your deployment server
The app can now be browsed to as amazon.lzx.swf. There is no need to set lzproxied=false in the query args, it has been set as the default on the canvas in the app by the compiler.
TBD
- How to compile an application for serverless deployment.
- The syntax used in data and media requests.
- The failure mode for APIs that are only available with an attached server, when an application is compiled or deployed in serverless mode.

"/>
<view resource="