
Hello all, I have been working on a WebSocket [1] library lately, which you can find here [2]. It's getting to the point at which I want to release it on Hackage. However, there is one thing remaining before the library will be really useful for applications: integration. I would like to provide integration with Happstack, Snap and Yesod -- this is why I have built the library around the enumerator package [3]. It would be awesome if frameworks could more or less agree on a way in which an HTTP connection can be "transformed" to a WebSocket. That way, I will be able to provide packages such as `websockets-warp`, `websockets-snap` etc. Currently, the "entry point" of the websockets library is the following function: runWebSockets :: WebSockets a -> Enumerator ByteString IO a -> Iteratee ByteString IO () -> Iteratee ByteString IO a Where the first argument is the user-supplied code in the `WebSockets` monad (needs to keep a bit of state etc.), the second argument is an enumerator which the library can use to read from the socket, and the last argument is an iteratee with which the library can write to the socket. A web server then needs to provide some way to get this enumerator/iteratee pair, and hand it over to the library (currently, this is lacking). Some more details apply, e.g. the web server shouldn't kill the websocket handler as fast as regular HTTP connections. Is this proposal somewhat agreeable? I'm open to any feedback. [1]: http://en.wikipedia.org/wiki/WebSocket [2]: http://github.com/jaspervdj/websockets [3]: http://hackage.haskell.org/package/enumerator Cheers, Jasper

On Sun, Sep 25, 2011 at 5:46 PM, Jasper Van der Jeugt
Hello all,
I have been working on a WebSocket [1] library lately, which you can find here [2]. It's getting to the point at which I want to release it on Hackage. However, there is one thing remaining before the library will be really useful for applications: integration.
I would like to provide integration with Happstack, Snap and Yesod -- this is why I have built the library around the enumerator package [3]. It would be awesome if frameworks could more or less agree on a way in which an HTTP connection can be "transformed" to a WebSocket.
That way, I will be able to provide packages such as `websockets-warp`, `websockets-snap` etc.
Currently, the "entry point" of the websockets library is the following function:
runWebSockets :: WebSockets a -> Enumerator ByteString IO a -> Iteratee ByteString IO () -> Iteratee ByteString IO a
Where the first argument is the user-supplied code in the `WebSockets` monad (needs to keep a bit of state etc.), the second argument is an enumerator which the library can use to read from the socket, and the last argument is an iteratee with which the library can write to the socket.
A web server then needs to provide some way to get this enumerator/iteratee pair, and hand it over to the library (currently, this is lacking). Some more details apply, e.g. the web server shouldn't kill the websocket handler as fast as regular HTTP connections.
Is this proposal somewhat agreeable? I'm open to any feedback.
[1]: http://en.wikipedia.org/wiki/WebSocket [2]: http://github.com/jaspervdj/websockets [3]: http://hackage.haskell.org/package/enumerator
Cheers, Jasper
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
I really like this approach. We had a discussion in #yesod not too long ago that essentially came to the same idea of having a plugin to add WebSocket support at the server level. I like even more that this would work for multiple servers. I think my main question is: why take an enumerator? Should the function just run as an iteratee? I know that will make it much more amenable to integration with Warp. All of Warp's internal processing lives inside an Iteratee, so we can't really extract an Enumerator from there. This is already how Warp handles the request body (the application lives in an Iteratee), so I think the approach is sound. I'll be happy to play around with Warp integration. Michael

Hi Michael,
I think my main question is: why take an enumerator? Should the function just run as an iteratee? I know that will make it much more amenable to integration with Warp. All of Warp's internal processing lives inside an Iteratee, so we can't really extract an Enumerator from there. This is already how Warp handles the request body (the application lives in an Iteratee), so I think the approach is sound.
You're right. I had this enumerator argument because initially it tied in better with my "demo" socket server. I've removed it, the type signature is now: runWebSockets :: WebSockets a -> Iteratee ByteString IO () -> Iteratee ByteString IO a This should work out better for Warp integration, if I understood you correctly. Cheers, Jasper

On Mon, Sep 26, 2011 at 12:15 AM, Jasper Van der Jeugt
Hi Michael,
I think my main question is: why take an enumerator? Should the function just run as an iteratee? I know that will make it much more amenable to integration with Warp. All of Warp's internal processing lives inside an Iteratee, so we can't really extract an Enumerator from there. This is already how Warp handles the request body (the application lives in an Iteratee), so I think the approach is sound.
You're right. I had this enumerator argument because initially it tied in better with my "demo" socket server. I've removed it, the type signature is now:
runWebSockets :: WebSockets a -> Iteratee ByteString IO () -> Iteratee ByteString IO a
This should work out better for Warp integration, if I understood you correctly.
This still don't work with wai at the present, because there's no way to create the outer iteratee which is used to send data back to client directly. I propose to expose such an iteratee through wai Request type.
Cheers, Jasper
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel

