~ubuntu-branches/ubuntu/trusty/ocamlnet/trusty

« back to all changes in this revision

Viewing changes to src/nethttpd-for-netcgi1/nethttpd_engine.mli

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu
  • Date: 2011-09-02 14:12:33 UTC
  • mfrom: (18.2.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110902141233-zbj0ygxb92u6gy4z
Tags: 3.4-1
* New upstream release
  - add a new NetcgiRequire directive to ease dependency management
    (Closes: #637147)
  - remove patches that were applied upstream:
    + Added-missing-shebang-lines-in-example-shell-scripts
    + Try-also-ocamlc-for-POSIX-threads

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
(* $Id: nethttpd_engine.mli 1063 2006-12-17 20:54:34Z gerd $
2
 
 *
3
 
 *)
4
 
 
5
 
(*
6
 
 * Copyright 2005 Baretta s.r.l. and Gerd Stolpmann
7
 
 *
8
 
 * This file is part of Nethttpd.
9
 
 *
10
 
 * Nethttpd is free software; you can redistribute it and/or modify
11
 
 * it under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation; either version 2 of the License, or
13
 
 * (at your option) any later version.
14
 
 *
15
 
 * Nethttpd is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU General Public License
21
 
 * along with WDialog; if not, write to the Free Software
22
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 
 *)
24
 
 
25
 
(** {1 The event-based encapsulation of the HTTP daemon}
26
 
  * 
27
 
  * This is a user-friendlier encapsulation of the HTTP daemon. It uses
28
 
  * the engine module defined in [Uq_engines].
29
 
 *)
30
 
 
31
 
(* Integration into event-based server design *)
32
 
 
33
 
open Nethttpd_types
34
 
 
35
 
type engine_req_state =
36
 
    [ `Received_header
37
 
    | `Receiving_body
38
 
    | `Received_request 
39
 
    | `Finishing
40
 
    ]
41
 
 
42
 
class type http_engine_config =
43
 
object
44
 
  inherit Nethttpd_reactor.http_processor_config
45
 
 
46
 
  method config_input_flow_control : bool
47
 
    (** If [true], the engine stops reading input tokens from the HTTP kernel when
48
 
      * there is data in the input channel of the engine not yet read. If [false],
49
 
      * all available input tokens are fetched from the kernel and buffered up
50
 
      * in the input channel.
51
 
      *
52
 
      * In general, this {b should} be set to [true]. However, this is only possible
53
 
      * when the user of the engine is prepared for flow control. In particular,
54
 
      * all data contained in the input channel must be immediately read, or else
55
 
      * the engine blocks. By calling [input_ch_async # request_notification], the
56
 
      * user can be notified when there is data to read.
57
 
      *
58
 
      * When set to [false], the engine never blocks, but the price is that the
59
 
      * input channel may become as large as needed to store the whole request.
60
 
      *
61
 
      * The option [config_limit_pipeline_size] does not have any effect for engines.
62
 
     *)
63
 
 
64
 
  method config_output_flow_control : bool
65
 
    (** If [true], the engine signals the user when there is already enough data
66
 
      * to output, and no more output should be generated. The user can query
67
 
      * this state by calling [output_ch_async # can_output], and react
68
 
      * accordingly. The user can also ignore this signal, and the output channel
69
 
      * buffers all data.
70
 
      *
71
 
      * If [false], the mentioned method [can_output] returns always [true]. This
72
 
      * turns off flow control in the case it is implemented by the user of the
73
 
      * engine, but actually not wanted.
74
 
      *
75
 
      * The internal processing of data is not affected by this configuration option.
76
 
      * In doubt, set it to [true].
77
 
     *)
78
 
 
79
 
end
80
 
 
81
 
 
82
 
class type extended_async_environment =
83
 
object
84
 
  inherit extended_environment
85
 
 
86
 
  (** Environment also providing asynchronous views to I/O *)
87
 
 
88
 
  method input_ch_async : Uq_engines.async_in_channel
89
 
    (** This is the [input_ch] channel taken as asynchonous channel. This type of
90
 
      * channel indicates when data is available to read, and also sends notifications.
91
 
      * Note that this is only an alternate interface of the [input_ch] object.
92
 
      *
93
 
      * The method [can_input] returns true when there is at least one byte of
94
 
      * the body to read, or the EOF has been seen. The channel buffers any arriving
95
 
      * data (which can be limited in amount by [config_pipeline_size]).
96
 
      *
97
 
      * The behaviour of this channel is influenced by the configuration option
98
 
      * [config_input_flow_control].
99
 
     *)
100
 
 
101
 
  method output_ch_async : Uq_engines.async_out_channel
102
 
    (** This is the [output_ch] channel taken as asynchronous channel. This type of
103
 
      * channel indicates when space is available for further output, and also sends
104
 
      * notifications. 
105
 
      * Note that this is only an alternate interface of the [output_ch] object.
106
 
      *
107
 
      * The method [can_output] returns [true] only when the internal buffer is empty,
108
 
      * i.e. all data have been transmitted to the client. Independent of this, the
109
 
      * channel buffers all data written to it.
110
 
      *
111
 
      * The behaviour of this channel is influenced by the configuration option
112
 
      * [config_output_flow_control].
113
 
     *)
114
 
end
115
 
 
116
 
 
117
 
class type http_request_header_notification =
118
 
object
119
 
  (** Notification that a new request header has arrived
120
 
    *
121
 
    * This object notifies the user that a new request header has arrived.
122
 
    * The header is accessible by the [environment] object. The channels
123
 
    * also contained in this object are locked at this moment. The user must
124
 
    * now either call [schedule_accept_body] or [schedule_reject_body]. The
125
 
    * user will get a second notification (a [http_request_notification], below)
126
 
    * when the request body has completely arrived (in case of acceptance), or
127
 
    * immediately (in case of rejection). One can also call [schedule_finish]
128
 
    * at any time to drop the current request.
129
 
   *)
130
 
  
131
 
  method req_state : engine_req_state
132
 
    (** Returns the request processing state which is [`Received_header] at the
133
 
      * moment when this notification is delivered.
134
 
     *)
135
 
 
136
 
  method environment : extended_async_environment
137
 
    (** The request environment. Depending on the request processing state, parts
138
 
      * of the environment are already set up or still unaccessible ("locked").
139
 
      * In the state [`Received_header] only the request header and the 
140
 
      * derived fields are accessible, and the input and output channels are
141
 
      * locked. In the state [`Receiving_body] the input channel is unlocked,
142
 
      * but it is not yet filled (reading from it may cause the exception 
143
 
      * [Buffer_underrun]). The output channel remains locked.
144
 
      * In the state [`Received_request], the input channel is unlocked and filled
145
 
      * with data, and the output channel is unlocked, too.
146
 
      *
147
 
      * This environment is not fully CGI-compatible. In particular, the following
148
 
      * differences exist:
149
 
      * - There is no [cgi_path_info] and no [cgi_path_translated].
150
 
      * - The user is always unauthenticated.
151
 
      * - The [Status] response header works as in CGI. The [Location] header, however,
152
 
      *   must be a full URL when set (only browser redirects)
153
 
      * - When the request body is transmitted by chunked encoding, the header
154
 
      *   [Content-Length] is not set. In CGI this is interpreted as missing body.
155
 
      *   It is unlikely that clients send requests with chunked encoding, as this
156
 
      *   may cause interoperability problems anyway.
157
 
      *   
158
 
     *)
159
 
 
160
 
  method schedule_accept_body : on_request:(http_request_notification -> unit) ->
161
 
                               ?on_error:(unit -> unit) -> 
162
 
                               unit -> unit
163
 
    (** Schedules that the request body is accepted. In terms of HTTP, this sends the
164
 
      * "100 Continue" response when necessary. One can reply with a positive or
165
 
      * negative message.
166
 
      *
167
 
      * This method returns immediately, and sets callbacks for certain events.
168
 
      * When the body has completely arrived (or is empty), the function 
169
 
      * [on_request] is called back. The argument is the full request notification
170
 
      * (see below).
171
 
      *
172
 
      * When the request is dropped for some reason, [on_error] is called back instead.
173
 
      * This can be used to free resources, for example.
174
 
      *
175
 
      * Neither of the callbacks must raise exceptions.
176
 
     *)
177
 
 
178
 
  method schedule_reject_body : on_request:(http_request_notification -> unit) ->
179
 
                               ?on_error:(unit -> unit) -> 
180
 
                               unit -> unit
181
 
    (** Schedules that the request body is rejected. In terms of HTTP, this prevents
182
 
      * sending the "100 Continue" response. Any arriving request body is silently
183
 
      * discarded. One should immediately reply with an error mesage.
184
 
      * negative message.
185
 
      *
186
 
      * This method returns immediately, and sets callbacks for certain events.
187
 
      * When the body has completely arrived (or is empty), the function 
188
 
      * [on_request] is called back. The argument is the full request notification
189
 
      * (see below).
190
 
      *
191
 
      * When the request is dropped for some reason, [on_error] is called back instead.
192
 
      * This can be used to free resources, for example.
193
 
      *
194
 
      * Neither of the callbacks must raise exceptions.
195
 
     *)
196
 
 
197
 
  method schedule_finish : unit -> unit
198
 
    (** Schedules that the request is finished. This method should be called after
199
 
      * the regular processing of the request to ensure that the HTTP protocol
200
 
      * is fulfilled. If the request body has not been
201
 
      * fully read, this is now done, and its data are dropped. If the response
202
 
      * is incomplete, it is completed. If the error is not recoverable, a "Server
203
 
      * Error" is generated.
204
 
     *)
205
 
 
206
 
end
207
 
 
208
 
 
209
 
and http_request_notification =
210
 
object
211
 
  (** Notification that the whole request has arrived
212
 
    *
213
 
    * This object notifies the user that the request has fully arrived (including
214
 
    * the body if accepted), and can now be responded. The [environment] is the
215
 
    * same as in the request header notification, but the channels are now
216
 
    * unlocked.
217
 
   *)
218
 
 
219
 
  method req_state : engine_req_state
220
 
    (** Returns the request processing state which is [`Received_request] at the
221
 
      * moment when this notification is delivered.
222
 
     *)
223
 
 
224
 
  method environment : extended_async_environment
225
 
    (** The request environment. See above. *)
226
 
 
227
 
  method schedule_finish : unit -> unit
228
 
    (** Schedules that the request is finished. See above. *)
229
 
 
230
 
end
231
 
 
232
 
 
233
 
class http_engine : on_request_header:(http_request_header_notification -> unit) ->
234
 
                    unit -> 
235
 
                    #http_engine_config -> Unix.file_descr -> 
236
 
                    Unixqueue.unix_event_system ->
237
 
                      [unit] Uq_engines.engine
238
 
  (** This engine processes the requests arriving on the file descriptor using
239
 
    * the Unix event system. Whenever a new request header arrives, the function
240
 
    * [on_request_header] is called back, and must handle the request.
241
 
    *
242
 
    * Unless aborted using the [abort] method, this engine is always successful.
243
 
    * Errors are logged, but not returned as result.
244
 
    *
245
 
    * The file descriptor is closed after processing all HTTP requests and
246
 
    * responses. It is also closed on error and when the engine is aborted.
247
 
    *
248
 
    * An aborted engine does not try to clean up resources external to the 
249
 
    * engine, e.g. by calling the [on_error] functions. This is up to the user.
250
 
   *)
251
 
 
252
 
 
253
 
class type http_engine_processing_config =
254
 
object
255
 
  method config_synch_input : 
256
 
           (Netchannels.in_obj_channel -> unit) ->
257
 
           Uq_engines.async_in_channel ->
258
 
           unit
259
 
    (** The "input synchronizer": It is called as [obj # config_synch_input f ch]
260
 
      * to create a synchronous input channel from an asynchronous one, [ch].
261
 
      * The function [f] must be called back by the synchronizer when synchronisation
262
 
      * is established, and with the synchronous channel [ch'] as argument.
263
 
      * In particular, the task of the synchronizer is to turn blocking reads of
264
 
      * [ch'] into non-blocking reads of [ch]. In general there are two ways of
265
 
      * implementation:
266
 
      * - Buffer all input from [ch] until the end of the channel is reached,
267
 
      *   then call [f] with a wrapper channel [ch'] that just reads from the
268
 
      *   buffer.
269
 
      * - Run [f] in a different thread that blocks whenever there is nothing to
270
 
      *   read from [ch]. 
271
 
      *
272
 
      * Both implementations are allowed, i.e. {b it is allowed that [f] runs in
273
 
      * a different thread}.
274
 
      *
275
 
      * CHECK: How to handle exceptions raised from [f]? Idea: [f] is obliged to
276
 
      * close [ch'] in this case, even if [ch] is not yet at the end. The rest of
277
 
      * exception handling is up to the user. - The complementary must also be true:
278
 
      * When there is an error in the engine, [ch] must be closed to signal the
279
 
      * other thread that we have a problem.
280
 
     *)
281
 
 
282
 
  method config_synch_output : 
283
 
           (Netchannels.out_obj_channel -> unit) ->
284
 
           Uq_engines.async_out_channel ->
285
 
           unit
286
 
    (** The "output synchronizer": It is called as [obj # config_synch_output f ch]
287
 
      * to create a synchronous output channel from an asynchronous one, [ch].
288
 
      * The function [f] must be called back by the synchronizer when synchronisation
289
 
      * is established, and with the synchronous channel [ch'] as argument.
290
 
      * In particular, the task of the synchronizer is to turn blocking writes to
291
 
      * [ch'] into non-blocking writes to [ch]. In general there are two ways of
292
 
      * implementation:
293
 
      * - Call [f], then buffer all output to [ch'] until the end of the channel is
294
 
      *   reached, and finally output the contents of the buffer in an asynchronous
295
 
      *   way.
296
 
      * - Run [f] in a different thread that blocks whenever there is no space to
297
 
      *   write to [ch]. 
298
 
      *
299
 
      * Both implementations are allowed, i.e. {b it is allowed that [f] runs in
300
 
      * a different thread}.
301
 
      *
302
 
      * CHECK: Exceptions.
303
 
     *)
304
 
end
305
 
 
306
 
class buffering_engine_processing_config : http_engine_processing_config
307
 
  (** Implements the synchronisation by buffering *)
308
 
 
309
 
class type http_engine_processing_context =
310
 
object
311
 
 
312
 
  method engine : unit Uq_engines.engine
313
 
    (** The engine doing HTTP *)
314
 
 
315
 
end
316
 
 
317
 
val process_connection :
318
 
      #Nethttpd_reactor.http_processor_config ->
319
 
      #http_engine_processing_config ->
320
 
      Unix.file_descr ->
321
 
      Unixqueue.unix_event_system ->
322
 
      'a http_service ->
323
 
        http_engine_processing_context
324
 
  (** Sets up an engine that processes all requests using the service description.
325
 
    * This function returns immediately, one needs to [Unixqueue.run] the event
326
 
    * system to start the engine.
327
 
    *
328
 
    * The passed [http_engine_processing_config] is crucial for good performance.
329
 
    * XXX
330
 
   *)