[Haskell-cafe] Network.Browser and Network.TLS

Myles C. Maxfield myles.maxfield at gmail.com
Mon Jan 16 21:28:23 CET 2012


I am interested in extending the Network.HTTP code in the HTTP package to
support HTTPS via TLS. A clear candidate is to use the Network.TLS module
in the TLS library (because its TLS logic is written in pure Haskell,
rather than any of the FFI libraries like Network.Curl or the OpenSSL
package). It's simple enough to provide an implementation of the
Network.Stream.Stream typeclass around a TLSCtx, and this works for the
Network.HTTP.Stream functions.

However, I am interested in using the functionality in the Network.Browser
module. This module uses the Network.HTTP.HandleStream interface, which is
implemented directly on top of the Handle datatype and the
Network.BufferType.BufferOp functions. HandleStreams seem to be for
allowing the user to pull out an arbitrary data type out of an HTTP stream,
not for doing any stream processing the way TLS does. As far as I can tell,
the current typeclass system does not allow a TLSCtx to piggypack off of a
HandleStream. My assumption is that this interface is used for speed so the
user doesn't have to convert some canonical type into the type that he/she
desires in client code.

TLS, however, must use a specific type to decode the bytes that it pulls
out of the stream. I don't think it's reasonable to try to modify the TLS
library to decode bytes from an arbitrary type. Decoding necessarily needs
byte-level access to its input (and therefore output) streams in a manner
extremely similar to the functions that ByteString provides. Perhaps I'm
wrong about this, but the conclusion I've reached is that it doesn't make
sense for TLS to use an arbitrary typeclass because the interface it
requires is so similar to the existing ByteString datatype. If an
application wants a specific type out of a TLS stream, it must necessarily
convert the type in software. Any speed that might be gained by pulling
your native type out of a network connection will be dwarfed anyway by the
cost of decryption.

The Network.Stream functions allow this by using String type for all data
transfers (which is counterintuitive for binary data transfers). An
implementation of Network.Stream.Stream using TLS would convert TLS's
output ByteString into a String (possibly by doing something like ((map
(toEnum . fromIntegral)) . unpack) which doesn't make a whole lot of sense
and is fairly wasteful). A client program might even convert it back to a
ByteString, so the client program must have knowledge about how the bytes
are packed into the String.

Network.Browser only seems to have one function which isn't simply a state
accessor/mutator: 'request'. This function gives the connection a type of
HStream ty => HandleStream ty. As stated before, the HandleStream directly
uses the Handle type. This means that, as far as I can tell, there is no
way to fit TLS into the Network.Browser module as it stands because the
types don't allow for it. Supporting TLS in Network.Browser would have to
change the type of 'request' and therefore break every program out there
which uses the Network.Browser module. It would be possible to create
something like a 'requestHTTPS' function which returns a different type,
but this is quite inelegant - there should be one function that inspects
the scheme of the URI it is handed.

I am left with the conclusion that it is impossible to support TLS in
Network.Browser without breaking many Haskell programs. It is obviously
possible to fork the HTTP library, but I'd like to improve the state of the
existing libraries. Likewise, it is possible to create a new module that
supports HTTPS but has different typed functions and lots of code
duplication with Network.Browser, but that is quite inelegant.

I suppose this is mostly directed at the maintainers of the HTTP and TLS
libraries, Sigbjorn Finne and Vincent Hanquez, but I'd be greatful for your
input on what I can do to contribute to the Haskell community regarding
Network.Browser and Network.TLS. Perhaps I should just use the
Network.HTTP.Enumerator module and not deal with Network.Browser? Maybe I'm
going about this in entirely the wrong way.

Myles C. Maxfield
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120116/9fdaf9c0/attachment.htm>

More information about the Haskell-Cafe mailing list