Hi yi,
WAI is and will always be designed for HTTP. Websockets is a different
protocol (even though it is normally initiated over HTTP). If there is a way
that makes sense to put it websockets into WAI, it can definitely be
considered. But I believe the current plan is to put Websocket support into
Warp. Haskell code re-use will be achieved through this Websockets library.
Does that seem reasonable to you?
Greg Weber
On Sun, Sep 25, 2011 at 6:11 PM, yi huang
On Mon, Sep 26, 2011 at 12:15 AM, Jasper Van der Jeugt
wrote: Hi Michael,
I think my main question is: why take an enumerator? Should the function just run as an iteratee? I know that will make it much more amenable to integration with Warp. All of Warp's internal processing lives inside an Iteratee, so we can't really extract an Enumerator from there. This is already how Warp handles the request body (the application lives in an Iteratee), so I think the approach is sound.
You're right. I had this enumerator argument because initially it tied in better with my "demo" socket server. I've removed it, the type signature is now:
runWebSockets :: WebSockets a -> Iteratee ByteString IO () -> Iteratee ByteString IO a
This should work out better for Warp integration, if I understood you correctly.
This still don't work with wai at the present, because there's no way to create the outer iteratee which is used to send data back to client directly. I propose to expose such an iteratee through wai Request type.
Cheers, Jasper
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
-- http://www.yi-programmer.com/blog/
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel

On Mon, Sep 26, 2011 at 3:36 AM, Greg Weber
Hi yi, WAI is and will always be designed for HTTP. Websockets is a different protocol (even though it is normally initiated over HTTP). If there is a way that makes sense to put it websockets into WAI, it can definitely be considered. But I believe the current plan is to put Websocket support into Warp. Haskell code re-use will be achieved through this Websockets library. Does that seem reasonable to you?
Snap was planning on handling this by giving you an "ejector seat"
mechanism in which control completely leaves the HTTP stack and you
get a (readEnd, writeEnd) enumerator/iteratee pair to do whatever you
want with.
G
--
Gregory Collins

I'm trying to take a look at it, but the README file on github points to a websockets package that doesn't look anything like this, and is not based on enumerator at all. I don't suppose there's API documentation anywhere? -- Chris

Hi Chris,
The package you see on Hackage is the one I started out from (the
author agreed to have me take over as maintainer) but I've rewritten
it from scratch. For your convenience, I've generated and dumped the
haddocks here [1].
[1]: http://jaspervdj.be/tmp/websockets/
Cheers,
Jasper
On Sun, Sep 25, 2011 at 6:21 PM, Chris Smith
I'm trying to take a look at it, but the README file on github points to a websockets package that doesn't look anything like this, and is not based on enumerator at all. I don't suppose there's API documentation anywhere?
-- Chris

Ah, nice! Thank you. So I'm trying to work out what the minimum "normal" API would be for using this (via Snap or WAI, for example). What I'm coming up with is that first of all, the following would be used in the integration layer: data Request data Response handshake runWebSockets The interface to the application programmer is less clear. Is the expectation that you'd use the WebSocketData type class? But then the abstraction looks a bit weak since you have to think in terms of text or data frames anyway... so ignoring that, the following looks closest to what I'd want: data WebSockets a data DataMessage sendDataMessage receiveDataMessage and a new export: getDataMessageSender :: WebSockets (DataMessage -> IO ()) getDataMessageSender = fmap ($ dataMessage) getSender to use with a forkIO. Is this something like what you'd expect people to do? -- Chris

Hi Chris,
The interface to the application programmer is less clear. Is the expectation that you'd use the WebSocketData type class?
I want the library to be flexible for both high- and low-level scenarios. Basically, there are three ways to use the library: * For a really low-level server (e.g. you want to send control frames such as pings yourself), you can use the `sendFrame`, `receiveFrame`, `sendMessage` and `receiveMessage` methods. * For a typical application, you would indeed use `sendDataMessage` and `receiveDataMessage`, as you said. * In some cases, the user doesn't care about the internal representation of frames (binary or text), and he just wants to send and receive messages in some format. For this scenario, there is the `WebSocketsData` typeclass, and the `receiveData` method. I hope this clears things up a little (I'll add an explanation like this to the docs), Cheers, Jasper

