(* $Id: http_client.mli 945 2006-07-11 21:35:50Z gerd $ *)
(** HTTP 1.1 client *)
(**********************************************************************)
(* HTTP/1.1 client *)
(* written by Gerd Stolpmann *)
(**********************************************************************)
(** {b Note for beginners:} There is a simplified interface called
* {!Http_client.Convenience}.
*)
(** Implements much of HTTP/1.1.
* Implements the following advanced features:
* - chunked messages
* - persistent connections
* - connections in pipelining mode ("full duplex" connections)
* - modular authentication methods, currently Basic and Digest
* - event-driven implementation; allows concurrent service for
* several network connections
*
* Left out:
* - multipart messages, including multipart/byterange
* - content encoding (compression) (1)
* - content digests specified by RFC 2068 and 2069 (1)
* - content negotiation (1)
* - conditional and partial GET (1)
* - following code 303 redirections automatically (1)
* - client-side caching (1)
* - HTTP/0.9 compatibility
*
* (1) These features can be implemented on top of this module if really needed,
* but there is no special support for them.
*)
(** {b Thread safety}
*
* The module can be compiled such that it is thread-safe. In particular,
* one has to link the http_client_mt.cm[xo] object, and thread-safety is
* restricted to the following kinds of usage:
* - The golden rule is that threads must not share pipeline objects.
* If every thread uses its own pipeline, every thread will have its own
* set of state variables.
* It is not detected if two threads errornously share a pipeline,
* neither by an error message nor by implicit serialization. Strange
* things may happen.
* - The same applies to the other objects, e.g. http_call objects
* - The [Convenience] module even serializes; see below.
*)
(** {1 Types and Exceptions} *)
exception Bad_message of string;;
(** The server sent a message which cannot be interpreted. The string
* indicates the reason.
*)
exception No_reply;;
(** There was no response to the request because some other request failed
* earlier and it was not allowed to send the request again.
*)
exception Too_many_redirections
(** While following redirections the limit has been reached *)
exception Name_resolution_error of string
(** Could not resolve this name *)
exception URL_syntax_error of string
(** This URL cannot be parsed after a redirection has been followed.
*)
exception Http_protocol of exn;;
(** The request could not be processed because the exception condition
* was raised. The inner exception is one of the above defined.
*)
exception Http_error of (int * string);;
(** {b Deprecated.}
* The server sent an error message. The left component of the pair is
* the error code, the right component is the error text.
* This exception is only used by [get_resp_body].
*)
type status =
[ `Unserved
| `Http_protocol_error of exn
| `Successful
| `Redirection
| `Client_error
| `Server_error
]
(** Condensed status information of a HTTP call:
* - [`Unserved]: The call has not yet been finished
* - [`HTTP_protocol_error e]: An error on HTTP level occurred. Corresponds
* to the exception [Http_protocol].
* - [`Successful]: The call is successful, and the response code is between
* 200 and 299.
* - [`Redirection]: The call is successful, and the response code is
* between 300 and 399.
* - [`Client_error]: The call failed with a response code between 400 and
* 499.
* - [`Server_error]: The call failed for any other reason.
*)
type 'message_class how_to_reconnect =
Send_again (** Send the request automatically again *)
| Request_fails (** Drop the request *)
| Inquire of ('message_class -> bool)
(** If the function return [true] send again, otherwise
* drop the request.
*)
| Send_again_if_idem (** Default behaviour: [Send_again] for idempotent
* methods (GET, HEAD), [Request_fails] for the rest
*)
(** How to deal with automatic reconnections, especially when the
* connection crashes.
*)
;;
type 'message_class how_to_redirect =
Redirect (** Perform the redirection *)
| Do_not_redirect (** No redirection *)
| Redirect_inquire of ('message_class -> bool)
(** If the function return [true] redirect, otherwise
* do not redirect. It is legal to set the [Location]
* header as part of the action performed by the
* function. (Should be an absolute http URL.)
*)
| Redirect_if_idem (** Default behaviour: [Redirect] for idempotent
* methods (GET, HEAD), [Do_not_redirect] for the rest
*)
;;
type private_api ;;
(** The private part of the [http_call] class type *)
type response_body_storage =
[ `Memory
| `File of unit -> string
| `Body of unit -> Netmime.mime_body
]
(** How to create the response body:
* - [`Memory]: The response body is in-memory
* - [`File f]: The response body is stored into the file whose name
* is returned by [f()]
* - [`Body f]: The response body is stored into the object returned
* by [f()]
*)
type synchronization =
| Sync
(** The next request begins after the response of the last request has
* been received.
*)
| Pipeline of int
(** The client is allowed to send several requests without waiting
* for responses. The number is the maximum number of unreplied
* requests that are allowed. A typical value: 5.
* If you increase this value, the risk becomes higher that requests
* must be repeatedly sent to the server in the case the connection
* crashes. Increasing is recommended if you send a bigger number of
* GET or HEAD requests to the server. Decreasing is recommended if you
* send large POST or PUT requests to the server.
*
* Values > 8 are interpreted as 8.
*)
(** This type determines whether to keep requests and responses
* synchronized or not.
*
* The first request/response round is always done in
* Sync mode, because the protocol version of the other side
* is not known at that moment. [Pipeline] requires HTTP/1.1.
*
* In previous versions of netclient there was a third option,
* [Sync_with_handshake_before_request_body]. This option is no
* longer necessary because the HTTP specification has been updated
* in the meantime, and there is a better mechanism now (the
* [Expect] header is set).
*)
;;
type resolver =
Unixqueue.unix_event_system ->
string ->
(Unix.inet_addr option -> unit) ->
unit
(** A name resolver is a function [r] called as [r esys name reply].
* As [name] the name to resolve is passed. The resolver must
* finally call [reply] with either the resolved address or
* with [None], indicating an error in the latter case.
* The event system [esys] can be used to carry out the resolution
* process in an asynchronous way, but this is optional.
*
* Only 1:1 resolution is supported, 1:n resolution not.
*)
type http_options =
{ synchronization : synchronization;
(** Default: [Pipeline 5]. *)
maximum_connection_failures : int;
(** This option limits the number of connection attempts.
* Default: 2
*)
maximum_message_errors : int;
(** This option limits the number of protocol errors tolerated per
* request. If a request leads to a protocol error, the connection
* is shut down, the server is connected again, and the request is
* tried again (if the kind of the message allows retransmission).
* If a request repeatedly fails, this option limits the number
* of retransmissions.
* Default: 2
*)
inhibit_persistency : bool;
(** This option turns persistent connections off.
* Default: [false]
* It is normally not necessary to change this option.
*)
connection_timeout : float;
(** If there is no network transmission for this period of time,
* the connection is shut down, and tried again.
* Default: 300.0 (seconds)
* It may be necessary to increase this value if HTTP is used for
* batch applications that contact extremely slow services.
*)
number_of_parallel_connections : int;
(** The client keeps up to this number of parallel connections to
* a single content server or proxy.
* Default: 2
* You may increase this value if you are mainly connected with
* an HTTP/1.0 proxy.
*)
maximum_redirections : int;
(** The maximum number of redirections per message *)
handshake_timeout : float;
(** The timeout when waiting for "100 Continue". Default: 1.0 *)
resolver : resolver;
(** The function for name resolution *)
configure_socket : Unix.file_descr -> unit;
(** A function to configure socket options *)
verbose_status : bool;
verbose_request_header : bool;
verbose_response_header : bool;
verbose_request_contents : bool;
verbose_response_contents : bool;
verbose_connection : bool;
(** Enable various debugging message types.
* - [verbose_status]: reports about status of received documents
* - [verbose_request_header]: prints the header sent to the server
* - [verbose_request_contents]: prints the document sent to the server
* - [verbose_response_header]: prints the header of the answer from the server
* - [verbose_response_contents]: prints the document received from the server
* - [verbose_connection]: reports many connection events; authentication,
* too.
*)
}
(** Options for the whole pipeline *)
;;
type header_kind = [ `Base | `Effective ]
(** The [`Base] header is set by the user of [http_call] and is never
* changed during processing the call. The [`Effective] header is