Alright, that's fine. I just wanted to be explicit about the interface we'd be providing. Taking the Request construction code out of 'http' and putting it into its own function should be a quick change - I'll have it to you soon. One possible wrench - The existing code copies some fields (like the proxy) from the original request. In order to keep this functionality, the signature would have to be:

checkRedirect :: Request m -> Response -> Maybe (Request m)

Is that okay with you? I think I'd also like to call the function something different, perhaps 'getRedirectedRequest'. Is that okay? I'll also add an example to the documentation about how a caller would get the redirection chain by re-implementing redirection (by using the example in your previous email).

As for cookie handling - I think Network.Browser has a pretty elegant solution to this. They allow a "CookieFilter" which has type of URI -> Cookie -> IO Bool. Cookies are only put in the cookie jar if the function returns True. There is a default CookieFilter, which behaves as we would expect, but the user can override this function. That way, if you don't want to support cookies, you can just pass in (\ _ _ -> return False).

If we're already expecting people that want specific functionality to re-implement the redirect-following code, this solution might be unnecessary. Do you think that such a concept would be beneficial for Network.HTTP.Conduit to implement?

Either way, I'll probably end up making a solution similar to your checkRedirect function that will just allow people to take SetCookies out of a Response and put Cookies into a Request. I'll probably also provide a default function which converts a SetCookie into a cookie by looking up the current time, inspecting the Request, etc. This will allow me to not have to change the type of Request or Response - the functions I'll be writing can deal with the raw Headers that are already in Requests and Responses. Modifying 'http' to use these functions will be straightforward.

How does this sound to you?

Thanks,
Myles C. Maxfield

On Wed, Jan 25, 2012 at 5:10 AM, Aristid Breitkreuz <aristidb@googlemail.com> wrote:

The nice thing is that this way, nobody can force me to handle cookies.  ;-)

Might be that usage patterns emerge, which we can then codify into functions later.

Am 25.01.2012 08:09 schrieb "Michael Snoyman" <michael@snoyman.com>:
On Wed, Jan 25, 2012 at 9:01 AM, Myles C. Maxfield
<myles.maxfield@gmail.com> wrote:
> Sorry, I think I'm still a little confused about this.
>
> From the point of view of a library user, if I use the 'http' function, but
> want to know what final URL I ended up at, I would have to set redirects to
> 0, call http, call checkRedirect, and recurse until checkRedirect returns
> Nothing (or a count runs out). I would be handling the recursion of
> redirects myself.
>
> On one hand, this solution is lightweight and easy to implement in the
> library. On the other hand, the caller has to run each individual request
> themselves, keeping track of the number of requests (so there isn't an
> infinite loop). The loop is already implemented in the http function - I
> think it's reasonable to modify the existing loop rather than expect the
> caller to re-implement that logic.
>
> However, it's probably just as reasonable to say "if you want to know what
> URL you end up at, you have to re-implement your own redirection-following
> logic."
>
> I do agree, however, that including an (possibly long, though explicitly
> bounded) [Ascii] along with every request is arbitrary, and probably not the
> best solution. Can you think of a solution which allows the caller to know
> the url chain (or possibly just the last URL - that's the important one)
> without having to re-implement the redirection-following logic themselves?
>
> It sounds like if you had to choose, you would rather force a caller to
> re-implement redirection-following rather than include a URL chain in every
> Response. Is this correct?

That's correct. I think knowing the final URL is a fairly arbitrary
requirement, in the same boat as wanting redirect handling without
supporting cookies. These to me fall well within the 20%: most people
won't need them, so the API should not be optimized for them.

There's also the fact that [Ascii] isn't nearly enough information to
properly follow the chain. Next someone's going to want to know if a
request was GET or POST, or whether it was a permanent or temporary
redirect, or the exact text of the location header, or a million other
things involved. If someone wants this stuff, they should reimplement
the redirect logic.

But I don't really see this as being such a burden. If we had the
checkRedirect function, it would look something like:

myHttp req = do
   let req' = req { redirectCount = 0 }
   res <- http req'
   case checkRedirect res of
       Just req2 -> myHttp req2
       Nothing -> return res

I don't think that's a terrible burden.

Michael

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe