http-streams 0.7.2.6 → 0.8.3.1
raw patch · 10 files changed
+181/−47 lines, 10 filesdep ~aesondep ~blaze-builderdep ~http-commonPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson, blaze-builder, http-common, http-streams, io-streams, network, network-uri, openssl-streams
API changes (from Hackage documentation)
+ Network.Http.Client: buildRequest1 :: RequestBuilder α -> Request
+ Network.Http.Client: openConnectionUnix :: FilePath -> IO Connection
- Network.Http.Client: buildRequest :: RequestBuilder α -> IO Request
+ Network.Http.Client: buildRequest :: Monad ν => RequestBuilder α -> ν Request
Files
- CHANGELOG.markdown +24/−0
- README.markdown +68/−0
- http-streams.cabal +20/−13
- lib/Network/Http/Client.hs +11/−9
- lib/Network/Http/Connection.hs +33/−4
- lib/Network/Http/Inconvenience.hs +15/−13
- lib/Network/Http/ResponseParser.hs +1/−1
- lib/Network/Http/Utilities.hs +1/−2
- tests/check.hs +1/−1
- tests/snippet.hs +7/−4
+ CHANGELOG.markdown view
@@ -0,0 +1,24 @@+* _v0.8.3_ + A pure version of `buildRequest` is now available as `buildRequest1`.+ Support for Unix domain socket has been added.++* _v0.7.0_ + The Request, Response, Headers, and RequestBuilder types have been+ factored out and moved to **http-common**. They are still exported+ by **http-streams**.++* _v0.6.0_ + Entity body lengths (both for Requests and Responses) now Int64.+ Library depends on **io-streams** 1.1.++* _v0.5.0_ + Definition of Hostname and Port have been changed to ByteString+ and Word16, respectively.++* _v0.4.0_ + Type signature of `buildRequest` changed, removing the Connection+ parameter. This allows you to construct Request objects before+ opening a connection to the web server if you wish.++* _v0.3.1_ + Initial public release
+ README.markdown view
@@ -0,0 +1,68 @@+An HTTP client+==============++An HTTP client library for Haskell using the Snap Framework's+[io-streams](https://github.com/snapframework/io-streams) library to+handle the streaming IO.+<!-- replace with link to hackage when it is released -->++A common case in writing RESTful web services is needing to make onward calls+to further servers. This package is intended to make this easy to do.+Though originally written for making calls from wep apps written with+Snap, you can use this from any library or framework.++Enjoy!++Example+-------++The underlying API is very simple:++```haskell+main :: IO ()+main = do+ c <- openConnection "www.example.com" 80+ + let q = buildRequest1 $ do+ http GET "/"+ setAccept "text/html"+ + sendRequest c q emptyBody+ + receiveResponse c (\p i -> do+ putStr $ show p++ x <- Streams.read i+ S.putStr $ fromMaybe "" x)+ + closeConnection c+```++There are also convenience functions for the common case of making+straight-forward GET and POST requests; for instance:++```haskell+ get "http://www.example.com/" (\_ i -> Streams.connect i stdout)+```++will _{ahem}_ stream the response body to stdout. Perhaps more+interesting (though less streams-oriented), is simply getting the+response as a ByteString using one of the pre-defined handlers:++```haskell+ x' <- get "https://secure.example.com/" concatHandler+```++See the documentation in+[Network.Http.Client](https://hackage.haskell.org/package/http-streams/docs/Network-Http-Client.html)+for further examples and details of usage of the API. There's also a [blog+post](http://blogs.operationaldynamics.com/andrew/software/haskell/http-streams-introduction)+introducing the library with a discussion of the design and usage.++Change Log+----------++Now included in separate file [CHANGELOG](CHANGELOG.markdown).++AfC+
http-streams.cabal view
@@ -1,6 +1,6 @@ cabal-version: >= 1.10 name: http-streams-version: 0.7.2.6+version: 0.8.3.1 synopsis: An HTTP client using io-streams description: /Overview/@@ -18,35 +18,42 @@ author: Andrew Cowie <andrew@operationaldynamics.com> maintainer: Andrew Cowie <andrew@operationaldynamics.com> copyright: © 2012-2015 Operational Dynamics Consulting, Pty Ltd and Others-category: Web+category: Web, IO-Streams tested-with: GHC == 7.8 stability: experimental homepage: http://research.operationaldynamics.com/projects/http-streams/ bug-reports: https://github.com/afcowie/http-streams/issues+extra-source-files: README.markdown CHANGELOG.markdown build-type: Custom +flag network-uri+ description: Get Network.URI from the network-uri package+ default: True+ library default-language: Haskell2010 build-depends: attoparsec,- http-common >= 0.7.2 && < 0.8,+ http-common >= 0.8.2, base >= 4 && <5, directory, base64-bytestring,- blaze-builder,+ blaze-builder >= 0.4, bytestring, case-insensitive,- io-streams >= 1.1 && <1.4,+ io-streams >= 1.3 && < 1.4, HsOpenSSL >= 0.10.3.5, openssl-streams >= 1.1 && < 1.4, mtl, transformers,- network >= 2.6,- network-uri >= 2.6, text, unordered-containers, aeson+ if flag(network-uri)+ build-depends: network-uri >= 2.6, network >= 2.6+ else+ build-depends: network-uri < 2.6, network < 2.6 hs-source-dirs: lib exposed-modules: Network.Http.Client@@ -75,7 +82,7 @@ default-language: Haskell2010 build-depends:- http-common >= 0.7.2 && < 0.8,+ http-common >= 0.8.2, HUnit, HsOpenSSL, MonadCatchIO-transformers,@@ -95,7 +102,7 @@ transformers, network >= 2.6, network-uri >= 2.6,- openssl-streams,+ openssl-streams >= 1.1 && < 1.4, snap-core >= 0.9 && < 1.0, snap-server >= 0.9 && < 1.0, system-fileio >= 0.3.10 && < 0.4,@@ -103,7 +110,8 @@ text, unordered-containers, aeson,- http-streams+ http-common >= 0.8.2,+ http-streams >= 0.8.2 hs-source-dirs: lib,tests main-is: check.hs@@ -125,11 +133,10 @@ default-language: Haskell2010 - build-depends:- base,+ build-depends: base, bytestring, io-streams,- http-streams+ http-streams >= 0.8.0 hs-source-dirs: tests main-is: snippet.hs
lib/Network/Http/Client.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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:@@ -42,19 +42,19 @@ -- main = do -- \ c <- 'openConnection' \"www.example.com\" 80 ----- \ q <- 'buildRequest' $ do--- 'http' GET \"\/\"--- 'setAccept' \"text/html\"+-- \ let q = 'buildRequest1' $ do+-- 'http' GET \"\/\"+-- 'setAccept' \"text/html\" ----- \ 'sendRequest' c q 'emptyBody'+-- \ 'sendRequest' c q 'emptyBody' ----- \ `receiveResponse` c (\\p i -> do+-- \ `receiveResponse` c (\\p i -> do -- xm <- Streams.read i -- case xm of -- Just x -> S.putStr x -- Nothing -> \"\") ----- \ 'closeConnection' c+-- \ 'closeConnection' c -- @ -- -- which would print the first chunk of the response back from the@@ -73,7 +73,7 @@ -- foo :: IO ByteString -- foo = 'withConnection' ('openConnection' \"www.example.com\" 80) doStuff ----- \ doStuff :: Connection -> IO ByteString+-- doStuff :: Connection -> IO ByteString -- @ -- -- There are also a set of convenience APIs that do just that, along with@@ -97,14 +97,16 @@ Port, Connection, openConnection,+ openConnectionUnix, -- * Building Requests -- | You setup a request using the RequestBuilder monad, and- -- get the resultant Request object by running 'buildRequest'. The+ -- get the resultant Request object by running 'buildRequest1'. The -- first call doesn't have to be to 'http', but it looks better when -- it is, don't you think? Method(..), RequestBuilder,+ buildRequest1, buildRequest, http, setHostname,
lib/Network/Http/Connection.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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:@@ -20,6 +20,7 @@ withConnection, openConnection, openConnectionSSL,+ openConnectionUnix, closeConnection, getHostname, getRequestHeaders,@@ -118,7 +119,7 @@ -- @Connection@ afterwards. -- -- > x <- withConnection (openConnection "s3.example.com" 80) $ (\c -> do--- > q <- buildRequest $ do+-- > let q = buildRequest1 $ do -- > http GET "/bucket42/object/149" -- > sendRequest c q emptyBody -- > ...@@ -256,6 +257,34 @@ close s --+-- | Open a connection to a Unix domain socket.+--+-- > main :: IO ()+-- > main = do+-- > c <- openConnectionUnix "/var/run/docker.sock"+-- > ...+-- > closeConnection c+--+openConnectionUnix :: FilePath -> IO Connection+openConnectionUnix path = do+ let a = SockAddrUnix path+ s <- socket AF_UNIX Stream defaultProtocol++ connect s a+ (i,o1) <- Streams.socketToStreams s++ o2 <- Streams.builderStream o1++ return Connection {+ cHost = path',+ cClose = close s,+ cOut = o2,+ cIn = i+ }+ where+ path' = S.pack path++-- -- | Having composed a 'Request' object with the headers and metadata for -- this connection, you can now send the request to the server, along -- with the entity body, if there is one. For the rather common case of@@ -519,8 +548,8 @@ -- -- > c <- openConnection "kernel.operationaldynamics.com" 58080 -- >--- > q <- buildRequest $ do--- > http GET "/time"+-- > let q = buildRequest1 $ do+-- > http GET "/time" -- > -- > sendRequest c q emptyBody -- >
lib/Network/Http/Inconvenience.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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:@@ -158,8 +158,8 @@ writeIORef global ctx' ----- | Given a URL, work out whether it is normal or secure, and then--- open the connection to the webserver including setting the+-- | Given a URL, work out whether it is normal, secure, or unix domain,+-- and then open the connection to the webserver including setting the -- appropriate default port if one was not specified in the URL. This -- is what powers the convenience API, but you may find it useful in -- composing your own similar functions.@@ -171,8 +171,8 @@ -- > let url = "https://www.example.com/photo.jpg" -- > -- > c <- establishConnection url--- > q <- buildRequest $ do--- > http GET url+-- > let q = buildRequest1 $ do+-- > http GET url -- > ... -- establishConnection :: URL -> IO (Connection)@@ -190,6 +190,8 @@ "https:" -> withOpenSSL $ do ctx <- readIORef global openConnectionSSL ctx host ports+ "unix:" -> do+ openConnectionUnix $ uriPath u _ -> error ("Unknown URI scheme " ++ scheme) where scheme = uriScheme u@@ -312,11 +314,11 @@ u = parseURL r' - process c = do- q <- buildRequest $ do+ q = buildRequest1 $ do http GET (path u) setAccept "*/*" + process c = do sendRequest c q emptyBody receiveResponse c (wrapRedirect u n handler)@@ -401,12 +403,12 @@ u = parseURL r' - process c = do- q <- buildRequest $ do+ q = buildRequest1 $ do http POST (path u) setAccept "*/*" setContentType t + process c = do _ <- sendRequest c q body x <- receiveResponse c handler@@ -438,12 +440,12 @@ u = parseURL r' - process c = do- q <- buildRequest $ do+ q = buildRequest1 $ do http POST (path u) setAccept "*/*" setContentType "application/x-www-form-urlencoded" + process c = do _ <- sendRequest c q (encodedFormBody nvs) x <- receiveResponse c handler@@ -508,12 +510,12 @@ u = parseURL r' - process c = do- q <- buildRequest $ do+ q = buildRequest1 $ do http PUT (path u) setAccept "*/*" setHeader "Content-Type" t + process c = do _ <- sendRequest c q body x <- receiveResponse c handler
lib/Network/Http/ResponseParser.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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:
lib/Network/Http/Utilities.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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:@@ -24,7 +24,6 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE Trustworthy #-} {-# LANGUAGE UnboxedTuples #-} module Network.Http.Utilities (
tests/check.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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
tests/snippet.hs view
@@ -1,7 +1,7 @@ -- -- HTTP client for use with io-streams ----- Copyright © 2012-2013 Operational Dynamics Consulting, Pty Ltd+-- Copyright © 2012-2014 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@@ -13,6 +13,7 @@ module Main where +import GHC.Conc import Network.Http.Client --@@ -27,11 +28,13 @@ main :: IO () main = do+ let n = numCapabilities+ putStrLn (show n) c <- openConnection "kernel.operationaldynamics.com" 58080 - q <- buildRequest $ do- http GET "/time"- setAccept "text/plain"+ let q = buildRequest1 $ do+ http GET "/time"+ setAccept "text/plain" putStr $ show q -- Requests [headers] are terminated by a double newline -- already. We need a better way of emitting debug