epic! Happstack will be migrating to warp/wai really soon now. So, that should make happstack support trivial[1]. - jeremy [1] One of the many reasons for migrating Happstack to warp is to get things like this for 'free'. On Sep 25, 2011, at 9:46 AM, Jasper Van der Jeugt wrote:
Hello all,
I have been working on a WebSocket [1] library lately, which you can find here [2]. It's getting to the point at which I want to release it on Hackage. However, there is one thing remaining before the library will be really useful for applications: integration.
I would like to provide integration with Happstack, Snap and Yesod -- this is why I have built the library around the enumerator package [3]. It would be awesome if frameworks could more or less agree on a way in which an HTTP connection can be "transformed" to a WebSocket.
That way, I will be able to provide packages such as `websockets- warp`, `websockets-snap` etc.
Currently, the "entry point" of the websockets library is the following function:
runWebSockets :: WebSockets a -> Enumerator ByteString IO a -> Iteratee ByteString IO () -> Iteratee ByteString IO a
Where the first argument is the user-supplied code in the `WebSockets` monad (needs to keep a bit of state etc.), the second argument is an enumerator which the library can use to read from the socket, and the last argument is an iteratee with which the library can write to the socket.
A web server then needs to provide some way to get this enumerator/ iteratee pair, and hand it over to the library (currently, this is lacking). Some more details apply, e.g. the web server shouldn't kill the websocket handler as fast as regular HTTP connections.
Is this proposal somewhat agreeable? I'm open to any feedback.
[1]: http://en.wikipedia.org/wiki/WebSocket [2]: http://github.com/jaspervdj/websockets [3]: http://hackage.haskell.org/package/enumerator
Cheers, Jasper
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel

Michael just implemented websockets with a simple demo that you can run. He
posted a basic explanation here, and we have instructions to run the demo:
http://www.reddit.com/r/haskell/comments/l2421/websockets_support_for_waiwar...
On Tue, Sep 27, 2011 at 10:34 AM, Jeremy Shaw
epic!
Happstack will be migrating to warp/wai really soon now. So, that should make happstack support trivial[1].
- jeremy
[1] One of the many reasons for migrating Happstack to warp is to get things like this for 'free'.
On Sep 25, 2011, at 9:46 AM, Jasper Van der Jeugt wrote:
Hello all,
I have been working on a WebSocket [1] library lately, which you can find here [2]. It's getting to the point at which I want to release it on Hackage. However, there is one thing remaining before the library will be really useful for applications: integration.
I would like to provide integration with Happstack, Snap and Yesod -- this is why I have built the library around the enumerator package [3]. It would be awesome if frameworks could more or less agree on a way in which an HTTP connection can be "transformed" to a WebSocket.
That way, I will be able to provide packages such as `websockets-warp`, `websockets-snap` etc.
Currently, the "entry point" of the websockets library is the following function:
runWebSockets :: WebSockets a -> Enumerator ByteString IO a -> Iteratee ByteString IO () -> Iteratee ByteString IO a
Where the first argument is the user-supplied code in the `WebSockets` monad (needs to keep a bit of state etc.), the second argument is an enumerator which the library can use to read from the socket, and the last argument is an iteratee with which the library can write to the socket.
A web server then needs to provide some way to get this enumerator/iteratee pair, and hand it over to the library (currently, this is lacking). Some more details apply, e.g. the web server shouldn't kill the websocket handler as fast as regular HTTP connections.
Is this proposal somewhat agreeable? I'm open to any feedback.
[1]: http://en.wikipedia.org/wiki/**WebSockethttp://en.wikipedia.org/wiki/WebSocket [2]: http://github.com/jaspervdj/**websocketshttp://github.com/jaspervdj/websockets [3]: http://hackage.haskell.org/**package/enumeratorhttp://hackage.haskell.org/package/enumerator
Cheers, Jasper
______________________________**_________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/**mailman/listinfo/web-develhttp://www.haskell.org/mailman/listinfo/web-devel
______________________________**_________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/**mailman/listinfo/web-develhttp://www.haskell.org/mailman/listinfo/web-devel
participants (7)
-
Chris Smith
-
Greg Weber
-
Gregory Collins
-
Jasper Van der Jeugt
-
Jeremy Shaw
-
Michael Snoyman
-
yi huang