-- -- HTTP client for use with io-streams -- -- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd -- -- The code in this file, and the program it is a part of, is -- made available to you by its authors as open source software: -- you can redistribute it and/or modify it under the terms of -- the BSD licence. -- {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS -fno-warn-orphans #-} {-| Maintainer: Andrew Cowie Stability: Experimental /Overview/ A simple HTTP client library, using the Snap Framework's @io-streams@ library to handle the streaming I\/O. The @http-streams@ API is designed for ease of use when querying web services and dealing with the result. Given: > import System.IO.Streams (InputStream, OutputStream, stdout) > import qualified System.IO.Streams as Streams > import qualified Data.ByteString as S and this library: > import Network.Http.Client the underlying API is straight-forward. In particular, constructing the 'Request' to send is quick and to the point: @ \ main :: IO () \ main = do \ c <- 'openConnection' \"www.example.com\" 80 \ q <- 'buildRequest' $ do \ 'http' GET \"\/\" \ 'setAccept' \"text/html\" \ 'sendRequest' c q 'emptyBody' \ `receiveResponse` c (\\p i -> do \ x <- Streams.read b \ S.putStr $ fromMaybe \"\" x) \ 'closeConnection' c @ which would print the first chunk of the response back from the server. Obviously in real usage you'll do something more interesting with the 'Response' in the handler function, and consume the entire response body from the InputStream ByteString. Because this is all happening in 'IO' (the defining feature of @io-streams@!), you can ensure resource cleanup on normal or abnormal termination by using @Control.Exception@'s standard 'Control.Exception.bracket' function; see 'closeConnection' for an example. For the common case we have a utility function which wraps @bracket@ for you: @ \ foo :: IO ByteString \ foo = 'withConnection' ('openConnection' \"www.example.com\" 80) doStuff \ doStuff :: Connection -> IO ByteString @ There are also a set of convenience APIs that do just that, along with the tedious bits like parsing URLs. For example, to do an HTTP GET and stream the response body to stdout, you can simply do: @ \ 'get' \"http:\/\/www.example.com\/file.txt\" (\\p i -> Streams.connect i stdout) @ which on the one hand is \"easy\" while on the other exposes the the 'Response' and InputStream for you to read from. Of course, messing around with URLs is all a bit inefficient, so if you already have e.g. hostname and path, or if you need more control over the request being created, then the underlying @http-streams@ API is simple enough to use directly. -} module Network.Http.Client ( -- * Connecting to server Hostname, Port, Connection, openConnection, -- * Building Requests -- | You setup a request using the RequestBuilder monad, and -- get the resultant Request object by running 'buildRequest'. The -- first call doesn't have to be to 'http', but it looks better when -- it is, don't you think? Method(..), RequestBuilder, buildRequest, http, setHostname, setAccept, setAccept', setAuthorizationBasic, ContentType, setContentType, setContentLength, setExpectContinue, setHeader, -- * Sending HTTP request Request, Response, Headers, getHostname, sendRequest, emptyBody, fileBody, inputStreamBody, encodedFormBody, -- * Processing HTTP response receiveResponse, StatusCode, getStatusCode, getStatusMessage, getHeader, debugHandler, concatHandler, concatHandler', -- * Resource cleanup closeConnection, withConnection, -- * Convenience APIs -- | Some simple functions for making requests with useful defaults. -- There's no @head@ function for the usual reason of needing to -- avoid collision with @Prelude@. -- -- These convenience functions work with @http@ and @https@, but -- note that if you retrieve an @https@ URL, you /must/ wrap your -- @main@ function with 'OpenSSL.withOpenSSL' to initialize the -- native openssl library code. -- URL, get, post, postForm, put, -- * Secure connections openConnectionSSL, baselineContextSSL, modifyContextSSL, establishConnection, -- * Testing support makeConnection ) where import Network.Http.Connection import Network.Http.Inconvenience import Network.Http.RequestBuilder import Network.Http.Types