[web-devel] Question about the composing order of conduit combination operations
Hiromi ISHII
konn.jinro at gmail.com
Thu Apr 5 14:01:08 CEST 2012
Hi,
I'm implementing a tiny SMTP server using conduit-0.4.0 and network-conduit-0.4.0.
I wrote code like below:
> smtpServer src sink = do
> LC.sourceList [ renderReply $ SMTPReply 220 (Just "localhost") ["hello"]] $$ sink
> src $$ C.sequence (sinkParser smtpCommand)
> =$ LC.map (BS.pack . show)
> =$ sink
Here is the complete (and slightly different) code: https://github.com/konn/haskell-smtp/blob/master/smtp-server/Network/SMTP/Server.hs
(You know, this server is not actually an smtp server; just echoing client's input for now.)
I ran this program and communicated using telnet.
I expected the access log like below (S means server, C means client; new-lines are CRLF) :
> S: 220 localhost hello
> C: EHLO another.example.com
> S: EHLO "another.example.com"
> C: MAIL FROM:<Postmaster at example.com>
> S: MAIL (Path [] (Mailbox {mbLocalPart = "Postmaster", mbDomain = "example.com"})) []
> C: RCPT TO:<foo at example.com>
> S: RCPT (Path [] (Mailbox {mbLocalPart = "foo", mbDomain = "example.com"})) []
> C: DATA
> C: hoge
> C: fuga
> C: oooo
> C: .
> S: DATA "hoge\r\nfuga\r\noooo"
> C: QUIT
> S: QUIT
But I got:
> S: 220 localhost hello
> C: EHLO another.example.com
> C: MAIL FROM:<Postmaster at example.com>
> C: RCPT TO:<foo at example.com>
> S: EHLO "another.example.com"
> C: DATA
> S: MAIL (Path [] (Mailbox {mbLocalPart = "Postmaster", mbDomain = "example.com"})) []
> C: hoge
> C: fuga
> C: oooo
> C: .
> C: QUIT
> S: RCPT (Path [] (Mailbox {mbLocalPart = "foo", mbDomain = "example.com"})) []
It seems that conduit produces a new SMTPCommand after reading another new command, and processes and convert it into SMTPReply much father later.
By the way, I rewrote the program above just like below and everythings seems to be good:
> smtpServer src sink = do
> LC.sourceList [ renderReply $ SMTPReply 220 (Just "localhost") ["hello"]] $$ sink
> src $= C.sequence (sinkParser smtpCommand)
> $= LC.map (BS.pack . show)
> $$ sink
If Conduits, Sinks and Sources are the same sings in conduit-0.4, why these two codes above behaves differently?
To summarize, my questions are divided into three:
1. Why the first one doesn't work as I expected?
2. Why the second one works well?
3. Is this difference intended? If so, what are the difference of semantics of ($=), (=$), ($$), (=$=) and their composition?
-- Hiromi ISHII
konn.jinro at gmail.com
More information about the web-devel
mailing list