So if I understand correctly, you only need a way to:

A) Parse requests from a raw byte stream (i.e. your `Producer`)
B) Create responses
C) Serialize responses to a byte stream

`pipes-attoparsec` is the most idiomatic way to do (A). You can get the necessary parsers from `hweblib`, which provides RFC2616-compliant parsers.

For (B), you can also use the `hweblib` library, which provides a `Response` type you can build.

For (C), I'm not as sure. Ask Aycan (the maintainer of `hweblib`) if there is a way to serialize `Response`s to `ByteString`s.

The main issue in general is that most web server libraries don't have a separate library just for parsing requests and serializing responses. `hweblib` is the closest library I've found for this purpose.

On 06/29/2014 05:00 PM, Nicolas Trangez wrote:
Gabriel,

On Sun, 2014-06-29 at 12:37 -0700, Gabriel Gonzalez wrote:
This is a simple "echo" server written using `pipes-wai`:

      {-# LANGUAGE OverloadedStrings #-}

      import Blaze.ByteString.Builder (fromByteString)
      import Pipes
      import qualified Pipes.Prelude as Pipes
      import Pipes.Wai
      import Network.Wai.Handler.Warp
      import Network.HTTP.Types (Status(..))

      main = run 8000 $ \request onResponse -> do
          let p = do
                  producerRequestBody request >-> Pipes.map (Chunk .
fromByteString)
                  yield Flush

          onResponse (responseProducer (Status 200 "") [] p)

`producerRequestBody` turns the incoming client's request into a
`Producer`.  Then you can do whatever you want with that `Producer`,
like read in its contents, discard it, or (in the above example) stream
it directly to the response.

If you give a more specific example of what you want to do, I can give a
more specific example.
Thanks for taking time looking into this. It looks like I might have
been somewhat unclear before.

Whilst your example above indeed turns a client request into a Producer
and turns a Producer into a response, this is all at another layer than
what I'm trying to accomplish.

Here's the difference: in your example, the 'run' function (as provided
by Warp) takes care of setting up a listening socket, accepting client
connections, forking threads,...

Whilst in my application, all this functionality is provided already,
all I'm left with are a ByteString Producer and ByteString Consumer
representing a client socket connection. Now a Request should be
read/parsed from the Producer, handled, and then a Response should be
yield'ed to the Consumer. All of this for this single client connection,
no need to accept connections, spawn threads,...

This could boil down to, e.g.

runHTTPInteraction :: Monad m => Pipe ByteString ByteString m r
runHTTPInteraction = do
    req <- readRequest
    let resp = ...
    renderResponse resp

Then, when my client handler function is called with a `Producer
ByteString m r` and `Consumer ByteString m r`, I can use the above using
something like

-- Interact with a single client. This runs in its own thread etc.
myHandler :: Monad m => Producer ByteString IO () -> Consumer ByteString
IO () -> ()
myHandler prod cons =
     runEffect $
     {- for HTTP pipelining / connection re-use... -} forever $
     prod >-> runHTTPInteractoin >-> cons

(or something along those lines, this is no real code so might not even
type-check).

Thanks,

Nicolas


On 06/28/2014 02:20 PM, Nicolas Trangez wrote:
On Sat, 2014-06-28 at 14:12 -0700, Gabriel Gonzalez wrote:
Have you tried the `pipes-wai` library?
I passed by it during my search, but its operations seem client-centric:
turning a `Request` into a `Producer ByteString m ()` (in order to
stream the data from that producer to some server?), or create a
`Response` out of a `Producer (Flush Builder) IO ()` (in order to stream
data from the producer to a client on some server?).

I could be missing something very obvious, but I don't think that's what
I need.

Thanks,

Nicolas

On Jun 28, 2014 1:52 PM, "Nicolas Trangez" <[email protected]> wrote:

All,

Has anyone ever written anything HTTP-server-like using Pipes? I looked
into Warp to check whether it could be integrated, but Warp seems to do
connection management, thread management, timeout handling, whatnot,
which is not what I need.

I'm looking for something simpler: given a `Producer ByteString m r` and
a `Consumer ByteString m r`, read a `Request` from the producer, then do
some handling, and render a `Response` to the consumer.

Are there any libraries I could look into, or is Warp easy to integrate
yet I'm failing to see how?

Thanks,

Nicolas

--
You received this message because you are subscribed to the Google Groups
"Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to [email protected].
To post to this group, send email to [email protected].



--
You received this message because you are subscribed to the Google Groups "Haskell 
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].

Reply via email to