summaryrefslogtreecommitdiffstats
path: root/netwerk/test/httpserver/nsIHttpServer.idl
blob: 97192a2d60dbc17d4646361ca74499eeed3fa898 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
/* 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);

  /**
   * 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
   */
  void registerFile(in string path, in nsIFile file);

  /**
   * 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();
};