(index ("call-with-response" 0) ("call-with-input-request" 2440) ("call-with-input-request*" 5810) ("with-input-from-request" 6757) ("max-retry-attempts" 7319) ("retry-request?" 7778) ("max-redirect-depth" 8399) ("client-software" 8859) ("prepare-request" 9287) ("default-prepare-request" 9926) ("max-idle-connections" 10282) ("close-connection!" 10714) ("close-idle-connections!" 10853) ("close-all-connections!" 11102) ("default-server-connector" 11244) ("server-connector" 11881) ("get-cookies-for-uri" 12634) ("store-cookie!" 12961) ("delete-cookie!" 13931) ("determine-username/password" 14286) ("http-authenticators" 14998) ("determine-proxy" 16488) ("determine-proxy-from-environment" 17417) ("determine-proxy-username/password" 19061))
(def (sig (procedure "(call-with-response request writer reader)" (id call-with-response))) (p "This is the core http-client procedure, but it is also pretty low-level.  It is only necessary to use this when you want the most control over the request/response cycle.  Otherwise, you should use " (tt "with-input-from-request") ", " (tt "call-with-input-request") " or " (tt "call-with-input-request*") ".") (p (tt "request") " is the request object that contains information about the request to perform.  " (tt "reader") " is a procedure that receives the response object and should read the " (i "entire") " request body (any leftover data will cause errors on subsequent requests with keepalive connections), " (tt "writer") " is a procedure that receives the request object and should write the request body.") (p "The " (tt "writer") " should be prepared to be called several times; if the response is a redirect or some other status that indicates the server wants the client to perform a new request, the writer should be ready to write a request body for this new request. In case digest authentication with message integrity checking is used, " (tt "writer") " is always invoked at least twice, once to determine the message digest of the response and once to actually write the response.") (p "Returns three values: The result of the call to " (tt "reader") " (or " (tt "#f") " if there is no message body in the response), the request-uri of the last request and the response object. The request-uri is useful because this is to be used as the base uri of the document. This can differ from the initial request in the presence of redirects.") (p "If there is no response body to read (as determined by intarweb's " (tt "response-has-message-body-for-request?") "), the " (tt "reader") " procedure is not invoked at all.") (p "If successive requests cause more than " (tt "max-redirect-depth") " redirect responses to occur, a condition of type " (tt "(exn http redirect-depth-exceeded)") " is raised.") (p "If the request's URI or the URI of a used proxy is of an unsupported type, a condition of type " (tt "(exn http unsupported-uri-scheme)") " is raised (this can of course also occur when the initial URI is correct, but the server redirects to an URI with an unsupported scheme).") (p "When the request requires authentication of an unsupported type, a condition of type " (tt "(exn http unknown-authtype)") " is raised."))
(def (sig (procedure "(call-with-input-request uri-or-request writer reader)" (id call-with-input-request))) (p "This procedure is a convenience wrapper around " (tt "call-with-response") ".") (p "It is much less strict - " (tt "uri-or-request") " can be an " (int-link "intarweb") " request object, but also an " (int-link "uri-common") " object or even a string with the URI in it, in which case a request object will be automatically constructed around the URI, using the " (tt "GET") " method when " (tt "writer") " is " (tt "#f") " or the " (tt "POST") " method when " (tt "writer") " is not " (tt "#f") ".") (p (tt "writer") " can be either " (tt "#f") " (in which case nothing is written and the " (tt "GET") " method chosen), a string containing the raw data to send, an alist, or a procedure that accepts a port and writes the response data to it.  If you supply a procedure, do not forget to set the " (tt "content-length") " header!  In the other cases, whenever possible, the length is calculated and the header automatically set for you.") (p "If you supplied an alist, the " (tt "content-type") " header is automatically set to " (tt "application/x-www-form-urlencoded") " unless there's an alist entry whose value is a list starting with the keyword " (tt "file:") ", in which case " (tt "multipart/form-data") " is used.  See the examples for " (tt "with-input-from-request") " below.  If the data cannot be form-encoded, a condition of type " (tt "(exn http formdata-error)") " is raised.") (p (tt "reader") " is either " (tt "#f") " or a procedure which accepts a port and reads out the data.  If there is data left in the port when the reader returns (or " (tt "#f") " was supplied), this will be automatically discarded to avoid problems.") (p "Returns three values: The result of the call to " (tt "reader") " (or " (tt "#f") " if there is no message body in the response), the request-uri of the last request and the response object.  If the response code is not in the 200 class, it will raise a condition of type " (tt "(exn http client-error)") ", " (tt "(exn http server-error)") " or " (tt "(exn http unexpected-server-response)") ", depending on the response code.  This includes " (tt "404 not found") " (which is a " (tt "client-error") ").") (p "If there is no response body to read (as determined by intarweb's " (tt "response-has-message-body-for-request?") "), the " (tt "reader") " procedure is not invoked at all.") (p "When posting multipart form data, the value of a file entry is a list of keyword-value pairs.  The following keywords are recognised:") (dl (dt (tt "file:")) (dd "This indicates the file to read from.  Can be either a string or a port. This " (i "must") " be specified, everything else is optional.") (dt (tt "filename:")) (dd "This indicates the filename to pass on to the server.  If not specified or " (tt "#f") ", the " (tt "file:") "'s string (or port-name in case of a port) will be used.") (dt (tt "headers:")) (dd "Additional headers to send for this entry (an " (int-link "intarweb") " headers-object).")) (p "If the URI argument is not a valid URI, a condition of type " (tt "(exn http client-error bad-uri)") " will be raised.") (p "If the writer is a list it is taken to be form-data, but if the encoding fails, a condition of type " (tt "(exn http client-error form-data-error)") " will be raised."))
(def (sig (procedure "(call-with-input-request* uri-or-request writer reader)" (id call-with-input-request*))) (p "As " (tt "call-with-input-request") ", except " (tt "reader") " is passed two arguments: the input port and the complete intarweb response object (useful for when you want to inspect headers or other aspects of the response).") (p "Please note that the port is " (b "not") " the same as the " (tt "response-port") " from the response object: the port is delimited so that you can read until " (tt "EOF") ".  The " (tt "response-port") " is the original underlying, unbounded port.  If you do want to read from it, you must make sure to read no more than what's in the " (tt "Content-Length") " header, if present.  If the header is not present, it will either be a chunked port (which is implicitly delimited by intarweb) or the port will be closed by the remote end after it is consumed, so you can read until EOF in that case."))
(def (sig (procedure "(with-input-from-request uri-or-request writer-thunk reader-thunk)" (id with-input-from-request))) (p "Same as " (tt "call-with-input-request") ", except when you pass a procedure as " (tt "reader-thunk") " or " (tt "writer-thunk") " it has to be a thunk (lambda of no arguments) instead of a procedure of one argument.  These thunks will be executed with the current input (or output) port to the request or response port, respectively.") (p "You can still pass " (tt "#f") " for both or an alist or string for " (tt "writer-thunk") "."))
(def (sig (parameter "(max-retry-attempts [number])" (id max-retry-attempts))) (p "When a request fails because of an I/O or network problem (or simply because the remote end closed a persistent connection while we were doing something else), the library will try to establish a new connection and perform the request again.  This parameter controls how many times this is allowed to be done.  If " (tt "#f") ", it will never give up.") (p "Defaults to 1."))
(def (sig (parameter "(retry-request? [predicate])" (id retry-request?))) (p "This procedure is invoked when a retry should take place, to determine if it should take place at all.  It should be a procedure accepting a request object and returning " (tt "#f") " or a true value.  If the value is true, the new request will be sent.  Otherwise, the error that caused the retry attempt will be re-raised.") (p "Defaults to " (tt "idempotent?") ", from " (int-link "intarweb") ".  This is because non-idempotent requests cannot be safely retried when it is unknown whether the previous request reached the server or not."))
(def (sig (parameter "(max-redirect-depth [number])" (id max-redirect-depth))) (p "The maximum number of allowed redirects, or " (tt "#f") " if there is no limit.  Currently there's no automatic redirect loop detection algorithm implemented.  If zero, no redirects will be followed at all.") (p "Defaults to 5.") (p "When the redirect limit is reached, " (tt "call-with-response") " raises a condition of type " (tt "(exn http redirect-depth-exceeded)") "."))
(def (sig (parameter "(client-software [software-spec])" (id client-software))) (p "This is the names, versions and comments of the software packages that the client is using, for use in the " (tt "user-agent") " header which is automatically added to each request by " (tt "prepare-request") ".") (p "Defaults to " (tt "((\"Chicken Scheme HTTP-client\" VERSION #f))") ", where " (tt "VERSION") " is the version of this egg."))
(def (sig (parameter "(prepare-request [preparer])" (id prepare-request))) (p "Here, " (tt "preparer") " is a procedure which will be called every time a connection is made.  This includes every request in a redirect chain, so you can decide for every URL in the chain what to do with the request.  The procedure receives and must return an intarweb request object.  The default implementation is " (tt "default-prepare-request") ".") (p (b "CAVEAT") ": If you decide to change the request-uri last-minute, you must also set the " (tt "host") " header, because it will have already been initialized to the request-uri's host attribute."))
(def (sig (procedure "(default-prepare-request req)" (id default-prepare-request))) (p "This is the default implementation of the " (tt "prepare-request") " parameter.  It sets the " (tt "User-Agent") " header from the " (tt "client-software") " parameter and adds " (tt "set-cookie") " headers which belong to the server and path from the request-uri."))
(def (sig (parameter "(max-idle-connections [count])" (id max-idle-connections))) (p "This controls the maximum allowed idle connections at any given time. When a connection would be returned to the pool, the connection will be discarded instead, if the maximum is exceeded.") (p "This value should always be well below the maximum number of available file descriptors for your operating system.") (p "Defaults to " (tt "32") "."))
(def (sig (procedure "(close-connection! uri)" (id close-connection!))) (p "Close the connection to the server associated with the URI."))
(def (sig (procedure "(close-idle-connections!)" (id close-idle-connections!))) (p "Close all remaining idle connections.  Note that connections that are currently in use will still be returned to the connection pool after their requests finish!"))
(def (sig (procedure "(close-all-connections!)" (id close-all-connections!))) (p "Deprecated alias for " (tt "close-idle-connections!") "."))
(def (sig (procedure "(default-server-connector uri proxy)" (id default-server-connector))) (p "The default value of the " (tt "server-connector") " parameter.  This procedure creates a connection to the remote end for the given " (tt "uri") " (an " (int-link "uri-common") " object) and returns two values: an input port and an output port.") (p "If " (tt "proxy") " is not " (tt "#f") " but an " (int-link "uri-common") " object, it will connect to that, instead.") (p "This connector supports plain " (tt "http") " connections, and " (tt "https") " if the " (tt "openssl") " egg can be loaded (which it attempts to do on the fly)."))
(def (sig (parameter "(server-connector [connector])" (id server-connector))) (p "This parameter holds a procedure which is invoked to establish a connection for an URI.") (p "The procedure should accept two " (int-link "uri-common") " objects as arguments: the first indicates the URI for which the connection is to be made and the second indicates the proxy through which the connection should be made, or " (tt "#f") " if a direct connection should be made to the first URI's host and port.  It should return two values: an input port and an output port corresponding to the connection.") (p "This can be used for nonstandard or complex connections, like for example connecting to UNIX domain sockets or for supplying SSL/TLS client certificates."))
(def (sig (procedure "(get-cookies-for-uri uri)" (id get-cookies-for-uri))) (p "Fetch a list of all cookies which ought to be sent to the given URI. Cookies are vectors of two elements: a name/value pair and an alist of attributes.  In other words, these are the exact same values you can put in a " (tt "cookie") " header."))
(def (sig (procedure "(store-cookie! cookie-info set-cookie)" (id store-cookie!))) (p "Store a cookie in the cookiejar corresponding to the Set-Cookie header given by " (tt "set-cookie") ".  This overwrites any cookie that is equal to this cookie, as defined by RFC 2965, section 3.3.3.  Practically, this means that when the cookie's name, domain and path are equal to an existant one, it will be overwritten by the new one.  These attributes are taken from the " (tt "cookie-info") " alist and expected to be there.") (p "Generally, attributes should be taken from " (tt "set-cookie") ", but if missing they ought to be taken from the request URI that responded with the " (tt "set-cookie") ".") (highlight scheme "(store-cookie! `((path . ,(make-uri path: '(/ \"\")))\n                 (domain . \"some.host.com\")\n                 (secure . #t))\n               `#((\"COOKIE_NAME\" . \"cookie-value\")\n                  ((path . ,(make-uri path: '(/ \"\"))))))"))
(def (sig (procedure "(delete-cookie! cookie-name cookie-info)" (id delete-cookie!))) (p "Removes any cookie from the cookiejar that is equal to the given cookie (again, in the sense of RFC 2965, section 3.3.3). The " (tt "cookie-name") " must match and the " (tt "path") " and " (tt "domain") " values for the " (tt "cookie-info") " alist must match."))
(def (sig (parameter "(determine-username/password [HANDLER])" (id determine-username/password))) (p "The procedure in this parameter is called whenever the remote host requests authentication via a 401 Unauthorized response.") (p "The " (tt "HANDLER") " is a procedure of two arguments; the URI for the resource currently being requested and the realm (a string) which wants credentials.  The procedure should return two string values: the username and the password to use for authentication.") (p "The default value is a procedure which extracts the username and password components from the URI.") (p "For proxy authentication support, see " (tt "determine-proxy-username/password") " in the next section."))
(def (sig (parameter "(http-authenticators [AUTHENTICATORS])" (id http-authenticators))) (p "This parameter allows for pluggable authentication schemes. " (tt "AUTHENTICATORS") " is an alist mapping authentication scheme name to a procedure of 7 arguments:") (p (tt "(lambda (response response-header new-request request-header uri realm writer) ...)")) (p "Here, " (tt "response") " is the response object, " (tt "response-header") " is the name of the response header which required authentication - a symbol which is either " (tt "www-authenticate") " or " (tt "proxy-authenticate") ".") (p (tt "new-request") " is the request that will be sent next, to be populated with additional headers by the authenticator procedure, and " (tt "request-header") " is the name of the request header which is expected to be provided and supplied with extra details by the authenticator - also a symbol, which is either " (tt "authorization") " or " (tt "proxy-authorization") ".") (p (tt "uri") " is the URI which was requested when the authorization was demanded (in case of " (tt "www-authenticate") ", the protected resource) and " (tt "realm") " is the authentication realm (a string).") (p "Finally " (tt "writer") " is the writer procedure passed by the user or fabricated by " (tt "call-with-input-request") " based on the user's form arguments.  It's always a procedure accepting a request object. This is only needed when full-request authentication is desired, to obtain a request body."))
(def (sig (parameter "(determine-proxy [HANDLER])" (id determine-proxy))) (p "Whenever a request is sent, the library invokes the procedure stored in this parameter to determine through what proxy to send the request, if any.") (p "The " (tt "HANDLER") " procedure receives one argument, the URI about to be requested, and returns either an " (int-link "uri-common") " absolute URI object representing the proxy or " (tt "#f") " if no proxy should be used.") (p "The URI's path and query, if present, are ignored; only the scheme and authority (host, port, username, password) are used.") (p "The default value of this parameter is " (tt "determine-proxy-from-environment") ".") (highlight scheme "(determine-proxy\n (lambda (url)\n   (uri-reference \"http://127.0.0.1:8888/\")))") (p "If you just want to disable proxy support, you can do:") (highlight scheme "(determine-proxy (constantly #f))   ; From unit data-structures"))
(def (sig (procedure "(determine-proxy-from-environment URI)" (id determine-proxy-from-environment))) (p "This procedure implements the common behaviour of HTTP software under UNIX:") (ul (li "First it checks if the requested URI's host (or an asterisk) is listed in the " (tt "NO_PROXY") " environment variable (if suffixed with a port number, the port is also compared).  If a match is found, no proxy is used.") (li "Then it will check if the " (tt "$(protocol)_proxy") " or the " (tt "$(PROTOCOL)_PROXY") " variable (in that order) are set.  If so, that's used.  " (tt "protocol") " here actually means \"scheme\", so the URI's scheme is used, suffixed with " (tt "_proxy") ". This means " (tt "http_proxy") " is used for HTTP requests and " (tt "https_proxy") " is used for HTTPS requests, but see the next point.") (li "If the scheme is " (tt "http") " and the environment variable " (tt "REQUEST_METHOD") " is present, " (tt "CGI_HTTP_PROXY") " is used instead of " (tt "HTTP_PROXY") " to prevent a \"" (link "https://httpoxy.org" "httpoxy") "\" attack.  This makes the assumption that " (tt "REQUEST_METHOD") " is set because the library is being used in a CGI script.") (li "If there's still no match, it looks for " (tt "all_proxy") " or " (tt "ALL_PROXY") ", in that order. If one of these environment variables are set, that value is used as a fallback proxy.") (li "Finally, if none of these checks resulted in a proxy URI, no proxy will be used.")) (p "Some UNIX software expects plain hostnames or hostname port combinations separated by colons, but (currently) this library expects full URIs, like most modern UNIX programs."))
(def (sig (parameter "(determine-proxy-username/password [HANDLER])" (id determine-proxy-username/password))) (p "The procedure in this parameter is called whenever the proxy requests authentication via a 407 Proxy Authentication Required response. This basically works the same as authentication against an origin server.") (p "The " (tt "HANDLER") " is a procedure of two arguments; the URI for the " (i "proxy") " currently being used and the realm (a string) which wants credentials.  The procedure should return two string values: the username and the password to use for authentication.") (p "The default value is a procedure which extracts the username and password components from the proxy's URI."))
