libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

actions.inc (15799B)


      1 When handling HTTP requests from clients in a
      2 @code{MHD_RequestCallback} the main result of the handler is always a
      3 @code{struct MHD_Action}.  The action returned by the handler
      4 determines how the processing of the HTTP request should continue.
      5 
      6 @anchor{MHD_Action}
      7 @deftp {C Struct} MHD_Action
      8 Actions are returned by the application to MHD
      9 to drive the request handling of MHD.
     10 @end deftp
     11 
     12 It is important to remember that the
     13 @ref{MHD_RequestCallback,,@code{MHD_RequestCallback}} is
     14 invoked immediately after MHD has parsed the HTTP request
     15 @emph{headers}.  This means, the client may not yet have uploaded the
     16 request body (for example, if the request is using the POST
     17 method). Depending on the HTTP protocol version and the size of the
     18 upload, the client may actually wait for confirmation (``101
     19 Continue'') from the HTTP server before proceeding with the upload.
     20 Thus, when the @code{MHD_RequestCallback} is invoked, we generally
     21 have several choices:
     22 
     23 @itemize @bullet{}
     24 @item Return an HTTP response immediately. If the client would have
     25 proceeded to send a body, this may possibly preempt it from
     26 uploading a body by denying the request.
     27 
     28 @item Fail hard by closing the connection. This is usually the
     29 least desirable choice and should be reserved to cases where the
     30 server has no resources to generate even an response to indicate
     31 a failure.
     32 
     33 @item Suspend handling the request. This can be useful if generating
     34 a response requires some other server-side process to make progress
     35 or to rate-limit overly eager clients. Note that if an application
     36 suspends handling a request, HTTP/1.1-compatible clients may start
     37 the upload anyway (without first waiting for the
     38 "101 Continue" response) as the may fall back to HTTP/1.0 compatibility
     39 in this case. Thus, suspending request handling is not recommended
     40 if an upload is to be prevented.
     41 
     42 @item Explicitly allow the client to upload data, parse it and eventually
     43 return a response (or fail hard by closing the connection).
     44 @end itemize
     45 
     46 @ref{libmicrohttpd2-responses} discusses generating responses in
     47 detail. This chapter will focus on the @emph{other} three
     48 cases.@footnote{There is a special fifth case which applies when an
     49 HTTP/1.x client requests a ``protocol upgrade''.  This is most often
     50 used to create a WebSocket. Creating an action for such protocol
     51 upgrades is described in @ref{libmicrohttpd-upgrade}.}
     52 
     53 @node libmicrohttpd-actions-fail
     54 @section Failing hard by closing the connection
     55 
     56 The simplest way to handle a request is to simply close the
     57 connection, not returning any data to the client. This violates
     58 the HTTP protocol, but is of course the ultimate fallback when
     59 regular error handling is not possible.
     60 
     61 @anchor{MHD_action_abort_request}
     62 @deftypefun {const struct MHD_Action *} MHD_action_abort_request (struct MHD_Request *request)
     63 
     64 Creates an action to tell MHD to close the connection hard
     65 (kind-of breaking HTTP specification). This
     66 is actually simply a macro that is equivalent to just @code{NULL},
     67 except that it also suggests to the compiler that it it should
     68 not emit a warning for not using @var{request}.
     69 @end deftypefun
     70 
     71 
     72 
     73 @node libmicrohttpd-actions-suspend
     74 @section Suspend handling the request
     75 
     76 @code{MHD_action_suspend()} is used to suspend a client's
     77 request. MHD will keep the network connection open until the
     78 application explicitly tells it to resume processing.
     79 
     80 @anchor{MHD_action_suspend}
     81 @deftypefun {const struct MHD_Action *} MHD_action_suspend (struct MHD_Request *request)
     82 
     83 Suspend handling of network data for a given request.  This can
     84 be used to dequeue a request from MHD's event loop for a while.
     85 
     86 Suspended requests continue to count against the total number of
     87 requests allowed (per daemon, as well as per IP, if such limits
     88 are set).  Suspended requests will NOT time out; timeouts will
     89 restart when the request handling is resumed.  While a
     90 request is suspended, MHD may not detect disconnects by the
     91 client.
     92 
     93 @table @var
     94 @item ctx request
     95 the request for which the action is generated
     96 @end table
     97 
     98 The function returns an action to cause a request to be suspended.
     99 
    100 @code{NULL} is returned if any action has been already created for the @var{request}.
    101 @end deftypefun
    102 
    103 After suspending a request, the application must eventually resume
    104 request handling via @code{MHD_request_resume()}.  MHD will then call
    105 the @code{MHD_RequestCallback} again for the @var{request}, allowing
    106 the application to again inspect the request and return a new action.
    107 
    108 @cindex long-polling
    109 @anchor{MHD_request_resume}
    110 @deftypefun void MHD_request_resume (struct MHD_Request *request)
    111 
    112 Resume handling of network data for suspended request.  It is safe to
    113 resume a suspended request at any time.  Calling this function on a
    114 request that was not previously suspended will result in undefined
    115 behaviour. @c FIXME: or a call to the panic function!?
    116 
    117 @table @var
    118 @item ctx request
    119 the request to resume
    120 @end table
    121 @end deftypefun
    122 
    123 If you are using this function in @emph{external} select mode, you
    124 must make sure to run @code{MHD_daemon_process_blocking()} afterwards
    125 (as otherwise the change may not be reflected in the set returned to
    126 your @code{MHD_SocketRegistrationUpdateCallback} and you may end up
    127 with a request that is stuck until the next network activity).
    128 
    129 
    130 @node libmicrohttpd-actions-upload
    131 @section Processing a request body
    132 
    133 There are various ways to create an action that tells MHD that the
    134 application wants to process the body being uploaded by the client. If
    135 the client sent an ``Expect: 100-Continue'' header with its request,
    136 returning any of these will automatically cause MHD to respond with a
    137 ``100 Continue'' status and initiate receiving the response from the
    138 client.  Thus, applications should never attempt to explicitly return
    139 ``100 Continue'' themselves.
    140 
    141 The main function to call to handle uploads discussed in this
    142 section is @code{MHD_action_process_upload()}. While this function
    143 in principle works for any kind of upload, it is not the most
    144 convenient when handling structured data from an HTML form that
    145 is encoded as ``application/x-www-form-urlencoded'' or
    146 ``multipart/form-data'' or the (less common) ``text/plain''
    147 HTML5 form.  When handling uploads of these formats, it is
    148 usually better to use @ref{MHD_action_parse_post}.
    149 
    150 @anchor{MHD_action_process_upload}
    151 @deftypefun {const struct MHD_Action *} MHD_action_process_upload (struct MHD_Request *request, size_t large_buffer_size, MHD_UploadCallback uc_full, void *uc_full_cls, MHD_UploadCallback uc_inc, void *uc_inc_cls)
    152 
    153 Creates an action that handles an upload from a client.
    154 
    155 @c FIXME: this isn't exactly elegant. We should see if we can
    156 @c provide a way to generate a TOO_LARGE status response properly instead!
    157 If @var{uc_inc} is @code{NULL} and the body does not fit
    158 into the allocated buffer, the request is aborted without
    159 any response by closing the connection.
    160 
    161 @table @var
    162 @item request
    163 the request to create action for;
    164 
    165 @item large_buffer_size
    166 how large should the upload buffer be.
    167 May allocate memory from the shared "large"
    168 memory pool if necessary and non-zero is given.
    169 Must be zero if @var{uc_full} is @code{NULL};
    170 
    171 @item uc_full
    172 function to call when complete body is
    173 received (only if it fits into @var{upload_buffer_size} bytes;
    174 can be @code{NULL} if @var{uc_inc} is not @code{NULL};
    175 must be @code{NULL} is @var{upload_buffer_size} is zero;
    176 
    177 @item uc_full_cls
    178 closure for @var{uc_full};
    179 
    180 @item uc_inc
    181 function to call to incrementally process the uploaded data
    182 if the upload if larger than @var{upload_buffer_size}
    183 or if @var{upload_buffer_size} cannot be allocated or
    184 if @var{uc_full} is @code{NULL};
    185 can be @code{NULL} if @var{uc_full} is not @code{NULL};
    186 
    187 @item uc_inc_cls
    188 closure for @var{uc_inc}.
    189 @end table
    190 
    191 The function returns @code{NULL} on error (out of memory, invalid parameters)
    192 or if any action has been already created for the @var{request},
    193 and otherwise a pointer to the action.
    194 @end deftypefun
    195 
    196 @code{MHD_action_process_upload()} is a bit overly complicated
    197 as it conflates the two main use-cases:
    198 
    199 @itemize
    200 @item handling of the entire data body in one buffer in memory, and
    201 @item incremental parsing of the upload over time.
    202 @end itemize
    203 
    204 In practice, applications are expected to use the two APIs
    205 that separate these use-cases, specifically
    206 @code{MHD_action_process_upload_full()} and
    207 @code{MHD_action_process_upload_inc()}.
    208 
    209 @anchor{MHD_action_process_upload_full}
    210 @deftypefun {const struct MHD_Action *} MHD_action_process_upload_full (struct MHD_Request *request, size_t large_buffer_size, MHD_UploadCallback uc_full, void *uc_full_cls)
    211 
    212 Creates an action that handles an upload from a client
    213 as a full upload data where MHD places all uploaded data
    214 into a buffer and then gives the result to the application
    215 all at once.
    216 
    217 @c FIXME: this isn't exactly elegant. We should see if we can
    218 @c provide a way to generate a TOO_LARGE status response properly instead!
    219 If @var{uc_inc} is @code{NULL} and the body does not fit
    220 into the allocated buffer, the request is aborted without
    221 any response by closing the connection.
    222 
    223 @table @var
    224 @item request
    225 the request to create action for
    226 
    227 @item large_buffer_size
    228 how large should the upload buffer be.
    229 May allocate memory from the shared "large"
    230 memory pool if necessary. Usually the value
    231 given here will be the size of the upload as
    232 provided by the HTTP request header.
    233 
    234 @item uc_full
    235 function to call when complete body is
    236 received (only if it fits into @var{upload_buffer_size} bytes;
    237 
    238 @item uc_full_cls
    239 closure for @var{uc_full}.
    240 @end table
    241 
    242 The function returns @code{NULL} on error (out of memory, invalid parameters)
    243 or if any action has been already created for the @var{request},
    244 and otherwise a pointer to the action.
    245 @end deftypefun
    246 
    247 @anchor{MHD_action_process_upload_inc}
    248 @deftypefun {const struct MHD_Action *} MHD_action_process_upload_inc (struct MHD_Request *request, MHD_UploadCallback uc_inc, void *uc_inc_cls)
    249 
    250 Creates an action that handles an upload from a client incrementally.
    251 
    252 @table @var
    253 @item request
    254 the request to create action for;
    255 
    256 @item uc_inc
    257 function to call to incrementally process the uploaded data;
    258 
    259 @item uc_inc_cls
    260 closure for @var{uc_inc}.
    261 @end table
    262 @end deftypefun
    263 
    264 In all three cases, the application must provide callbacks to handle
    265 the uploaded data. These callbacks have the type @code{MHD_UploadCallback}.
    266 The application is provided with the uploaded data (either all of it at
    267 once or just the latest increment) and must return a
    268 @code{struct MHD_UploadAction} to determine how to continue handling
    269 the @var{request}.
    270 
    271 
    272 @anchor{MHD_UploadCallback}
    273 @deftypefn {Function Pointer} {struct MHD_UploadAction *} (*MHD_UploadCallback) (void *cls, struct MHD_Request *request, size_t content_data_size, void *content_data)
    274 
    275 Functions of this type are invoked by MHD whenever an application
    276 should process the HTTP body of a client's request.
    277 
    278 @table @var
    279 @item upload_cls
    280 custom closure provided by the application together with the
    281 pointer to the function
    282 
    283 @item request
    284 the request that is being processed
    285 
    286 @item content_data_size
    287 number of bytes in @var{content_data},
    288 zero when all data have been processed;
    289 
    290 @item content_data
    291 @var{content_data_size} bytes of the HTTP request body;
    292 can be safely modified in the callback;
    293 the buffer is valid only until the application
    294 returns from the callback;
    295 @code{NULL} when all data of the body have been processed;
    296 
    297 @end table
    298 The returned @code{struct MHD_UploadAction}
    299 informs MHD how to proceed further with the
    300 @var{request}.  Returning @code{NULL} is
    301 equivalent to @code{MHD_upload_action_abort_request()}.
    302 @end deftypefn
    303 
    304 The @code{struct MHD_UploadAction} is quite similar to
    305 the @ref{MHD_Action,,@code{struct MHD_Action}} except that it is only
    306 applicable when processing client uploads.
    307 
    308 @anchor{MHD_UploadAction}
    309 @deftp {C Struct} MHD_UploadAction
    310 Actions are returned by the application to MHD
    311 to drive the request handling of MHD.
    312 @end deftp
    313 
    314 There are four basic @code{struct MHD_UploadAction}s that
    315 applications can use:
    316 
    317 @c FIXME: the fact that there are upload actions that only
    318 @c work for incremental upload processing suggests to me
    319 @c again that we should just have MHD_Action and not Upload/DCC actions.
    320 @itemize
    321 @item continue processing the upload (for incremental upload processing only)
    322 @item suspend processing the upload (say to slow down the client to allow
    323   the application to keep up)
    324 @item abort handling the request (closing the connection), and
    325 @item returning an HTTP response
    326 @end itemize
    327 
    328 The following functions generate the respective upload actions.
    329 
    330 
    331 @anchor{MHD_upload_action_continue}
    332 @deftypefun {const struct MHD_UploadAction *} MHD_upload_action_continue (struct MHD_Request *request)
    333 
    334 Action telling MHD to continue processing the upload.
    335 Valid only for incremental upload processing.
    336 
    337 @table @var
    338 @item request
    339 the request to create the upload action for;
    340 @end table
    341 
    342 Fails and returns @code{NULL} when used in combination with a
    343 full upload callback, for the final (with zero bytes of data)
    344 call to an incremental callback or on a request that is not
    345 handling an upload.
    346 @c FIXME: the fact that we fail here if an upload action
    347 @c is created for a request that isn't doing an upload suggests to me
    348 @c again that we should just have MHD_Action and not Upload/DCC actions.
    349 
    350 @end deftypefun
    351 
    352 
    353 @anchor{MHD_upload_action_abort_request}
    354 @deftypefun {const struct MHD_UploadAction *} MHD_upload_action_abort_request (struct MHD_Request *request)
    355 
    356 Aborts handling the request by closing the connection. This
    357 is actually simply a macro that is equivalent to just @code{NULL},
    358 except that it also suggests to the compiler that it it should
    359 not emit a warning for not using @var{request}.
    360 
    361 @table @var
    362 @item request
    363 the request to create the upload action for;
    364 @end table
    365 @end deftypefun
    366 
    367 
    368 @anchor{MHD_upload_action_from_response}
    369 @deftypefun {const struct MHD_UploadAction *} MHD_upload_action_from_response (struct MHD_Request *request, struct MHD_Response *response)
    370 
    371 Converts a @var{response} to an upload action.  If
    372 @code{MHD_R_O_REUSABLE} is not set, the reference to the
    373 @var{response} is consumed by the conversion. If
    374 @code{MHD_R_O_REUSABLE} is @code{MHD_YES}, then the @var{response} can
    375 be used again to create other actions in the future.  However, the
    376 @var{response} is frozen by this step and must no longer be modified
    377 (i.e. by setting headers).
    378 
    379 @table @var
    380 @item request
    381 the request to create the upload action for;
    382 
    383 @item response
    384 the response to return to the client.
    385 @end table
    386 
    387 The function returns a pointer to the upload action; the upload action
    388 must be consumed otherwise the response object may leak; The function
    389 returns @code{NULL} if it failed (no memory) or if any other upload
    390 action has been already created for the @var{request} (or if the
    391 request is currently not in a state of handling an upload).  When the
    392 function fails, the response object is nevertheless consumed and need
    393 not be "destroyed" by the application.
    394 
    395 @end deftypefun
    396 
    397 @anchor{MHD_upload_action_suspend}
    398 @deftypefun {const struct MHD_UploadAction *} MHD_upload_action_suspend (struct MHD_Request *request)
    399 
    400 Suspend handling of network data for the given @var{request}.  This can
    401 be used to dequeue a request from MHD's event loop for a while.
    402 
    403 Suspended requests continue to count against the total number of
    404 requests allowed (per daemon, as well as per IP, if such limits
    405 are set).  Suspended requests will NOT time out; timeouts will
    406 restart when the request handling is resumed.  While a
    407 request is suspended, MHD may not detect disconnects by the
    408 client.
    409 
    410 @table @var
    411 @item request
    412 the request to create the upload action for;
    413 @end table
    414 @end deftypefun
    415 
    416 After suspending an upload action, applications must
    417 use @ref{MHD_request_resume,,@code{MHD_request_resume()}}
    418 to resume processing the upload.