diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,8 @@
+## 5.2.2
+
+* Mark final chunk as final
+  [#116](https://github.com/kazu-yamamoto/http2/pull/116)
+
 ## 5.2.1
 
 * Using time-manager v0.1.0.
diff --git a/Network/HTTP2/H2/Receiver.hs b/Network/HTTP2/H2/Receiver.hs
--- a/Network/HTTP2/H2/Receiver.hs
+++ b/Network/HTTP2/H2/Receiver.hs
@@ -180,7 +180,7 @@
                 streamId
                 "no body but content-length is not zero"
     tlr <- newIORef Nothing
-    let inpObj = InpObj tbl (Just 0) (return "") tlr
+    let inpObj = InpObj tbl (Just 0) (return (mempty, True)) tlr
     if isServer ctx
         then do
             let si = toServerInfo roleInfo
@@ -441,7 +441,7 @@
         then do
             tbl <- hpackDecodeTrailer frag streamId ctx
             writeIORef tlr (Just tbl)
-            atomically $ writeTQueue q $ Right ""
+            atomically $ writeTQueue q $ Right (mempty, True)
             return HalfClosedRemote
         else -- we don't support continuation here.
             E.throwIO $
@@ -486,7 +486,7 @@
                     E.throwIO $ ConnectionErrorIsSent EnhanceYourCalm streamId "too many empty data"
             else do
                 writeIORef bodyLength len
-                atomically $ writeTQueue q $ Right body
+                atomically $ writeTQueue q $ Right (body, endOfStream)
         if endOfStream
             then do
                 case mcl of
@@ -499,7 +499,7 @@
                                     streamId
                                     "actual body length is not the same as content-length"
                 -- no trailers
-                atomically $ writeTQueue q $ Right ""
+                atomically $ writeTQueue q $ Right (mempty, True)
                 return HalfClosedRemote
             else return s
 
@@ -615,26 +615,26 @@
 data Source
     = Source
         (Int -> IO ())
-        (TQueue (Either E.SomeException ByteString))
+        (TQueue (Either E.SomeException (ByteString, Bool)))
         (IORef ByteString)
         (IORef Bool)
 
 mkSource
-    :: TQueue (Either E.SomeException ByteString) -> (Int -> IO ()) -> IO Source
+    :: TQueue (Either E.SomeException (ByteString, Bool)) -> (Int -> IO ()) -> IO Source
 mkSource q inform = Source inform q <$> newIORef "" <*> newIORef False
 
-readSource :: Source -> IO ByteString
+readSource :: Source -> IO (ByteString, Bool)
 readSource (Source inform q refBS refEOF) = do
     eof <- readIORef refEOF
     if eof
-        then return ""
+        then return (mempty, True)
         else do
-            bs <- readBS
+            (bs, isEOF) <- readBS
             let len = BS.length bs
             inform len
-            return bs
+            return (bs, isEOF)
   where
-    readBS :: IO ByteString
+    readBS :: IO (ByteString, Bool)
     readBS = do
         bs0 <- readIORef refBS
         if bs0 == ""
@@ -644,9 +644,9 @@
                     Left err -> do
                         writeIORef refEOF True
                         E.throwIO err
-                    Right bs -> do
-                        when (bs == "") $ writeIORef refEOF True
-                        return bs
+                    Right (bs, isEOF) -> do
+                        writeIORef refEOF isEOF
+                        return (bs, isEOF)
             else do
                 writeIORef refBS ""
-                return bs0
+                return (bs0, False)
diff --git a/Network/HTTP2/H2/Stream.hs b/Network/HTTP2/H2/Stream.hs
--- a/Network/HTTP2/H2/Stream.hs
+++ b/Network/HTTP2/H2/Stream.hs
@@ -85,7 +85,7 @@
                     mErr
         case st of
             Open _ (Body q _ _ _) ->
-                atomically $ writeTQueue q $ maybe (Right mempty) Left mErr
+                atomically $ writeTQueue q $ maybe (Right (mempty, True)) Left mErr
             _otherwise ->
                 return ()
     mErr :: Maybe SomeException
diff --git a/Network/HTTP2/H2/Types.hs b/Network/HTTP2/H2/Types.hs
--- a/Network/HTTP2/H2/Types.hs
+++ b/Network/HTTP2/H2/Types.hs
@@ -109,7 +109,7 @@
     | NoBody TokenHeaderTable
     | HasBody TokenHeaderTable
     | Body
-        (TQueue (Either SomeException ByteString))
+        (TQueue (Either SomeException (ByteString, Bool)))
         (Maybe Int) -- received Content-Length
         -- compared the body length for error checking
         (IORef Int) -- actual body length
diff --git a/http2.cabal b/http2.cabal
--- a/http2.cabal
+++ b/http2.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               http2
-version:            5.2.1
+version:            5.2.2
 license:            BSD3
 license-file:       LICENSE
 maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>
@@ -115,7 +115,7 @@
         bytestring >=0.10,
         case-insensitive >=1.2 && <1.3,
         containers >=0.6 && <0.7,
-        http-semantics,
+        http-semantics >= 0.0.1,
         http-types >=0.12 && <0.13,
         network >=3.1,
         network-byte-order >=0.1.7 && <0.2,
