strelka-core (empty) → 0.1
raw patch · 8 files changed
+284/−0 lines, 8 filesdep +basedep +base-preludedep +bifunctorssetup-changed
Dependencies added: base, base-prelude, bifunctors, bytestring, hashable, mtl, semigroups, text, transformers, unordered-containers
Files
- LICENSE +22/−0
- Setup.hs +2/−0
- library/Strelka/Core/Executor.hs +19/−0
- library/Strelka/Core/Model.hs +55/−0
- library/Strelka/Core/Prelude.hs +62/−0
- library/Strelka/Core/RequestParser.hs +32/−0
- library/Strelka/Core/ResponseBuilder.hs +28/−0
- strelka-core.cabal +64/−0
+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2016, Nikita Volkov++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ library/Strelka/Core/Executor.hs view
@@ -0,0 +1,19 @@+module Strelka.Core.Executor where++import Strelka.Core.Prelude+import Strelka.Core.Model+import qualified Strelka.Core.RequestParser as A+import qualified Strelka.Core.ResponseBuilder as B+import qualified Data.Text as C+import qualified Data.Text.Encoding as D+import qualified Data.Text.Encoding.Error as E+++route :: Monad m => Request -> A.RequestParser m B.ResponseBuilder -> m (Either Text Response)+route request route =+ (liftM . liftM) (B.run . fst) (A.run route request segments)+ where+ segments =+ case request of+ Request _ x _ _ _ ->+ x
+ library/Strelka/Core/Model.hs view
@@ -0,0 +1,55 @@+module Strelka.Core.Model where++import Strelka.Core.Prelude+++data Request =+ Request !Method ![PathSegment] !(HashMap ParamName ParamValue) !(HashMap HeaderName HeaderValue) !InputStream++data Response =+ Response !Status ![Header] !OutputStream++-- |+-- HTTP Method __in lower-case__.+newtype Method =+ Method ByteString+ deriving (IsString, Show, Eq, Ord, Hashable)++newtype PathSegment =+ PathSegment Text+ deriving (IsString, Show, Eq, Ord, Hashable)++newtype ParamName =+ ParamName ByteString+ deriving (IsString, Show, Eq, Ord, Hashable)++newtype ParamValue =+ ParamValue (Maybe ByteString)+ deriving (Show, Eq, Ord, Hashable)++data Header =+ Header !HeaderName !HeaderValue++-- |+-- Header name __in lower-case__.+newtype HeaderName =+ HeaderName ByteString+ deriving (IsString, Show, Eq, Ord, Hashable)++newtype HeaderValue =+ HeaderValue ByteString+ deriving (IsString, Show, Eq, Ord, Hashable)++newtype Status =+ Status Int++-- |+-- IO action, which produces the next chunk.+-- An empty chunk signals the end of the stream.+newtype InputStream =+ InputStream (IO ByteString)++-- |+-- A function on a chunk consuming and flushing IO actions.+newtype OutputStream =+ OutputStream ((ByteString -> IO ()) -> IO () -> IO ())
+ library/Strelka/Core/Prelude.hs view
@@ -0,0 +1,62 @@+module Strelka.Core.Prelude+( + module Exports,+ tryError,+)+where+++-- base-prelude+-------------------------+import BasePrelude as Exports hiding (First(..), Last(..), (<>))++-- transformers+-------------------------+import Control.Monad.IO.Class as Exports+import Control.Monad.Trans.Class as Exports+import Control.Monad.Trans.Cont as Exports hiding (shift, callCC)+import Control.Monad.Trans.Except as Exports (ExceptT(ExceptT), Except, except, runExcept, runExceptT, mapExcept, mapExceptT, withExcept, withExceptT)+import Control.Monad.Trans.Maybe as Exports+import Control.Monad.Trans.Reader as Exports (Reader, runReader, mapReader, withReader, ReaderT(ReaderT), runReaderT, mapReaderT, withReaderT)+import Control.Monad.Trans.State.Strict as Exports (State, runState, evalState, execState, mapState, withState, StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT)+import Control.Monad.Trans.Writer.Strict as Exports (Writer, runWriter, execWriter, mapWriter, WriterT(..), execWriterT, mapWriterT)++-- mtl+-------------------------+import Control.Monad.Cont.Class as Exports+import Control.Monad.Error.Class as Exports hiding (Error(..))+import Control.Monad.Reader.Class as Exports+import Control.Monad.State.Class as Exports+import Control.Monad.Writer.Class as Exports++-- semigroups+-------------------------+import Data.Semigroup as Exports++-- bifunctors+-------------------------+import Data.Bifunctor as Exports++-- unordered-containers+-------------------------+import Data.HashMap.Strict as Exports (HashMap)++-- bytestring+-------------------------+import Data.ByteString as Exports (ByteString)++-- text+-------------------------+import Data.Text as Exports (Text)++-- hashable+-------------------------+import Data.Hashable as Exports++-- Utils+-------------------------+import qualified Data.ByteString as ByteString++tryError :: MonadError e m => m a -> m (Either e a)+tryError m =+ catchError (liftM Right m) (return . Left)
+ library/Strelka/Core/RequestParser.hs view
@@ -0,0 +1,32 @@+module Strelka.Core.RequestParser where++import Strelka.Core.Prelude+import Strelka.Core.Model+++{-|+Parser of an HTTP request.+Analyzes its meta information, consumes the path segments and the body.+-}+newtype RequestParser m a =+ RequestParser (ReaderT Request (StateT [PathSegment] (ExceptT Text m)) a)+ deriving (Functor, Applicative, Monad, Alternative, MonadPlus, MonadError Text)++instance MonadIO m => MonadIO (RequestParser m) where+ liftIO io =+ RequestParser ((lift . lift . ExceptT . liftM (either (Left . fromString . show) Right) . liftIO . trySE) io)+ where+ trySE :: IO a -> IO (Either SomeException a)+ trySE =+ Strelka.Core.Prelude.try++instance MonadTrans RequestParser where+ lift m =+ RequestParser (lift (lift (lift m)))++{-|+Execute the parser providing a request and a list of segments.+-}+run :: RequestParser m a -> Request -> [PathSegment] -> m (Either Text (a, [PathSegment]))+run (RequestParser impl) request segments =+ runExceptT (runStateT (runReaderT impl request) segments)
+ library/Strelka/Core/ResponseBuilder.hs view
@@ -0,0 +1,28 @@+module Strelka.Core.ResponseBuilder where++import Strelka.Core.Prelude+import Strelka.Core.Model+++{-|+A composable abstraction for building an HTTP response.+-}+newtype ResponseBuilder =+ ResponseBuilder (Response -> Response)++instance Monoid ResponseBuilder where+ mempty =+ ResponseBuilder id+ mappend (ResponseBuilder fn1) (ResponseBuilder fn2) =+ ResponseBuilder (fn2 . fn1)++instance Semigroup ResponseBuilder+++{-|+Execute the builder producing Response.+-}+run :: ResponseBuilder -> Response+run (ResponseBuilder fn) =+ fn (Response (Status 200) [] (OutputStream (const (const (pure ())))))+
+ strelka-core.cabal view
@@ -0,0 +1,64 @@+name:+ strelka-core+version:+ 0.1+synopsis:+ Core components of "strelka"+description:+ This library is only intended for the internal usage+ by the \"strelka\" ecosystem.+ It exposes the components,+ which may be needed by both the \"strelka\" library and+ the server drivers.+homepage:+ https://github.com/nikita-volkov/strelka-core+bug-reports:+ https://github.com/nikita-volkov/strelka-core/issues +author:+ Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer:+ Nikita Volkov <nikita.y.volkov@mail.ru>+copyright:+ (c) 2016, Nikita Volkov+license:+ MIT+license-file:+ LICENSE+build-type:+ Simple+cabal-version:+ >=1.10++source-repository head+ type:+ git+ location:+ git://github.com/nikita-volkov/strelka-core.git++library+ hs-source-dirs:+ library+ other-modules:+ Strelka.Core.Prelude+ exposed-modules:+ Strelka.Core.Model+ Strelka.Core.RequestParser+ Strelka.Core.ResponseBuilder+ Strelka.Core.Executor+ default-extensions:+ Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+ default-language:+ Haskell2010+ build-depends:+ -- + bytestring >= 0.10 && < 0.11,+ text >= 1 && < 2,+ unordered-containers >= 0.2 && < 0.3,+ hashable == 1.*,+ -- + bifunctors == 5.*,+ semigroups >= 0.18 && < 0.19,+ mtl == 2.*,+ transformers >= 0.4 && < 0.6,+ base-prelude < 2,+ base < 5