diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for http-pony
+
+## 0.1.0.0  -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2016, Jinjing Wang
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Jinjing Wang nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/http-pony.cabal b/http-pony.cabal
new file mode 100644
--- /dev/null
+++ b/http-pony.cabal
@@ -0,0 +1,39 @@
+-- Initial http-pony.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                http-pony
+version:             0.1.0.0
+synopsis:            A type unsafe http library
+-- description:         
+license:             BSD3
+license-file:        LICENSE
+author:              Jinjing Wang
+maintainer:          nfjinjing@gmail.com
+-- copyright:           
+category:            Network
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Network.HTTP.Pony.Type
+                     , Network.HTTP.Pony.Builder
+                     , Network.HTTP.Pony.Serve
+                     , Network.HTTP.Pony.Parser
+                     , Network.HTTP.Pony.Helper
+  -- other-modules:       
+  -- other-extensions:    OverloadedStrings
+  build-depends:       base >=4.9 && <4.10
+                     , bytestring >=0.10 && <0.11
+                     , case-insensitive >=1.2
+                     , network >=2.6
+                     , pipes >=4.1
+                     , pipes-attoparsec >=0.5
+                     , pipes-network >=0.6
+                     , pipes-parse >=3.0
+                     , pipes-safe >=2.2
+                     , transformers >=0.5
+                     , attoparsec >=0.13
+
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Network/HTTP/Pony/Builder.hs b/src/Network/HTTP/Pony/Builder.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/HTTP/Pony/Builder.hs
@@ -0,0 +1,36 @@
+-- | Builder
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Network.HTTP.Pony.Builder where
+
+import           Data.ByteString (ByteString)
+import qualified Data.CaseInsensitive as CI
+import           Pipes as Pipes
+import qualified Pipes.Attoparsec as AttoParser
+import           Pipes.Network.TCP.Safe
+import qualified Pipes.Parse as Parser
+import           Pipes.Prelude (tee)
+import qualified Pipes.Prelude as Pipes
+
+import           Network.HTTP.Pony.Helper ((-))
+import           Network.HTTP.Pony.Type
+import           Prelude hiding ((-), log)
+
+header :: Monad m => Header -> Producer ByteString m ()
+header (key, value) = do
+  yield - CI.original key
+  yield ": "
+  yield value
+  yield "\n"
+
+
+message :: Monad m => Request ByteString m r -> Producer ByteString m r
+message (startLine, headers, body) = do
+  yield startLine
+  yield "\n"
+
+  Pipes.each ~> header - headers
+
+  yield "\n"
+  body
diff --git a/src/Network/HTTP/Pony/Helper.hs b/src/Network/HTTP/Pony/Helper.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/HTTP/Pony/Helper.hs
@@ -0,0 +1,15 @@
+-- | Helper
+
+module Network.HTTP.Pony.Helper where
+
+import Control.Monad.IO.Class (MonadIO(..))
+import Network.Socket (Socket, ShutdownCmd(..), shutdown)
+
+infixr 0 -
+f - x = f x
+
+shutdownSend :: (MonadIO m) => Socket -> m ()
+shutdownSend = liftIO . flip shutdown ShutdownSend
+
+shutdownReceive :: (MonadIO m) => Socket -> m ()
+shutdownReceive = liftIO . flip shutdown ShutdownReceive
diff --git a/src/Network/HTTP/Pony/Parser.hs b/src/Network/HTTP/Pony/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/HTTP/Pony/Parser.hs
@@ -0,0 +1,59 @@
+-- | Parser
+
+module Network.HTTP.Pony.Parser where
+
+import           Control.Applicative ((<|>))
+import           Control.Monad.Trans.State.Strict (runStateT)
+import           Data.Attoparsec.ByteString
+import qualified Data.Attoparsec.ByteString.Char8 as Char
+import           Data.ByteString.Char8 (ByteString)
+import qualified Data.ByteString.Char8 as B
+import qualified Data.CaseInsensitive as CI
+import           Pipes (Producer)
+import           Pipes.Attoparsec (ParsingError(..))
+import qualified Pipes.Attoparsec as PA
+
+import           Network.HTTP.Pony.Helper ((-))
+import           Network.HTTP.Pony.Type
+import           Prelude hiding ((-))
+
+-- https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
+
+
+startLine :: Parser ByteString
+startLine = takeTill Char.isEndOfLine <* Char.endOfLine
+
+requestLine :: Parser ByteString
+requestLine = startLine
+
+statusLine :: Parser ByteString
+statusLine = startLine
+
+headers :: Parser [Header]
+headers = do
+  many' header <* Char.endOfLine
+
+token :: Parser ByteString
+token = fmap B.pack - many1' (Char.letter_ascii <|> Char.char '-')
+
+header :: Parser Header
+header = do
+  fieldName <- token
+  Char.char ':'
+  Char.skipSpace
+  fieldValue <- takeTill Char.isEndOfLine
+  Char.endOfLine
+  pure (CI.mk fieldName, fieldValue)
+
+message :: Parser (ByteString, [Header])
+message = do
+  Char.skipSpace
+  (,) <$> startLine <*> headers
+
+parseMessage :: (Monad m) => Producer ByteString m r
+                          -> m a
+                          -> m (Maybe (Either ParsingError (Message ByteString m r)))
+parseMessage p errHandler = do
+  (r, body) <- runStateT (PA.parse message) p
+
+  pure - fmap (fmap (\(x, xs) -> (x, xs, body))) r
diff --git a/src/Network/HTTP/Pony/Serve.hs b/src/Network/HTTP/Pony/Serve.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/HTTP/Pony/Serve.hs
@@ -0,0 +1,64 @@
+-- | Serve
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Network.HTTP.Pony.Serve where
+
+import           Control.Monad.IO.Class (MonadIO(..))
+import           Data.ByteString.Char8 (ByteString)
+import qualified Network.Socket as NS
+import           Pipes (Producer, Consumer, runEffect, (>->))
+import           Pipes.Attoparsec (ParsingError(..))
+import           Pipes.Network.TCP.Safe (HostPreference())
+import           Pipes.Network.TCP.Safe (fromSocket, toSocket)
+import qualified Pipes.Network.TCP.Safe as PipesNetwork
+import           Pipes.Safe (MonadSafe(), runSafeT)
+
+import qualified Network.HTTP.Pony.Builder as Builder
+import           Network.HTTP.Pony.Helper ((-), shutdownSend, shutdownReceive)
+import qualified Network.HTTP.Pony.Parser as Parser
+import           Network.HTTP.Pony.Type (Application, App)
+import           Prelude hiding ((-), log)
+
+serve :: (MonadIO m)  => Producer ByteString m a
+                      -> Consumer ByteString m b
+                      -> Application m ByteString ByteString a b
+                      -> m (Maybe ParsingError)
+serve pull push app = do
+  maybeRequest <- Parser.parseMessage pull (pure ())
+
+  case maybeRequest of
+    Just (Right request) -> do
+      response <- app request
+
+      runEffect -
+        Builder.message response >-> push
+
+      pure Nothing
+    Just (Left err) -> pure - pure - err
+    _ -> pure Nothing
+
+
+
+serveWithSocket :: (MonadIO m)  => (NS.Socket, NS.SockAddr)
+                                -> Application m ByteString ByteString () ()
+                                -> m (Maybe ParsingError)
+serveWithSocket (s,_) =
+  let
+    pull = fromSocket s 4096 >> shutdownReceive s
+    push = toSocket s >> shutdownSend s
+  in
+
+  serve pull push
+
+
+run :: (MonadSafe m) => HostPreference
+                     -> NS.ServiceName
+                     -> App
+                     -> m ()
+run host service app =
+  PipesNetwork.serve host service - \socket -> do
+    r <- serveWithSocket socket app
+    case r of
+      Nothing -> pure ()
+      Just err -> pure () -- log - view packed - show err
diff --git a/src/Network/HTTP/Pony/Type.hs b/src/Network/HTTP/Pony/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/HTTP/Pony/Type.hs
@@ -0,0 +1,19 @@
+module Network.HTTP.Pony.Type where
+
+
+import Data.ByteString (ByteString)
+import Data.CaseInsensitive (CI)
+import Network.Socket (Socket)
+import Pipes (Producer)
+
+type StartLine = ByteString
+type Header = (CI ByteString, ByteString)
+
+type Message a m r = (StartLine, [Header], Producer a m r)
+
+type Request a m r = Message a m r
+type Response a m r = Message a m r
+
+-- App shouldn't block!
+type Application m a b c d = Request a m c -> m (Response b m d)
+type App = Application IO ByteString ByteString () ()
