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.