/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" interface nsIInputStream; interface nsIFile; interface nsIOutputStream; interface nsISimpleEnumerator; interface nsIHttpServer; interface nsIHttpServerStoppedCallback; interface nsIHttpRequestHandler; interface nsIHttpRequest; interface nsIHttpResponse; interface nsIHttpServerIdentity; /** * An interface which represents an HTTP server. */ [scriptable, uuid(cea8812e-faa6-4013-9396-f9936cbb74ec)] interface nsIHttpServer : nsISupports { /** * Starts up this server, listening upon the given port. * * @param port * the port upon which listening should happen, or -1 if no specific port is * desired * @throws NS_ERROR_ALREADY_INITIALIZED * if this server is already started * @throws NS_ERROR_NOT_AVAILABLE * if the server is not started and cannot be started on the desired port * (perhaps because the port is already in use or because the process does * not have privileges to do so) * @note * Behavior is undefined if this method is called after stop() has been * called on this but before the provided callback function has been * called. */ void start(in long port); /** * Starts up this server, listening upon the given port on a ipv6 adddress. * * @param port * the port upon which listening should happen, or -1 if no specific port is * desired * @throws NS_ERROR_ALREADY_INITIALIZED * if this server is already started * @throws NS_ERROR_NOT_AVAILABLE * if the server is not started and cannot be started on the desired port * (perhaps because the port is already in use or because the process does * not have privileges to do so) * @note * Behavior is undefined if this method is called after stop() has been * called on this but before the provided callback function has been * called. */ void start_ipv6(in long port); /** * Like the two functions above, but this server supports both IPv6 and * IPv4 addresses. */ void start_dualStack(in long port); /** * Shuts down this server if it is running (including the period of time after * stop() has been called but before the provided callback has been called). * * @param callback * an asynchronous callback used to notify the user when this server is * stopped and all pending requests have been fully served * @throws NS_ERROR_NULL_POINTER * if callback is null * @throws NS_ERROR_UNEXPECTED * if this server is not running */ void stop(in nsIHttpServerStoppedCallback callback); /** * Associates the local file represented by the string file with all requests * which match request. * * @param path * the path which is to be mapped to the given file; must begin with "/" and * be a valid URI path (i.e., no query string, hash reference, etc.) * @param file * the file to serve for the given path, or null to remove any mapping that * might exist; this file must exist for the lifetime of the server * @param handler * an optional object which can be used to handle any further changes. */ void registerFile(in string path, in nsIFile file, [optional] in nsIHttpRequestHandler handler); /** * Registers a custom path handler. * * @param path * the path on the server (beginning with a "/") which is to be handled by * handler; this path must not include a query string or hash component; it * also should usually be canonicalized, since most browsers will do so * before sending otherwise-matching requests * @param handler * an object which will handle any requests for the given path, or null to * remove any existing handler; if while the server is running the handler * throws an exception while responding to a request, an HTTP 500 response * will be returned * @throws NS_ERROR_INVALID_ARG * if path does not begin with a "/" */ void registerPathHandler(in string path, in nsIHttpRequestHandler handler); /** * Registers a custom prefix handler. * * @param prefix * the path on the server (beginning and ending with "/") which is to be * handled by handler; this path must not include a query string or hash * component. All requests that start with this prefix will be directed to * the given handler. * @param handler * an object which will handle any requests for the given path, or null to * remove any existing handler; if while the server is running the handler * throws an exception while responding to a request, an HTTP 500 response * will be returned * @throws NS_ERROR_INVALID_ARG * if path does not begin with a "/" or does not end with a "/" */ void registerPrefixHandler(in string prefix, in nsIHttpRequestHandler handler); /** * Registers a custom error page handler. * * @param code * the error code which is to be handled by handler * @param handler * an object which will handle any requests which generate the given status * code, or null to remove any existing handler. If the handler throws an * exception during server operation, fallback is to the genericized error * handler (the x00 version), then to 500, using a user-defined error * handler if one exists or the server default handler otherwise. Fallback * will never occur from a user-provided handler that throws to the same * handler as provided by the server, e.g. a throwing user 404 falls back to * 400, not a server-provided 404 that might not throw. * @note * If the error handler handles HTTP 500 and throws, behavior is undefined. */ void registerErrorHandler(in unsigned long code, in nsIHttpRequestHandler handler); /** * Maps all requests to paths beneath path to the corresponding file beneath * dir. * * @param path * the absolute path on the server against which requests will be served * from dir (e.g., "/", "/foo/", etc.); must begin and end with a forward * slash * @param dir * the directory to be used to serve all requests for paths underneath path * (except those further overridden by another, deeper path registered with * another directory); if null, any current mapping for the given path is * removed * @throws NS_ERROR_INVALID_ARG * if dir is non-null and does not exist or is not a directory, or if path * does not begin with and end with a forward slash */ void registerDirectory(in string path, in nsIFile dir); /** * Associates files with the given extension with the given Content-Type when * served by this server, in the absence of any file-specific information * about the desired Content-Type. If type is empty, removes any extant * mapping, if one is present. * * @throws NS_ERROR_INVALID_ARG * if the given type is not a valid header field value, i.e. if it doesn't * match the field-value production in RFC 2616 * @note * No syntax checking is done of the given type, beyond ensuring that it is * a valid header field value. Behavior when not given a string matching * the media-type production in RFC 2616 section 3.7 is undefined. * Implementations may choose to define specific behavior for types which do * not match the production, such as for CGI functionality. * @note * Implementations MAY treat type as a trusted argument; users who fail to * generate this string from trusted data risk security vulnerabilities. */ void registerContentType(in string extension, in string type); /** * Sets the handler used to display the contents of a directory if * the directory contains no index page. * * @param handler * an object which will handle any requests for directories which * do not contain index pages, or null to reset to the default * index handler; if while the server is running the handler * throws an exception while responding to a request, an HTTP 500 * response will be returned. An nsIFile corresponding to the * directory is available from the metadata object passed to the * handler, under the key "directory". */ void setIndexHandler(in nsIHttpRequestHandler handler); /** Represents the locations at which this server is reachable. */ readonly attribute nsIHttpServerIdentity identity; /** * Retrieves the string associated with the given key in this, for the given * path's saved state. All keys are initially associated with the empty * string. */ AString getState(in AString path, in AString key); /** * Sets the string associated with the given key in this, for the given path's * saved state. */ void setState(in AString path, in AString key, in AString value); /** * Retrieves the string associated with the given key in this, in * entire-server saved state. All keys are initially associated with the * empty string. */ AString getSharedState(in AString key); /** * Sets the string associated with the given key in this, in entire-server * saved state. */ void setSharedState(in AString key, in AString value); /** * Retrieves the object associated with the given key in this in * object-valued saved state. All keys are initially associated with null. */ nsISupports getObjectState(in AString key); /** * Sets the object associated with the given key in this in object-valued * saved state. The value may be null. */ void setObjectState(in AString key, in nsISupports value); }; /** * An interface through which a notification of the complete stopping (socket * closure, in-flight requests all fully served and responded to) of an HTTP * server may be received. */ [scriptable, function, uuid(925a6d33-9937-4c63-abe1-a1c56a986455)] interface nsIHttpServerStoppedCallback : nsISupports { /** Called when the corresponding server has been fully stopped. */ void onStopped(); }; /** * Represents a set of names for a server, one of which is the primary name for * the server and the rest of which are secondary. By default every server will * contain ("http", "localhost", port) and ("http", "127.0.0.1", port) as names, * where port is what was provided to the corresponding server when started; * however, except for their being removed when the corresponding server stops * they have no special importance. */ [scriptable, uuid(a89de175-ae8e-4c46-91a5-0dba99bbd284)] interface nsIHttpServerIdentity : nsISupports { /** * The primary scheme at which the corresponding server is located, defaulting * to 'http'. This name will be the value of nsIHttpRequest.scheme for * HTTP/1.0 requests. * * This value is always set when the corresponding server is running. If the * server is not running, this value is set only if it has been set to a * non-default name using setPrimary. In this case reading this value will * throw NS_ERROR_NOT_INITIALIZED. */ readonly attribute string primaryScheme; /** * The primary name by which the corresponding server is known, defaulting to * 'localhost'. This name will be the value of nsIHttpRequest.host for * HTTP/1.0 requests. * * This value is always set when the corresponding server is running. If the * server is not running, this value is set only if it has been set to a * non-default name using setPrimary. In this case reading this value will * throw NS_ERROR_NOT_INITIALIZED. */ readonly attribute string primaryHost; /** * The primary port on which the corresponding server runs, defaulting to the * associated server's port. This name will be the value of * nsIHttpRequest.port for HTTP/1.0 requests. * * This value is always set when the corresponding server is running. If the * server is not running, this value is set only if it has been set to a * non-default name using setPrimary. In this case reading this value will * throw NS_ERROR_NOT_INITIALIZED. */ readonly attribute long primaryPort; /** * Adds a location at which this server may be accessed. * * @throws NS_ERROR_ILLEGAL_VALUE * if scheme or host do not match the scheme or host productions imported * into RFC 2616 from RFC 2396, or if port is not a valid port number */ void add(in string scheme, in string host, in long port); /** * Removes this name from the list of names by which the corresponding server * is known. If name is also the primary name for the server, the primary * name reverts to 'http://127.0.0.1' with the associated server's port. * * @throws NS_ERROR_ILLEGAL_VALUE * if scheme or host do not match the scheme or host productions imported * into RFC 2616 from RFC 2396, or if port is not a valid port number * @returns * true if the given name was a name for this server, false otherwise */ boolean remove(in string scheme, in string host, in long port); /** * Returns true if the given name is in this, false otherwise. * * @throws NS_ERROR_ILLEGAL_VALUE * if scheme or host do not match the scheme or host productions imported * into RFC 2616 from RFC 2396, or if port is not a valid port number */ boolean has(in string scheme, in string host, in long port); /** * Returns the scheme for the name with the given host and port, if one is * present; otherwise returns the empty string. * * @throws NS_ERROR_ILLEGAL_VALUE * if host does not match the host production imported into RFC 2616 from * RFC 2396, or if port is not a valid port number */ string getScheme(in string host, in long port); /** * Designates the given name as the primary name in this and adds it to this * if it is not already present. * * @throws NS_ERROR_ILLEGAL_VALUE * if scheme or host do not match the scheme or host productions imported * into RFC 2616 from RFC 2396, or if port is not a valid port number */ void setPrimary(in string scheme, in string host, in long port); }; /** * A representation of a handler for HTTP requests. The handler is used by * calling its .handle method with data for an incoming request; it is the * handler's job to use that data as it sees fit to make the desired response. * * @note * This interface uses the [function] attribute, so you can pass a * script-defined function with the functionality of handle() to any * method which has a nsIHttpRequestHandler parameter, instead of wrapping * it in an otherwise empty object. */ [scriptable, function, uuid(2bbb4db7-d285-42b3-a3ce-142b8cc7e139)] interface nsIHttpRequestHandler : nsISupports { /** * Processes an HTTP request and initializes the passed-in response to reflect * the correct HTTP response. * * If this method throws an exception, externally observable behavior depends * upon whether is being processed asynchronously. If such is the case, the * output is some prefix (perhaps all, perhaps none, perhaps only some) of the * data which would have been sent if, instead, the response had been finished * at that point. If no data has been written, the response has not had * seizePower() called on it, and it is not being asynchronously created, an * error handler will be invoked (usually 500 unless otherwise specified). * * Some uses of nsIHttpRequestHandler may require this method to never throw * an exception; in the general case, however, this method may throw an * exception (causing an HTTP 500 response to occur, if the above conditions * are met). * * @param request * data representing an HTTP request * @param response * an initially-empty response which must be modified to reflect the data * which should be sent as the response to the request described by metadata */ void handle(in nsIHttpRequest request, in nsIHttpResponse response); }; /** * A representation of the data included in an HTTP request. */ [scriptable, uuid(978cf30e-ad73-42ee-8f22-fe0aaf1bf5d2)] interface nsIHttpRequest : nsISupports { /** * The request type for this request (see RFC 2616, section 5.1.1). */ readonly attribute string method; /** * The scheme of the requested path, usually 'http' but might possibly be * 'https' if some form of SSL tunneling is in use. Note that this value * cannot be accurately determined unless the incoming request used the * absolute-path form of the request line; it defaults to 'http', so only * if it is something else can you be entirely certain it's correct. */ readonly attribute string scheme; /** * The host of the data being requested (e.g. "localhost" for the * http://localhost:8080/file resource). Note that the relevant port on the * host is specified in this.port. This value is in the ASCII character * encoding. */ readonly attribute string host; /** * The port on the server on which the request was received. */ readonly attribute unsigned long port; /** * The requested path, without any query string (e.g. "/dir/file.txt"). It is * guaranteed to begin with a "/". The individual components in this string * are URL-encoded. */ readonly attribute string path; /** * The URL-encoded query string associated with this request, not including * the initial "?", or "" if no query string was present. */ readonly attribute string queryString; /** * A string containing the HTTP version of the request (i.e., "1.1"). Leading * zeros for either component of the version will be omitted. (In other * words, if the request contains the version "1.01", this attribute will be * "1.1"; see RFC 2616, section 3.1.) */ readonly attribute string httpVersion; /** * Returns the value for the header in this request specified by fieldName. * * @param fieldName * the name of the field whose value is to be gotten; note that since HTTP * header field names are case-insensitive, this method produces equivalent * results for "HeAdER" and "hEADer" as fieldName * @returns * The result is a string containing the individual values of the header, * usually separated with a comma. The headers WWW-Authenticate, * Proxy-Authenticate, and Set-Cookie violate the HTTP specification, * however, and for these headers only the separator string is '\n'. * * @throws NS_ERROR_INVALID_ARG * if fieldName does not constitute a valid header field name * @throws NS_ERROR_NOT_AVAILABLE * if the given header does not exist in this */ string getHeader(in string fieldName); /** * Returns true if a header with the given field name exists in this, false * otherwise. * * @param fieldName * the field name whose existence is to be determined in this; note that * since HTTP header field names are case-insensitive, this method produces * equivalent results for "HeAdER" and "hEADer" as fieldName * @throws NS_ERROR_INVALID_ARG * if fieldName does not constitute a valid header field name */ boolean hasHeader(in string fieldName); /** * An nsISimpleEnumerator of nsISupportsStrings over the names of the headers * in this request. The header field names in the enumerator may not * necessarily have the same case as they do in the request itself. */ readonly attribute nsISimpleEnumerator headers; /** * A stream from which data appearing in the body of this request can be read. */ readonly attribute nsIInputStream bodyInputStream; }; /** * Represents an HTTP response, as described in RFC 2616, section 6. */ [scriptable, uuid(1acd16c2-dc59-42fa-9160-4f26c43c1c21)] interface nsIHttpResponse : nsISupports { /** * Sets the status line for this. If this method is never called on this, the * status line defaults to "HTTP/", followed by the server's default HTTP * version (e.g. "1.1"), followed by " 200 OK". * * @param httpVersion * the HTTP version of this, as a string (e.g. "1.1"); if null, the server * default is used * @param code * the numeric HTTP status code for this * @param description * a human-readable description of code; may be null if no description is * desired * @throws NS_ERROR_INVALID_ARG * if httpVersion is not a valid HTTP version string, statusCode is greater * than 999, or description contains invalid characters * @throws NS_ERROR_NOT_AVAILABLE * if this response is being processed asynchronously and data has been * written to this response's body, or if seizePower() has been called on * this */ void setStatusLine(in string httpVersion, in unsigned short statusCode, in string description); /** * Sets the specified header in this. * * @param name * the name of the header; must match the field-name production per RFC 2616 * @param value * the value of the header; must match the field-value production per RFC * 2616 * @param merge * when true, if the given header already exists in this, the values passed * to this function will be merged into the existing header, per RFC 2616 * header semantics (except for the Set-Cookie, WWW-Authenticate, and * Proxy-Authenticate headers, which will treat each such merged header as * an additional instance of the header, for real-world compatibility * reasons); when false, replaces any existing header of the given name (if * any exists) with a new header with the specified value * @throws NS_ERROR_INVALID_ARG * if name or value is not a valid header component * @throws NS_ERROR_NOT_AVAILABLE * if this response is being processed asynchronously and data has been * written to this response's body, or if seizePower() has been called on * this */ void setHeader(in string name, in string value, in boolean merge); /** * This is used for testing our header handling, so header will be sent out * without transformation. There can be multiple headers. */ void setHeaderNoCheck(in string name, in string value); /** * A stream to which data appearing in the body of this response (or in the * totality of the response if seizePower() is called) should be written. * After this response has been designated as being processed asynchronously, * or after seizePower() has been called on this, subsequent writes will no * longer be buffered and will be written to the underlying transport without * delaying until the entire response is constructed. Write-through may or * may not be synchronous in the implementation, and in any case particular * behavior may not be observable to the HTTP client as intermediate buffers * both in the server socket and in the client may delay written data; be * prepared for delays at any time. * * @throws NS_ERROR_NOT_AVAILABLE * if accessed after this response is fully constructed */ readonly attribute nsIOutputStream bodyOutputStream; /** * Writes a string to the response's output stream. This method is merely a * convenient shorthand for writing the same data to bodyOutputStream * directly. * * @note * This method is only guaranteed to work with ASCII data. * @throws NS_ERROR_NOT_AVAILABLE * if called after this response has been fully constructed */ void write(in string data); /** * Signals that this response is being constructed asynchronously. Requests * are typically completely constructed during nsIHttpRequestHandler.handle; * however, responses which require significant resources (time, memory, * processing) to construct can be created and sent incrementally by calling * this method during the call to nsIHttpRequestHandler.handle. This method * only has this effect when called during nsIHttpRequestHandler.handle; * behavior is undefined if it is called at a later time. It may be called * multiple times with no ill effect, so long as each call occurs before * finish() is called. * * @throws NS_ERROR_UNEXPECTED * if not initially called within a nsIHttpRequestHandler.handle call or if * called after this response has been finished * @throws NS_ERROR_NOT_AVAILABLE * if seizePower() has been called on this */ void processAsync(); /** * Seizes complete control of this response (and its connection) from the * server, allowing raw and unfettered access to data being sent in the HTTP * response. Once this method has been called the only property which may be * accessed without an exception being thrown is bodyOutputStream, and the * only methods which may be accessed without an exception being thrown are * write(), finish(), and seizePower() (which may be called multiple times * without ill effect so long as all calls are otherwise allowed). * * After a successful call, all data subsequently written to the body of this * response is written directly to the corresponding connection. (Previously- * written data is silently discarded.) No status line or headers are sent * before doing so; if the response handler wishes to write such data, it must * do so manually. Data generation completes only when finish() is called; it * is not enough to simply call close() on bodyOutputStream. * * @throws NS_ERROR_NOT_AVAILABLE * if processAsync() has been called on this * @throws NS_ERROR_UNEXPECTED * if finish() has been called on this */ void seizePower(); /** * Signals that construction of this response is complete and that it may be * sent over the network to the client, or if seizePower() has been called * signals that all data has been written and that the underlying connection * may be closed. This method may only be called after processAsync() or * seizePower() has been called. This method is idempotent. * * @throws NS_ERROR_UNEXPECTED * if processAsync() or seizePower() has not already been properly called */ void finish(); };