[Haskell-cafe] Contributing to http-conduit
Myles C. Maxfield
myles.maxfield at gmail.com
Tue Jan 24 07:37:53 CET 2012
I have attached a patch to add a redirect chain to the Response datatype.
Comments on this patch are very welcome.
I was originally going to include the entire Request object in the
redirection chain, but Request objects are parameterized with a type 'm',
so including a 'Request m' field would force the Response type to be
parameterized as well. I felt that would be too large a change, so I made
the type of the redirection chain W.Ascii.
Perhaps its worth using the 'forall' keyword to get rid of the pesky 'm'
type parameter for Requests?
data RequestBody
= RequestBodyLBS L.ByteString
| RequestBodyBS S.ByteString
| RequestBodyBuilder Int64 Blaze.Builder
| forall m. RequestBodySource Int64 (C.Source m Blaze.Builder)
| forall m. RequestBodySourceChunked (C.Source m Blaze.Builder)
--Myles
On Mon, Jan 23, 2012 at 3:31 AM, Michael Snoyman <michael at snoyman.com>wrote:
> On Mon, Jan 23, 2012 at 1:20 PM, Aristid Breitkreuz
> <aristidb at googlemail.com> wrote:
> > Rejecting cookies is not without precedent.
> >
> > If you must force cookie handling upon us, at least make it possible to
> > selectively reject them.
> >
> > Aristid
>
> If you turn off automatic redirects, then you won't have cookie
> handling. I'd be interested to hear of a use case where you would want
> to avoid passing cookies after a redirect.
>
> Michael
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120123/030d417e/attachment.htm>
-------------- next part --------------
From d60bc1adf4af5a038432c35cde222654dfabf6dd Mon Sep 17 00:00:00 2001
From: "Myles C. Maxfield" <litherum at gmail.com>
Date: Mon, 23 Jan 2012 21:44:12 -0800
Subject: [PATCH] Adding a redirection chain field to Responses
---
Network/HTTP/Conduit.hs | 7 ++++---
Network/HTTP/Conduit/Request.hs | 24 +++++++++++++++++++++++-
Network/HTTP/Conduit/Response.hs | 7 ++++---
3 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/Network/HTTP/Conduit.hs b/Network/HTTP/Conduit.hs
index 794a62a..879d5a8 100644
--- a/Network/HTTP/Conduit.hs
+++ b/Network/HTTP/Conduit.hs
@@ -147,7 +147,7 @@ http
-> Manager
-> ResourceT m (Response (C.Source m S.ByteString))
http req0 manager = do
- res@(Response status hs body) <-
+ res@(Response _ status hs body) <-
if redirectCount req0 == 0
then httpRaw req0 manager
else go (redirectCount req0) req0
@@ -160,7 +160,7 @@ http req0 manager = do
where
go 0 _ = liftBase $ throwIO TooManyRedirects
go count req = do
- res@(Response (W.Status code _) hs _) <- httpRaw req manager
+ res@(Response uri (W.Status code _) hs _) <- httpRaw req manager
case (300 <= code && code < 400, lookup "location" hs) of
(True, Just l'') -> do
-- Prepend scheme, host and port if missing
@@ -192,7 +192,8 @@ http req0 manager = do
then "GET"
else method l
}
- go (count - 1) req'
+ response <- go (count - 1) req'
+ return $ response {requestChain = (head uri) : (requestChain response)}
_ -> return res
-- | Get a 'Response' without any redirect following.
diff --git a/Network/HTTP/Conduit/Request.hs b/Network/HTTP/Conduit/Request.hs
index e6e8876..a777285 100644
--- a/Network/HTTP/Conduit/Request.hs
+++ b/Network/HTTP/Conduit/Request.hs
@@ -7,6 +7,7 @@ module Network.HTTP.Conduit.Request
, ContentType
, Proxy (..)
, parseUrl
+ , unParseUrl
, browserDecompress
, HttpException (..)
, alwaysDecompress
@@ -39,7 +40,7 @@ import qualified Network.HTTP.Types as W
import Control.Exception (Exception, SomeException, toException)
import Control.Failure (Failure (failure))
-import Codec.Binary.UTF8.String (encodeString)
+import Codec.Binary.UTF8.String (encode, encodeString)
import qualified Data.CaseInsensitive as CI
import qualified Data.ByteString.Base64 as B64
@@ -207,6 +208,27 @@ parseUrl2 full sec s = do
(readDec rest)
x -> error $ "parseUrl1: this should never happen: " ++ show x
+unParseUrl :: Request m -> W.Ascii
+unParseUrl Request { secure = secure'
+ , host = host'
+ , port = port'
+ , path = path'
+ , queryString = querystring'
+ } = S.concat
+ [ "http"
+ , if secure' then "s" else S.empty
+ , "://"
+ , host'
+ , case (secure', port') of
+ (True, 443) -> S.empty
+ (True, p) -> S.pack $ encode $ ":" ++ show p
+ (False, 80) -> S.empty
+ (False, p) -> S.pack $ encode $ ":" ++ show p
+ , path'
+ , "?"
+ , querystring'
+ ]
+
data HttpException = StatusCodeException W.Status W.ResponseHeaders
| InvalidUrlException String String
| TooManyRedirects
diff --git a/Network/HTTP/Conduit/Response.hs b/Network/HTTP/Conduit/Response.hs
index 5c6fd23..c183e34 100644
--- a/Network/HTTP/Conduit/Response.hs
+++ b/Network/HTTP/Conduit/Response.hs
@@ -33,7 +33,8 @@ import Network.HTTP.Conduit.Chunk
-- | A simple representation of the HTTP response created by 'lbsConsumer'.
data Response body = Response
- { statusCode :: W.Status
+ { requestChain :: [W.Ascii]
+ , statusCode :: W.Status
, responseHeaders :: W.ResponseHeaders
, responseBody :: body
}
@@ -41,7 +42,7 @@ data Response body = Response
-- | Since 1.1.2.
instance Functor Response where
- fmap f (Response status headers body) = Response status headers (f body)
+ fmap f res@(Response {responseBody = body}) = res {responseBody = (f body)}
-- | Convert a 'Response' that has a 'C.Source' body to one with a lazy
-- 'L.ByteString' body.
@@ -90,7 +91,7 @@ getResponse connRelease req@(Request {..}) bsrc = do
else bsrc'
return $ addCleanup cleanup bsrc''
- return $ Response s hs' body
+ return $ Response [unParseUrl req] s hs' body
-- | Add some cleanup code to the given 'C.Source'. General purpose
-- function, could be included in conduit itself.
--
1.7.7.4
More information about the Haskell-Cafe
mailing list