|
Unite API | |||||||
| PREV NEXT | FRAMES NO FRAMES | |||||||
This API document describes the JavaScript bindings for the Opera Unite Web Server, available through Opera Unite applications. Opera Unite applications supply Web services served directly from the user's computer.
Opera Unite applications are packaged like Opera Widgets with a config.xml file.
Note that no methods in this API return actual arrays. Instead they return
objects whose properties can be iterated over in an array style syntax, i.e. array[i].
Methods like push(), shift(), sort(), and so on are not available.
In order to make the file system and its methods available, you need to add a feature element to your config.xml file like this:
<widget>
...
<feature name="http://xmlns.opera.com/webserver">
<param name="servicepath" value="chat" />
</feature>
...
</widget>
The servicepath parameter is required and defines the path the service will be accessed from. See the note on service URLs for more information.
The entry point to the API becomes available as a JavaScript object opera.io.webserver.
Opera Unite users may start a Web server on different devices running Opera, for example on a home and work computer, a living room media center and a mobile phone. The user may install a set applications on each Web server, providing several services . A service is typically a single application, for example a file sharing service or a multiplayer chess service. Services can accessed on the following general URL:
http://device.user.proxy/service/path
For example:
http://work.john.operaunite.com/wiki/add
The username is the user's My Opera username.
The device name is whatever the user has chosen when enabling the Web server. It's tied to one instance of Opera.
The proxy is a server run by Opera, proxying requests between servers and clients.
The service, or service path, is the IRI name of the service, as defined in config.xml.
The path represents a file or instruction the service will handle.
Note that only valid IRI characters can be used as part of the device name, username and service name.
The function of a Web server is to listen to requests from clients, process them and issue a response, for example send a Web page or the result of a script. Requests occur when the user visits a particular service URL. The request may contain form data, send via GET and POST and uploaded files.
In the case of the Opera Unite Web Server you listen to requests from clients by adding event listeners to the opera.io.webserver object:
opera.io.webserver.addEventListener('path',somehandler,false);
The path corresponds to the first path component in the URL after the service name, for example:
opera.io.webserver.addEventListener('add',addHandler,false);
In this case, if the user visits the URL
http://work.john.operaunite.com/wiki/add
The application will pick it up and call the supplied addHandler function.
Handler functions are passed a WebServerRequestEvent object as an argument. This event object gives access to the incoming connection (WebServerConnection), the incoming request (WebServerRequest), and the response (WebServerResponse) the author can write data to. The addhandler could look something like this:
function addHandler(e)
{
//Shorthands
var req = e.connection.request;
var res = e.connection.response;
//Get article from POST data
var article = req.bodyItems['article'][0];
//...Store the article data
//Write a response back to the client
res.write('Article updated');
res.close();
}
Data sent as GET are available in the queryItems property of the request. Data sent as POST are available in the bodyItems property. The body of the request is also available in the raw form in the body property. If files were attached, these are available in the files property of the request.
The response object has methods for sending different kinds of data, for example writeImage() and writeFile().
You may supply a custom protcol string, status code and headers, but these must be set before data is written to the response.
Note that requests may not begin with '_', as this is reserved for special, system generated events.
The Web server supports three special requests.
http://work.john.operaunite.com/share. If you do not listen for this request, the file public_html/index.html will be served when the user visits the root of the server._close. Use this to gain fine grained control of the requests made to the server. You'll need to use WebServerRequest.uri to differentiate between different requests. This request also catches _index, but not _close.id property contains the id of the closed connection.If the developer adds event listeners for both _request and some specific path, the event handler for the specific path will be called before the _request handler. Handlers for _index are also fired before _request.
You can redispatch a request to a new URI by changing the WebServerRequest.uri property and calling the WebServerResponse.closeAndRedispatch() method. This is useful for example for correcting commonly mistyped URLs, chaining requests and providing authentication across the entire service. For example:
if ( ! authenticated )
{
request.uri = opera.io.webserver.currentServicePath + 'loginform';
response.closeAndRedispatch();
}
And headers, GET or POST data in the original request are sent along with the redispatched request.
Note that uri must be set to a relative URI path, starting with '/' and the name of the service (the opera.io.webserver.currentServicePath property), potentially followed by more path components, for example '/blog/add'.
If a request is redispatched, none of the special event handlers, like _request will be fired.
If an incoming request URI matches a shared file or a file in public_html, the file will be served.
However, if you listen for the _request event, even requests to files will be intercepted. In order to serve the
file, you'll need to call WebServerResponse.closeAndRedispatch() without changing the URI.
You can share files from a local disk through your Web server. Use the opera.io.webserver.sharePath() and opera.io.webserver.unsharePath() methods.
The first takes two arguments - a URL path and a File object retrieved using the File I/O API. The path denotes which sub-path of your service the file will be accessible on.
Here's an example:
//mount a directory using File I/O, get a reference to it called 'dir'
opera.io.webserver.sharePath('myShare', dir);
Assuming the device is called 'work', the user is called 'john' and the service is called 'fileSharing', the directory will now be available on the URL http://work.john.operaunite.com/fileSharing/myShare.
To unshare a path, call the opera.io.webserver.unsharePath() method with the path you've previously shared something on:
opera.io.webserver.unsharePath('myShare');
Note that for security reasons the contents of a shared directory is not listed automatically. If you visit the URL of a shared directory, you will get a 404 error code. You may still access files under the shared directory, for example:
http://work.john.operaunite.com/fileSharing/myShare/notes.txt
You'll need to listen for the name of the share as a request, and serve a listing to the client yourself.
If you do listen for the _request event to serve directory listings, you will also need to check for requests to files under a shared path. If you catch such references, you need to call WebServerResponse.closeAndRedispatch() without changing the WebServerRequest.uri property of the request to send the request back to the Web server. On the second pass, the Web server will serve the shared file directly.
You can upload files using a normal file upload form. Once uploaded, the file will be available in the WebServerRequest.files property. This is a special File object that functions like a directory. You can iterate through it to locate your uploaded file.
The File object and its children will be deleted when the request object goes out of scope. You must make sure to read it or copy it before this happens.
for ( var i = 0, file; file = request.files[i]; i++ )
{
file.copyTo('/storage/' + file.name);
}
The value of the name property of the File object will be the same as the file name the uploaded file had on the user's disk.
Each uploaded file has a metaData property, which contains a dictionary of headers for that uploaded file.
You can set cookies using the Set-Cookie header as you would for a normal Web page using the WebServerResponse.setResponseHeader() method:
response.setResponseHeader('Set-Cookie', 'session=' + seesionId );
The cookie will not be valid for any other domains, nor the admin subdomain. Setting the domain attribute does not override this. This means that if the current request is made out to the admin subdomain, setting a cookie in the response will set it for the admin subdomain.
If you do not specify a path, the Web server will set it to the path of the current service. Cookies are not shared among services.
In order to allow administration of the service, the developer will need to be able to positively identify a user as the owner of the service. Administration pages can be accessed through the admin subdomain of the service.
The following URL pattern will be interpreted as an administration page:
http://admin.device.user.operaunite.com/path
For example:
http://admin.work.john.operaunite.com/fileSharing/
URLs on this form can only be accessed successfully from the same instance of Opera running the application. If it is accessed in any other way, for example through another browser, the user will be redirected to the non-admin version of the page.
In cases where a service page is successfully accessed through http://admin., the corresponding WebServerConnection object will have its isOwner property set to true. Developers can check this property and provide an administration interface:
if ( e.connection.isOwner )
{
showAdminPage();
}
The admin page for the root service is special and may be used to provide admin-links to other installed applications. This service is integrated into Opera. It's available on the URL:
http://admin.work.john.operaunite.com/
When accessing service pages in the same instance, Opera will sometimes either ask the user to confirm the action or block the access. The reason for asking for a confirmation is to protect the user from malicious links which may result in cross-posting and destructive operations on the application. The table below summarized the different cases:
| From page \ To Page | Admin root, start URL | Admin root, other URL | Admin same service, start URL | Admin same service, other URL | Admin other service, any URL | Non-admin, any URL |
|---|---|---|---|---|---|---|
| From panel, bookmarks or UI | open | open | open | open | open | open |
| From root admin, any URL | open | open | open | open | open | open |
| From service admin, any URL | open | block | open | open | block | open |
| From non-admin, locally hosted root (isLocal = true) | open | warning | open | warning | warning | open |
| From non-admin, locally hosted service (isLocal = true) | warning | warning | open | warning | warning | open |
| From regular page | warning | warning | warning | warning | warning | open |
The start URL of a service or the root, is the minimal URL, ending in a slash, without path, filename, query arguments or hash.
If a warning is shown, and the user chooses to continue, any POST request is changed to a GET request.
In order to maintain security, the services will by default ignore requests for administration access from other instances or browsers. There is no native way of doing remote administration of applications. Developers can relax this model by implementing additional administration using authentication and nonces. It is not possible to access the admin subdomain through an IP address or through localhost, so the same applies in this case.
| Class Summary | |
| opera.io.webserver | Web server implementation |
| WebServerConnection | Connection made to the Web server. |
| WebServerRequest | Request made to the Web server. |
| WebServerRequestEvent | Event fired when requests are made to the Web server. |
| WebServerResponse | Response from the Web server. |
| WebServerServiceDescriptor | Data about a service. |
/** @fileoverview <h3>Opera Unite Web server APIs</h3> <p>This API document describes the JavaScript bindings for the Opera Unite Web Server, available through Opera Unite applications. Opera Unite applications supply Web services served directly from the user's computer.</p> <p>Opera Unite applications are packaged like Opera Widgets with a config.xml file.</p> <p>Note that no methods in this API return actual arrays. Instead they return objects whose properties can be iterated over in an array style syntax, i.e. <code>array[i]</code>. Methods like <code>push()</code>, <code>shift()</code>, </code>sort()</code>, and so on are not available.</p> <h4>Enabling the Web server API</h4> <p>In order to make the file system and its methods available, you need to add a <code>feature</code> element to your config.xml file like this:</p> <pre><code><widget> ... <feature name="http://xmlns.opera.com/webserver"> <param name="servicepath" value="chat" /> </feature> ... </widget></code></pre> <p>The <code>servicepath</code> parameter is required and defines the path the service will be accessed from. See the <a href="#urls">note on service URLs</a> for more information.</p> <p>The entry point to the API becomes available as a JavaScript object <code>opera.io.webserver</code>.</p> <h4 id="urls">Opera Unite applications and URLs</h4> <p>Opera Unite users may start a Web server on different devices running Opera, for example on a home and work computer, a living room media center and a mobile phone. The user may install a set applications on each Web server, providing several services . A service is typically a single application, for example a file sharing service or a multiplayer chess service. Services can accessed on the following general URL:</p> <p><code>http://device.user.proxy/service/path</code></p> <p>For example:</p> <p><code>http://work.john.operaunite.com/wiki/add</code></p> <p>The username is the user's My Opera username.</p> <p>The device name is whatever the user has chosen when enabling the Web server. It's tied to one instance of Opera.</p> <p>The proxy is a server run by Opera, proxying requests between servers and clients.</p> <p>The service, or service path, is the IRI name of the service, as defined in config.xml.</p> <p>The path represents a file or instruction the service will handle.</p> <p>Note that only valid IRI characters can be used as part of the device name, username and service name.</p> <h4>Working with requests and responses</h4> <p>The function of a Web server is to listen to requests from clients, process them and issue a response, for example send a Web page or the result of a script. Requests occur when the user visits a particular service URL. The request may contain form data, send via GET and POST and uploaded files.</p> <p>In the case of the Opera Unite Web Server you listen to requests from clients by adding event listeners to the <code>opera.io.webserver</code> object:</p> <pre><code>opera.io.webserver.addEventListener('path',somehandler,false);</code></pre> <p>The path corresponds to the first path component in the URL after the service name, for example:</p> <pre><code>opera.io.webserver.addEventListener('add',addHandler,false);</code></pre> <p>In this case, if the user visits the URL</p> <p><code>http://work.john.operaunite.com/wiki/add</code></p> <p>The application will pick it up and call the supplied <code>addHandler</code> function.</p> <p>Handler functions are passed a {@link WebServerRequestEvent} object as an argument. This event object gives access to the incoming connection ({@link WebServerConnection}), the incoming request ({@link WebServerRequest}), and the response ({@link WebServerResponse}) the author can write data to. The <code>addhandler</code> could look something like this:</p> <pre><code>function addHandler(e) { //Shorthands var req = e.connection.request; var res = e.connection.response; //Get article from POST data var article = req.bodyItems['article'][0]; //...Store the article data //Write a response back to the client res.write('Article updated'); res.close(); }</code></pre> <p>Data sent as GET are available in the <code>queryItems</code> property of the request. Data sent as POST are available in the <code>bodyItems</code> property. The body of the request is also available in the raw form in the <code>body</code> property. If files were attached, these are available in the <code>files</code> property of the request.</p> <p>The <code>response</code> object has methods for sending different kinds of data, for example <code>writeImage()</code> and <code>writeFile()</code>.</p> <p>You may supply a custom protcol string, status code and headers, but these must be set before data is written to the response.</p> <p>Note that requests may not begin with '_', as this is reserved for special, system generated events.</p> <h5>Special requests: _index, _request, _close</h5> <p>The Web server supports three special requests.</p> <dl> <dt>_index</dt> <dd>This request occurs when a user visits the root of the service, e.g. <code>http://work.john.operaunite.com/share</code>. If you do not listen for this request, the file <code>public_html/index.html</code> will be served when the user visits the root of the server.</dd> <dt>_request</dt> <dd>This is a special request that catches all incoming requests, except for <code>_close</code>. Use this to gain fine grained control of the requests made to the server. You'll need to use {@link WebServerRequest#uri} to differentiate between different requests. This request also catches <code>_index</code>, but not <code>_close</code>.</dd> <dt>_close</dt> <dd>This request occurs when a connection is closed. The connection property of the resulting event is a dummy object, while the <code>id</code> property contains the id of the closed connection.</dd> </dl> <p>If the developer adds event listeners for both _request and some specific path, the event handler for the specific path will be called before the _request handler. Handlers for _index are also fired before _request.</p> <h5>Redispatching requests</h5> <p>You can redispatch a request to a new URI by changing the {@link WebServerRequest#uri} property and calling the {@link WebServerResponse#closeAndRedispatch} method. This is useful for example for correcting commonly mistyped URLs, chaining requests and providing authentication across the entire service. For example:</p> <pre><code> if ( ! authenticated ) { request.uri = opera.io.webserver.currentServicePath + 'loginform'; response.closeAndRedispatch(); } </code></pre> <p>And headers, GET or POST data in the original request are sent along with the redispatched request.</p> <p>Note that <code>uri</code> must be set to a relative URI path, starting with '/' and the name of the service (the {@link opera.io.webserver#currentServicePath} property), potentially followed by more path components, for example '/blog/add'.</p> <p>If a request is redispatched, none of the special event handlers, like <code>_request</code> will be fired.</p> <h5>Requests and files</h5> <p>If an incoming request URI matches a shared file or a file in <code>public_html</code>, the file will be served.</p> <p>However, if you listen for the <code>_request</code> event, even requests to files will be intercepted. In order to serve the file, you'll need to call {@link WebServerResponse#closeAndRedispatch} without changing the URI.</p> <h4>Sharing files</h4> <p>You can share files from a local disk through your Web server. Use the {@link opera.io.webserver#sharePath} and {@link opera.io.webserver#unsharePath} methods. The first takes two arguments - a URL path and a <code>File</code> object retrieved using the File I/O API. The path denotes which sub-path of your service the file will be accessible on.</p> <p>Here's an example:</p> <pre><code>//mount a directory using File I/O, get a reference to it called 'dir' opera.io.webserver.sharePath('myShare', dir);</code></pre> <p>Assuming the device is called 'work', the user is called 'john' and the service is called 'fileSharing', the directory will now be available on the URL <em>http://work.john.operaunite.com/fileSharing/myShare</em>.</p> <p>To unshare a path, call the {@link opera.io.webserver#unsharePath} method with the path you've previously shared something on:</p> <pre><code>opera.io.webserver.unsharePath('myShare');</code></pre> <p>Note that for security reasons the contents of a shared directory is not listed automatically. If you visit the URL of a shared directory, you will get a 404 error code. You may still access files under the shared directory, for example:</p> <p><em>http://work.john.operaunite.com/fileSharing/myShare/notes.txt</em></p> <p>You'll need to listen for the name of the share as a request, and serve a listing to the client yourself.</p> <p>If you do listen for the <code>_request</code> event to serve directory listings, you will also need to check for requests to files under a shared path. If you catch such references, you need to call {@link WebServerResponse#closeAndRedispatch} without changing the {@link WebServerRequest#uri} property of the request to send the request back to the Web server. On the second pass, the Web server will serve the shared file directly.</p> <h4>Uploading files</h4> <p>You can upload files using a normal file upload form. Once uploaded, the file will be available in the {@link WebServerRequest#files} property. This is a special <code>File</code> object that functions like a directory. You can iterate through it to locate your uploaded file.</p> <p>The File object and its children will be deleted when the request object goes out of scope. You must make sure to read it or copy it before this happens.</p> <pre><code>for ( var i = 0, file; file = request.files[i]; i++ ) { file.copyTo('/storage/' + file.name); }</code></pre> <p>The value of the name property of the File object will be the same as the file name the uploaded file had on the user's disk.</p> <p>Each uploaded file has a <code>metaData</code> property, which contains a dictionary of headers for that uploaded file.</p> <h4>Working with cookies</h4> <p>You can set cookies using the <code>Set-Cookie</code> header as you would for a normal Web page using the {@link WebServerResponse#setResponseHeader} method:</p> <pre><code>response.setResponseHeader('Set-Cookie', 'session=' + seesionId );</code></pre> <p>The cookie will not be valid for any other domains, nor the admin subdomain. Setting the domain attribute does not override this. This means that if the current request is made out to the admin subdomain, setting a cookie in the response will set it for the admin subdomain.</p> <p>If you do not specify a path, the Web server will set it to the path of the current service. Cookies are not shared among services.</p> <h4>Generating administration pages: The admin subdomain and WebServerRequest.isOwner</h4> <p>In order to allow administration of the service, the developer will need to be able to positively identify a user as the owner of the service. Administration pages can be accessed through the admin subdomain of the service.</p> <p>The following URL pattern will be interpreted as an administration page:</p> <p><em>http://<strong>admin.</strong>device.user.operaunite.com/path</em></p> <p>For example:</p> <p><em>http://admin.work.john.operaunite.com/fileSharing/</em></p> <p>URLs on this form can only be accessed successfully from the same instance of Opera running the application. If it is accessed in any other way, for example through another browser, the user will be redirected to the non-admin version of the page.</p> <p>In cases where a service page is successfully accessed through http://admin., the corresponding {@link WebServerConnection} object will have its <code>isOwner</code> property set to true. Developers can check this property and provide an administration interface:</p> <pre><code>if ( e.connection.isOwner ) { showAdminPage(); }</code></pre> <p>The admin page for the root service is special and may be used to provide admin-links to other installed applications. This service is integrated into Opera. It's available on the URL:</p> <p><em>http://admin.work.john.operaunite.com/</em></p> <p>When accessing service pages in the same instance, Opera will sometimes either ask the user to confirm the action or block the access. The reason for asking for a confirmation is to protect the user from malicious links which may result in cross-posting and destructive operations on the application. The table below summarized the different cases:</p> <TABLE style=""> <TBODY> <TR> <TH class="right thGroup">From page \ To Page</TH> <TH>Admin root, start URL</TH> <TH>Admin root, other URL</TH> <TH>Admin same service, start URL</TH> <TH>Admin same service, other URL</TH> <TH>Admin other service, any URL</TH> <TH>Non-admin, any URL</TH> </TR> <TR> <TH class="right">From panel, bookmarks or UI</TH> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> </TR> <TR> <TH class="right">From root admin, any URL</TH> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="open">open</TD> </TR> <TR> <TH class="right">From service admin, any URL</TH> <TD class="open">open</TD> <TD class="block">block</TD> <TD class="open">open</TD> <TD class="open">open</TD> <TD class="block">block</TD> <TD class="open">open</TD> </TR> <TR> <TH class="right">From non-admin, locally hosted root (isLocal = true)</TH> <TD class="open">open</TD> <TD class="warning">warning</TD> <TD class="open">open</TD> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="open">open</TD> </TR> <TR> <TH class="right">From non-admin, locally hosted service (isLocal = true)</TH> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="open">open</TD> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="open">open</TD> </TR> <TR> <TH class="right">From regular page</TH> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="warning">warning</TD> <TD class="open">open</TD> </TR> </TBODY> </TABLE> <p>The start URL of a service or the root, is the minimal URL, ending in a slash, without path, filename, query arguments or hash.</p> <p>If a warning is shown, and the user chooses to continue, any POST request is changed to a GET request.</p> <p>In order to maintain security, the services will by default ignore requests for administration access from other instances or browsers. There is no native way of doing remote administration of applications. Developers can relax this model by implementing additional administration using authentication and nonces. It is not possible to access the admin subdomain through an IP address or through localhost, so the same applies in this case.</p> @author Hans S. Toemmerholt, Web Applications, Opera Software ASA */ /** * This class has no constructor. * @constructor * @class * Web server implementation * * <p>The WebServer offers access to information about the proxy, device and currently running service. It also maintains * incoming connections.</p> * * <p>Services running on the Web server are accessed through a URL on the form: * <code>http://device.host.proxy/service/path</code>, e.g. * <code>http://work.john.operaunite.com/wiki/addEntry</code></p> * */ var opera.io.webserver = function () { /** * The public facing IP address of this Web server, as seen by the proxy. * * If the Web server does not accept direct connections, this property is <code>null</code>. * @type String */ this.publicIP = ''; /** * The public facing port of this Web server, as seen by the proxy. * * If the Web server does not accept direct connections, this property is <code>null</code>. * @type int */ this.publicPort = 0; /** * The current connections made to this Web server. Readonly. * * <p>Array-like object containing {@link WebServerConnection} objects representing the current connections to * this Web server.</p> * * <p>Connections remain in this collection even if they are closed. They are removed when there are * no longer any references to the connection elsewhere in the system.</p> * * @type Object */ this.connections = {}; /** * The URL the currently running service was downloaded from. Readonly. * * <p>This property can be used to make a download link to the service and can also function * as part of an auto update scheme.</p> * * @type string */ this.originURL = ''; /** * The name of the service currently accessing the webserver object, for example 'File Sharing'. Readonly. * * <p>The name of the service, for example as defined in the <code>widgetname</code> element * in the <code>config.xml</code> of a Opera Unite application.</p> * * @type String */ this.currentServiceName = ''; /** * The path of the service currently accessing the webserver object, for example '/fileSharing/'. Readonly. * * <p>The path of the service, for example as defined in the <code>servicePath</code> element * in the <code>config.xml</code> of an Opera Unite application. In contrast to the <code>serviceName</code>, * this name can only contain characters that are valid in an IRI.</p> * * <p>The path includes a leading and trailing slash.</p> * * <p>This way a service called "My Cool File Sharing (tm) (c)" can be * identified as simply "share" in it's URL, i.e. * <code>http://work.john.operaunite.com/share</code>.</p> * * <p>In the example above this property would contain '/share/'.</p> * * <p>Note that anything after the first path component is handled by * the service.</p> * * @type String */ this.currentServicePath = ''; /** * The name of the proxy the Web server is connected to, for example 'operaunite.com'. Readonly. * * The proxy name is the last part of the full host name, * e.g. <code>operaunite.com</code> as in <code>http://work.john.operaunite.com/wiki</code> * * @type String */ this.proxyName = ''; /** * The hostname of the Webserver, for example 'work.john.operaunite.com'. Readonly. * * <p>You may run Web servers on different devices. The hostname contains the device name, * username and proxy address, for example <code>work.john.operaunite.com</code> * as in <code>http://work.john.operaunite.com/wiki</code>.</p> * * <p>Note that this will always be a host name which contains the proxy name.</p> * * <p>This property will not contain the 'admin.' subdomain, if it is used.</p> * * @type String */ this.hostName = ''; /** * The name of the device the Web server is running on, for example 'work'. Readonly. * * You may run a Web server on different devices, like two different computers * in your home network and your mobile phone, e.g. <code>work</code> as in http://work.john.operaunite.com. * * @type String */ this.deviceName = ''; /** * The My Opera user name of the user owning the Web server, for example 'john'. Readonly. * * For authentication purposes, a <a href="http://my.opera.com">My Opera</a> user name is required for connecting to the * proxy and publishing services. * * @type String */ this.userName = ''; /** * The port this Web server is listening to, for example 8840. Readonly. * * You may run multiple Web servers from the same computer by assigning different port * numbers and device names to each instance of Opera running the Web server in opera:config. * Valid ports are in the range 0-65536 * * @type String */ this.port = ''; /** * Services running on this Web server. Readonly. * * Array-like object containing {@link WebServerServiceDescriptor} objects that describe the services currently running * on this device. You can use this property to discover and communicate with other services, and potentially share data * with them. * * @type Object */ this.services = []; /** * Get the MIME content type mapped to a particular file name. * * This function looks up the MIME content type associated with the given file name in Opera. * It can for example be used to set proper headers when serving special types of files. The file name * must contain a period ('.'). * * @param {String} file The file name to get a MIME type for, for example 'index.html'. * @returns {String} The MIME content type mapped to the given file name. */ this.getContentType = function ( file ) /** * Add an event listener for incoming requests. * * <p>Listening for requests is done by registering event listeners on the * Web server. The "event name" corresponds to the path fragment of the URL after * the service name, e.g. 'add' as in http://work.john.operaunite.com/wiki/add.</p> * * <p>Registered event handlers are called with an event of the type {@link WebServerRequestEvent}.</p> * * <p>Any request names starting with underscore ('_') is reserved and cannot be used.</p> * * <p>The exceptions are the following request names, which have special meanings:</p> * * <dl> * <dt>_index</dt> * <dd>Event fired when a user accesses the root of the service (i.e. http://work.john.operaunite.com/wiki). * Use this to supply a default start page or similar for your service.</dd> * <dt>_request</dt><dd>Event fired when a user accesses any URL under the service. Use this to catch * all requests to the server in a general fashion. You'll need to use the * {@link WebServerRequest#uri} to distinguish the actual request URI. Listening for this event will also catch * the <code>_index</code> request, but not <code>_close</code>.</dd> * <dt>_close</dt><dd>Event fired when a connection is closed. In this case the <code>connection</code> property * of the <code>event</code> object is null.</dd> * </dl> * * <p>Events for specific event listeners and _index events are fired before the _request event is fired. * Consider the following code example:</p> * * <pre><code>opera.io.webserver.addEventListener('_request', generalhandler, false); *opera.io.webserver.addEventListener('add', addhandler, false);</code></pre> * * <p>The handlers for a specific path, including _index is called before _request.</p> * * <p>If the user visits the URL http://work.john.operaunite.com/wiki/add, a {@link WebServerRequestEvent} is fired, * and the <code>addhandler</code> is called, before the <code>generalhandler</code> * method is called. This happens regardless of which event listener was registered first.</p> * * @param {String} pathFragment Path fragment to add a listener for. * @param {Function} handler Event listener function to add. * @param {boolean} useCapture Whether or not the capture phase should be used. */ this.addEventListener = function ( pathFragment, handler, useCapture ) { ; } /** * Remove an event listener from the server. * @param {String} pathFragment Path fragment to remove a listener for. * @param {Function} handler Event listener function to remove. * @param {boolean} useCapture Whether or not this applies to the capture phase. */ this.removeEventListener = function ( pathFragment, handler, useCapture ) { ; } /** * Shares a File * * <p>Shares a File from a mountpoint that has been acquired earlier, and makes * it available under the path specified in the second argument.</p> * * <p>The File can be a regular file, a directory or an archive.</p> * * <p>The share is automatically deleted when the application is closed.</p> * * <p>Example: If you have resolved a File to a given folder and then specify <code>opera.io.webserver.shareFile(myFile, 'share')</code>, * it will be shared as the URL <code>http://device.user.proxy/service/share</code></p> * * @param {File} file The File to share * @param {String} path The path this file will be shared as on the Web. * @deprecated This function will be removed shortly. Use {@link #sharePath} instead. */ this.shareFile = function ( file, path ) { ; } /** * Unshares a previously shared file * * When a file has been shared using shareFile, it can be unshared again * by calling this method with the same File reference used to share the file * * @param {File} file The file to unshare. * @deprecated This function will be removed shortly. Use {@link #unsharePath} instead. */ this.unshareFile = function ( file ) { ; } /** * Share the given file on the given URL path. * * <p>The path must be a valid URL path token, and should be a relative sub path of the service. * It should not start with '../' or '/', but you may specify additional path tokens, like 'media/gfx/logo.png'.</p> * * <p>The File can be a regular file, a directory or an archive, but it must be referenced by a mount point.</p> * * <p>ALREADY_SHARED_ERR will be thrown if something is already shared on the given path The share is automatically * deleted when the application is closed.</p> * * <p>Note that if you have added a <code>_request</code> event handler, you will need to compare the incoming requests * with the paths you have shared to see if the request matches a shared file. If so, you will need to call * {@link WebServerResponse#closeAndRedispatch} without changing the uri fo the request to send the request back to * the Web server. On the second pass, the Web server will serve the shared file directly.</p> * * <p>Example: In order to share a resolved File on the path 'media/gfx', you would do the following:</p> * * <pre><code>opera.io.webserver.sharePath('media/gfx', myFile);</code></pre> * * <p>The file will now be shared as the URL <code>http://device.user.proxy/service/media/gfx</code>.</p> * * @param {String} path URL path to share something on. * @param {File} file File to share on the given path. * @throws ALREADY_SHARED_ERR if something is already shared on the given path. */ this.sharePath = function ( path, file ) { ; } /** * Unshare a File previously shared on the given URL path * * <p>When a file has been shared using {@link #sharePath}, it can be unshared again * by calling this method with the same path used to share the file.</p> * * <p>Example: Assume that a file has been shared on the path 'media/gfx', i.e. on the URL * <code>http://device.user.proxy/service/media/gfx/</code>, calling this method as follows will unshare the file:</p> * * <pre><code>opera.io.webserver.unsharePath('media/gfx');</code></pre> * * @param {String} path URL path of the file to unshare. */ this.unsharePath = function ( path ) { ; } } /** * This class has no public constructor. * @constructor * @class * Data about a service. * * <p>Objects of this class contain basic information about a service and how to reach it. Information about * the service is usually taken from its config.xml.</p> * */ var WebServerServiceDescriptor = function () { /** * Whether or not this service requires HTTP Digest authentication. * @type boolean */ this.authentication = false; /** * The URL this service was originally downloaded from. * @type String */ this.originURL = ''; /** * The path to this service, as taken from the <code>widgetname</code> or <code>feature</code> elements * in the config.xml file of the service. * @type String */ this.servicePath = ''; /** * Name of this service. * @type String */ this.name = ''; /** * Description of this service. * @type String */ this.description = ''; /** * Author of this service. * @type String */ this.author = ''; /** * URI of this service. * * This is the full URI of the service, e.g. http://work.john.operaunite.com/wiki * * @type String */ this.uri = ''; } /** * This class has no public constructor. * @constructor * @class * Connection made to the Web server. * * <p>WebServerConnection holds the incoming request and gives the user access to the outgoing response, * as well maintaining the state of the connection.</p> */ var WebServerConnection = function () { /** * The incoming HTTP request on this connection. Readonly. * @type WebServerRequest */ this.request = {}; /** * The outgoing HTTP response that will be send to the client. Readonly. * @type WebServerResponse */ this.response = {}; /** * Whether or not this connection is made through the proxy. * * <p>This property will be false if you access the services through a local URL.</p> * * @type boolean */ this.isProxied = false; /** * Whether or not this connection is made directly through the Opera instance. * @type boolean */ this.isLocal = false; /** * Whether this connection is made from a page with a URL on the admin subdomain in the same instance running the service. * * <p>You can use this property to determine if the connection is coming from the owner (typically yourself) of the service and * therefore whether to, for example, grant it special privileges. This is the case when the request is the result of accessing a * URL with the admin subdomain.</p> * * @type boolean */ this.isOwner = false; /** * Whether or not this connection has been closed. Readonly. * @type boolean */ this.closed = false; /** * The id of this connection. Readonly. * @type int */ this.id = 0; } /** * This class has no public constructor. * @constructor * @class * Request made to the Web server. * * <p>WebServerRequest holds information about the incoming request, such as its URI, method and any data * sent along with it.</p> */ var WebServerRequest = function () { /** * The connection this request was sent through. Readonly. * @type WebServerConnection */ this.connection = {}; /** * The HTTP method of this request, one of GET, POST, PUT or DELETE. Readonly. * @type String */ this.method = ''; /** * The IP address of the client that sent this request. Readonly. * * <p class="ni">This currently only gives you the IP address of the proxy.</p> * * @type String */ this.ip = ''; /** * The protocol this request was made to. Readonly. * * This is either 'http' or 'https'. Use it to construct links * and redirects and preserve the correct security qualifications of the URIs. * * @type String */ this.protocol = ''; /** * The value of the Host header sent with this request. Readonly. * * As opposed to the {@link #uri} property, this will give you the host name the request * was made to, which can be used for among other things redirects. This may contain the * port of the request, i.e. 'foo.bar:80'. * * @type String */ this.host = ''; /** * The HTTP headers sent with this request. Readonly. * * <p>This property will contain a dictionary of HTTP headers sent * with this request. As each HTTP header may occur multiple times, * each key/property of the dictionary points to an array-like object * of values:</p> * * <pre><code>firstCookie = request.headers.Cookie[0]; *firstCookie = request.headers['Cookie'][0];</code></pre> * * @type Object */ this.headers = {}; /** * The items in the body of this request, meaning data sent as POST. Readonly. * * <p>This property will contain a dictionary of only those items sent as part * of the body of the request, for example large amounts of text or sensitive * information such as passwords that should not be visible in the URL.</p> * * <p>As each CGI parameter may occur multiple times, each key/property of the * dictionary points to an array-like object of values.</p> * * <pre><code>password = request.bodyItems.passwords[0]; *password = request.bodyItems['passwords'][0]; *passwords = request.bodyItems.passwords</code></pre> * @type Object */ this.bodyItems = {}; /** * The items sent as part of the query string in this request, meaning data sent as GET. Readonly. * * <p>This property will contain a dictionary of only those items sent as part * of the query string i.e. anything after the ? in the URL.</p> * * <p>As each CGI parameter may occur multiple times, each key/property of the * dictionary points to an array-like object of values.</p> * * <pre><code>user = request.queryItems.user[0]; *user = request.queryItems['user'][0]; *users = request.queryItems.users;</code></pre> * @type Object */ this.queryItems = {}; /** * Files uploaded with this request. Readonly. * * <p>This File object represents a virtual directory which points to the * uploaded files. Access the individual files by getting the listing * from the file.</p> * * <p>The name of the file is the filename the user selected when uploading.</p> * * <p>Request headers for these files are available through the metaData property: * <code>req.files[0].metaData.headers['some header'];</code></p> * * <p>See the File API for details about files.</p> * * @type File */ this.files = {}; /** * The full body of the HTTP request as a String. Readonly. * * If the body is non existintant or binary, this property is null. * * @type String */ this.body = ''; /** * The relative Uniform Resource Identifier this request was made to. * * <p>Relative URI the request is made out to, starting with '/' and the name of the service, * e.g. http://work.john.operaunite.com/wiki/add becomes '/wiki/add'. It is rewritable to allow * redispatching of the request. See the {@link WebServerResponse#closeAndRedispatch} method.</p> * * <p>Setting this property will throw a SECURITY_ERR if an invalid URI is set or if the URI * points to a different service than the one the request was issued from.</p> * @type String */ this.uri = ''; /** * Get the values of a HTTP header in the request. * * <p>The returned object is a collection of headers matching the given header name.</p> * * <h3>Example:</h3> * * <p>Assuming that the client sent a request with a header of <code>Foo</code>, access it as follows:</p> * * <pre><code> * headers = request.getRequestHeader('Foo'); * if ( headers ) * { * opera.postError(headers[0]); * }</code></pre> * * @param {String} requestHeader Name of the HTTP header to get. * @returns {Object} Array-like object with headers matching the given name, or null if there are no headers with the given name. */ this.getRequestHeader = function ( requestHeader ) { ; } /** * Get the value of a request item. * * <p>This method gets the values of items sent in a query string (typically through GET requests) * or in the body of the request (typically through POST requests). Each item may occur multiple times * with different values, both in the query string and the body. The optional second argument * <code>method</code> can be used to limit the selection to either of those two.</p> * * <h3>Examples:</h3> * * <p>In the case of a query string <code>foo=bar</code>:</p> * * <p><code>getItem( 'foo' )</code> will produce an array-like object [ 'bar' ].</p> * * <p>In the case of a query string <code>foo=bar&foo=baz</code>:</p> * * <p><code>getItem( 'foo' )</code> will produce an array-like object <code>[ 'bar', 'baz' ]</code>.</p> * * <p>In the case of a query string <code>foo=bar</code> and a request body containing <code>foo=baz</code>:</p> * * <p><code>getItem( 'foo', 'POST' )</code> will produce an array-like object [ 'baz' ].</p> * * @param {String} requestItem Name of the request item to get * @param {String} method Optional argument with the method of the request item to get, either GET or POST. * @returns {Object} Array-like object of values for the given request item, or null if there are no values for the given request item. */ this.getItem = function ( requestItem, method ) { ; } } /** * This class has no public constructor. * @constructor * @class * Event fired when requests are made to the Web server. * * <p>See {@link opera.io.webserver#addEventListener} for details on different event names.</p> */ var WebServerRequestEvent = function () { /** * Id of the connection this request was generated from. * * If this event was fired for a <code>_close</code> request, this property will hold the id of the closed connection. * * @type int */ this.id = 0; /** * The connection this request event was generated from. * * <p>Use this property to access the incoming request and outgoing response:</p> * * <pre><code>req = e.connection.request; *res = e.connection.response;</code></pre> * * <p>If this event was fired for a <code>_close</code> request, this property will be <code>null</code>.</p> * * @type WebServerConnection */ this.connection = null; } /** * This class has no public constructor. * @constructor * @class * Response from the Web server. * * <p>The <code>WebServerResponse</code> allows the user to write data back to the client which made a request. It supports * writing string data, bytes of binary data and images.</p> */ var WebServerResponse = function () { /** * Connection this response will be sent to. * @type WebServerConnection */ this.connection = {}; /** * Whether or not this response has been closed. * * This property mirrors the {@link WebServerConnection#closed} property. * * @type boolean */ this.closed = false; /** * Whether or not to use chunked encoding in the response. * * <p>Chunked encoding is used when you don't know the length of the encoding when starting to * send data and to avoid frequently closing and reopening connections. It is only recommended * to turn this off if clients are not expected to support chunked encoding.</p> * * <p>This property defaults to <code>true</code>.</p> * * @type boolean */ this.chunked = true; /** * Whether or not to flush data written to the response automatically. * * <p>By default, you need to explicitly call <code>response.flush()</code> in order to * actually send data written to the response. By setting this property * to true, data are flushed immediately when they are written.</p> * * <p>This property defaults to <code>false</code>.</p> * * @type boolean */ this.implicitFlush = false; /** * Set the HTTP status code of the response. * * <p>This method sets the status code sent back to the client, * such as 404 (Not found), 200 (OK), etc. An optional argument * can be used to set a specific response text as well, allowing * for messages not in the HTTP specification.</p> * * <p>If you do not set a status code, a 200 (OK) status * code is silently set.</p> * * <p>Note that you must set any status before you start writing * to the response. Failure to do so will result in an INVALID_STATE_ERR.</p> * * @param {String} statusCode Status code to set, e.g. 200 or 404 * @param {String} text Status text to set, e.g. "Success" or "Out of pidgeons". Optional. * @throws INVALID_STATE_ERR If data has been written to the response before setting the status code. */ this.setStatusCode = function ( statusCode, text ) { ; } /** * Set a HTTP response header. * * <p>Use this method to specify response headers sent back to the client. * For example setting the content type to XML, by doing: * <code>response.setResponseHeader( "Content-type", "text/html" );</code></p> * * <p>Note that you must set any headers before you start writing * to the response. Failure to do so will result in an INVALID_STATE_ERR.</p> * * @param {String} name Name of the HTTP response header to set, e.g. "Content-type" * @param {String} value Value to set for the given HTTP response header. * @throws INVALID_STATE_ERR If data has been written to the response before setting any headers. */ this.setResponseHeader = function ( name, value ) { ; } /** * Set the protocol version string of the response. * * <p>Usually the protocol version string will contain a version of HTTP, but it can * be used to set other protocols as well.</p> * * <p>Note that you must set a protocol string before you start writing * to the response. Failure to do so will result in an INVALID_STATE_ERR.</p> * * @param {String} protocolString Protocol string to set. * @throws INVALID_STATE_ERR If data has been written to the response before setting the protocol string. */ this.setProtocolString = function ( protocolString ) { ; } /** * Write data to the response. * @param {String} data String of data to write. */ this.write = function ( data ) { ; } /** * Write data to the response and append a newline. * @param data String of data to write. */ this.writeLine = function ( data ) { ; } /** * Write binary data to the response. * * This method takes an ECMA 4 <code>ByteArray</code> object and * writes it to the response. * * @param {ByteArray} data Binary data to write */ this.writeBytes = function ( data ) { ; } /** * Write a File to the response. * * This methods takes a <code>File</code> object and writes the * contents of the file to the response. * * @param {File} file File object to write */ this.writeFile = function ( file ) { ; } /** * Write an image to the response. * * The image can either be an <code>HTMLImageElement</code> or an <code>HTMLCanvasElement</code> object. * In both cases the image or data referenced is serialized and written to the * response, encoded as a PNG image. * * @param {HTMLImageElement} image HTML Image element or Canvas element to write. */ this.writeImage = function ( image ) { ; } /** * Flush the data in the response. * * <p>Flush the data in the response and send them to the client immediately. * Used in combination with chunked encoding, where each flush sends a chunk to the * client.</p> * * <p>Flushing is by default an asynchronous operation. You may catch when the * the response is actually flushed by supplying an optional <code>callback</code> parameter.</p> * * @param {Function} callback Function to call when the response is flushed. Optional. */ this.flush = function ( callback ) { ; } /** * Close the connection. * * <p>Close the connection and set the {@link WebServerConnection#closed} property of the * corresponding <code>WebServerConnection</code> object to false. No writing to the * the response is possible after <code>close()</code> is called.</p> * * <p>Closing is by default an asynchronous operation. You may catch when the * connection actually closes by supplying an optional callback parameter.</p> * * @param {Function} callback Function to call when the connection is closed. Optional. */ this.close = function ( callback ) { ; } /** * Close the connection and redispatch the request to the Web server. * * <p>Close the connection and put the request back into the request queue of * the Web server. The <code>uri</code> property of the <code>WebServerRequest</code> may be rewritten * for this purpose. See the {@link WebServerRequest#uri} property.</p> * * <p>If you have set the status code or added any headers to this response, * these will be sent with the new request. But if you redispatch after having * written to the response it will fail with a <code>INVALID_STATE_ERR</code>.</p> * * <p>If {@link WebServerRequest#uri} is not changed, redispatching the request * will bypass any JavaScript event listeners in the next run. If the URI points * to a shared file, this file will be served. Otherwise a 404 will be shown * to the user.</p> * * @throws INVALID_STATE_ERR If data has been written to this response before it is redispatched. */ this.closeAndRedispatch = function () { ; } }
|
Unite API | |||||||
| PREV NEXT | FRAMES NO FRAMES | |||||||