packages feed

http2-grpc-types (empty) → 0.1.0.0

raw patch · 7 files changed

+340/−0 lines, 7 filesdep +basedep +binarydep +bytestringsetup-changed

Dependencies added: base, binary, bytestring, proto-lens, zlib

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for http2-grpc-types++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Author name here (c) 2018++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 Author name here 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.
+ README.md view
@@ -0,0 +1,3 @@+# http2-grpc-types++A module to put in common HTTP2/gRPC types, values, and helpers.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ http2-grpc-types.cabal view
@@ -0,0 +1,43 @@+-- This file has been generated from package.yaml by hpack version 0.28.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: ac7deaf4e4e16246c07477c353a2f55ac558d8b90ae2a0682e21c1bfd613a057++name:           http2-grpc-types+version:        0.1.0.0+synopsis:       Types for gRPC over HTTP2 common for client and servers.+description:    Please see the README on GitHub at <https://github.com/lucasdicioccio/http2-grpc-types#readme>+category:       Network+homepage:       https://github.com/lucasdicioccio/http2-grpc-types#readme+bug-reports:    https://github.com/lucasdicioccio/http2-grpc-types/issues+author:         Lucas DiCioccio+maintainer:     lucas@dicioccio.fr+copyright:      2018 Lucas DiCioccio+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10+extra-source-files:+    ChangeLog.md+    README.md++source-repository head+  type: git+  location: https://github.com/lucasdicioccio/http2-grpc-types++library+  exposed-modules:+      Network.GRPC.HTTP2.Encoding+      Network.GRPC.HTTP2.Types+  other-modules:+      Paths_http2_grpc_types+  hs-source-dirs:+      src+  build-depends:+      base >=4.7 && <5+    , binary >=0.8.5 && <0.11+    , bytestring >=0.10.8 && <0.11+    , proto-lens >=0.3.1 && <0.4+    , zlib+  default-language: Haskell2010
+ src/Network/GRPC/HTTP2/Encoding.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Module for GRPC binary encoding/decoding from and to binary messages.+--+-- So far, only "pure" compression algorithms are supported as we rely on+-- 'Decoder' (resp. 'Builder') which run with no interleaved side-effects.+module Network.GRPC.HTTP2.Encoding (+  -- * Decoding.+    decoder+  , fromDecoder+  , decodeInput+  , decodeOutput+  -- * Encoding.+  , encode+  , fromBuilder+  , encodeInput+  , encodeOutput+  -- * Compression.+  , Compression+  , grpcCompressionHV+  , uncompressed+  , gzip+  ) where++import qualified Codec.Compression.GZip as GZip+import           Data.Binary.Builder (Builder, toLazyByteString, fromByteString, singleton, putWord32be)+import           Data.Binary.Get (getByteString, getInt8, getWord32be, runGetIncremental, Decoder(..))+import           Data.ByteString.Char8 (ByteString)+import qualified Data.ByteString.Char8 as ByteString+import           Data.ByteString.Lazy (fromStrict, toStrict)+import           Data.ProtoLens.Encoding (encodeMessage, decodeMessage)+import           Data.ProtoLens.Message (Message)+import           Data.ProtoLens.Service.Types (Service(..), HasMethod, HasMethodImpl(..))++import           Network.GRPC.HTTP2.Types++-- | Decoder for gRPC/HTTP2-encoded Protobuf messages.+decoder :: Message a => Compression -> Decoder (Either String a)+decoder compression = runGetIncremental $ do+    isCompressed <- getInt8      -- 1byte+    let decompress = if isCompressed == 0 then id else (_decompressionFunction compression)+    n <- getWord32be             -- 4bytes+    decodeMessage . decompress <$> getByteString (fromIntegral n)++-- | Tries finalizing a Decoder.+fromDecoder :: Decoder (Either String a) -> Either String a+fromDecoder (Fail _ _ msg) = Left msg+fromDecoder (Partial _)    = Left "got only a subet of the message"+fromDecoder (Done _ _ val) = val++decodeOutput+  :: (Service s, HasMethod s m)+  => RPC s m+  -> Compression+  -> Decoder (Either String (MethodOutput s m))+decodeOutput _ = decoder++decodeInput+  :: (Service s, HasMethod s m)+  => RPC s m+  -> Compression+  -> Decoder (Either String (MethodInput s m))+decodeInput _ = decoder++-- | Encodes as binary using gRPC/HTTP2 framing.+encode :: Message m => Compression -> m -> Builder+encode compression plain =+    mconcat [ singleton (if _compressionByteSet compression then 1 else 0)+            , putWord32be (fromIntegral $ ByteString.length bin)+            , fromByteString (_compressionFunction compression $ bin)+            ]+  where+    bin = encodeMessage plain++-- | Finalizes a Builder.+fromBuilder :: Builder -> ByteString+fromBuilder = toStrict . toLazyByteString++encodeInput+  :: (Service s, HasMethod s m)+  => RPC s m+  -> Compression+  -> MethodInput s m -> Builder+encodeInput _ = encode++encodeOutput+  :: (Service s, HasMethod s m)+  => RPC s m+  -> Compression+  -> MethodOutput s m -> Builder+encodeOutput _ = encode++-- | Opaque type for handling compression.+--+-- So far, only "pure" compression algorithms are supported.+-- TODO: suport IO-based compression implementations once we move from 'Builder'.+data Compression = Compression {+    _compressionName       :: ByteString+  , _compressionByteSet    :: Bool+  , _compressionFunction   :: (ByteString -> ByteString)+  , _decompressionFunction :: (ByteString -> ByteString)+  }++grpcCompressionHV :: Compression -> HeaderValue+grpcCompressionHV = _compressionName++-- | Do not compress.+uncompressed :: Compression+uncompressed = Compression "identity" False id id++-- | Use gzip as compression.+gzip :: Compression+gzip = Compression "gzip" True (toStrict . GZip.compress . fromStrict) (toStrict . GZip.decompress . fromStrict)
+ src/Network/GRPC/HTTP2/Types.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++-- | Module for GRPC <> HTTP2 mapping.+module Network.GRPC.HTTP2.Types where++import           Control.Exception (Exception)+import           Data.ProtoLens.Service.Types (Service(..), HasMethod, HasMethodImpl(..))+import           Data.Proxy (Proxy(..))+import           Data.ByteString.Char8 (ByteString)+import qualified Data.ByteString.Char8 as ByteString+import           GHC.TypeLits (Symbol, symbolVal)++-- | HTTP2 Header Key.+type HeaderKey = ByteString++-- | HTTP2 Header Value.+type HeaderValue = ByteString++grpcTimeoutH :: HeaderKey+grpcTimeoutH = "grpc-timeout"++grpcEncodingH :: HeaderKey+grpcEncodingH = "grpc-encoding"++grpcAcceptEncodingH :: HeaderKey+grpcAcceptEncodingH = "grpc-accept-encoding"++grpcAcceptEncodingHVdefault :: HeaderValue+grpcAcceptEncodingHVdefault = "identity,gzip"++grpcStatusH :: HeaderKey+grpcStatusH = "grpc-status"++grpcMessageH :: HeaderKey+grpcMessageH = "grpc-message"++grpcContentTypeHV :: HeaderValue+grpcContentTypeHV = "application/grpc+proto"++grpcStatusHV :: HeaderValue+grpcStatusHV = "Grpc-Status"++grpcMessageHV :: HeaderValue+grpcMessageHV = "Grpc-Message"++-- https://grpc.io/grpc/core/impl_2codegen_2status_8h.html#a35ab2a68917eb836de84cb23253108eb+data GRPCStatusCode =+    OK+  | CANCELLED+  | UNKNOWN+  | INVALID_ARGUMENT+  | DEADLINE_EXCEEDED+  | NOT_FOUND+  | ALREADY_EXISTS+  | PERMISSION_DENIED+  | UNAUTHENTICATED+  | RESOURCE_EXHAUSTED+  | FAILED_PRECONDITION+  | ABORTED+  | OUT_OF_RANGE+  | UNIMPLEMENTED+  | INTERNAL+  | UNAVAILABLE+  | DATA_LOSS+  deriving (Show, Eq, Ord)++trailerForStatusCode :: GRPCStatusCode -> ByteString+trailerForStatusCode = \case+    OK+      -> "0"+    CANCELLED+      -> "1"+    UNKNOWN+      -> "2"+    INVALID_ARGUMENT+      -> "3"+    DEADLINE_EXCEEDED+      -> "4"+    NOT_FOUND+      -> "5"+    ALREADY_EXISTS+      -> "6"+    PERMISSION_DENIED+      -> "7"+    UNAUTHENTICATED+      -> "16"+    RESOURCE_EXHAUSTED+      -> "8"+    FAILED_PRECONDITION+      -> "9"+    ABORTED+      -> "10"+    OUT_OF_RANGE+      -> "11"+    UNIMPLEMENTED+      -> "12"+    INTERNAL+      -> "13"+    UNAVAILABLE+      -> "14"+    DATA_LOSS+      -> "15"++type GRPCStatusMessage = ByteString++data GRPCStatus = GRPCStatus !GRPCStatusCode !GRPCStatusMessage+  deriving (Show, Eq, Ord)++instance Exception GRPCStatus++trailers :: GRPCStatus -> [(ByteString, ByteString)]+trailers (GRPCStatus s msg) =+    if ByteString.null msg then [status] else [status, message]+  where+    status = ("grpc-status", trailerForStatusCode s)+    message = ("grpc-message", msg)++-- | A proxy type for giving static information about RPCs.+data RPC (s :: *) (m :: Symbol) = RPC++-- | Returns the HTTP2 :path for a given RPC.+path :: (Service s, HasMethod s m) => RPC s m -> ByteString+{-# INLINE path #-}+path rpc = "/" <> pkg rpc Proxy <> "." <> srv rpc Proxy <> "/" <> meth rpc Proxy+  where+    pkg :: (Service s) => RPC s m -> Proxy (ServicePackage s) -> ByteString+    pkg _ p = ByteString.pack $ symbolVal p++    srv :: (Service s) => RPC s m -> Proxy (ServiceName s) -> ByteString+    srv _ p = ByteString.pack $ symbolVal p++    meth :: (Service s, HasMethod s m) => RPC s m -> Proxy (MethodName s m) -> ByteString+    meth _ p = ByteString.pack $ symbolVal p++-- | Timeout in seconds.+newtype Timeout = Timeout Int++showTimeout :: Timeout -> ByteString+showTimeout (Timeout n) = ByteString.pack $ show n ++ "S"++-- | The HTTP2-Authority portion of an URL (e.g., "dicioccio.fr:7777").+type Authority = ByteString.ByteString+