### Snap Web Server Basics Source: https://github.com/snapframework/snap/wiki/Book-Outline Demonstrates the fundamental setup of a web server using the Snap framework, including routing combinators and handling request data. ```Haskell import Snap.Core import Snap.Util.Heist (renderText) -- A simple handler helloHandler :: Snap () helloHandler = writeBS "Hello from Snap!" -- Basic routing app :: Snap () app = route [ ("hello", helloHandler) ] -- To run this, you would typically use a main function like: -- main :: IO () -- main = serveSnap snapConfig app -- where snapConfig is defined elsewhere. ``` -------------------------------- ### Hspec Migration Example Source: https://github.com/snapframework/snap/wiki/1.0-TODO-List Demonstrates the necessary code changes to migrate from the 'test-framework' to 'hspec' testing library in Haskell projects. This includes changes to imports, function names, and test structure. ```haskell import Test.Hspec import Test.Hspec.QuickCheck -- Original test structure (example): -- defaultMain [ -- testGroup "MyTests" [ -- testCase "MyFirstTest" (assertEqual "Expected value" 5 (2+3)), -- testProperty "MyProperty" (\(x :: Int) -> x == x) -- ] -- ] -- Migrated test structure: spec :: Spec spec = describe "MyTests" $ do it "MyFirstTest" $ do (2 + 3) `shouldBe` 5 prop "MyProperty" $ \(x :: Int) -> x == x main :: IO () main = hspec spec ``` -------------------------------- ### HasHeist Instance Example Source: https://github.com/snapframework/snap/blob/master/design.md Example of how to define a HasHeist instance for an application type. This allows Heist API functions to be used without explicitly passing a lens. ```haskell instance HasHeist App where heistLens = subSnaplet heist ``` -------------------------------- ### Enter Nix Shell for Snap Development Source: https://github.com/snapframework/snap/blob/master/README.md Instructions for entering the Nix shell environment for Snap development, which sets up the necessary dependencies. Includes an option for direnv integration. ```Shell nix-shell ``` ```Shell echo 'use nix' > .envrc && direnv allow ``` -------------------------------- ### Run Snap Test Suite Source: https://github.com/snapframework/snap/blob/master/README.md Command to build and execute the test suite for the Snap Framework. ```Shell cabal test all ``` -------------------------------- ### Organizing Apps with Snaplets Source: https://github.com/snapframework/snap/wiki/Book-Outline Explains the concept of Snaplets for modularizing and organizing Snap applications, promoting code reusability and maintainability. ```Haskell -- A hypothetical example of defining and using a snaplet. -- This is conceptual and requires the 'snaplet' package. -- Define a simple snaplet mySnaplet :: Snaplet () mySnaplet = makeSnaplet "mySnaplet" Nothing $ return () -- Integrate the snaplet into the application -- appWithSnaplet :: SnapApp () -- appWithSnaplet = -- addSnaplet "mySnaplet" mySnaplet $ -- defaultMainApp -- The actual implementation involves more setup and configuration. ``` -------------------------------- ### Initializing a Snaplet Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Shows the process of initializing a snaplet within the application's initializer function. It uses `nestSnaplet` to integrate the snaplet and returns the initialized snaplet. ```Haskell f <- nestSnaplet "" foo $ fooInit fooParam return $ App h f ``` -------------------------------- ### Build Snap Project with Cabal Source: https://github.com/snapframework/snap/blob/master/README.md Commands to build the Snap Framework project using Cabal. This includes updating git submodules and then building all targets. ```Shell git submodule update --init --recursive cabal build all ``` -------------------------------- ### HTML Templating with Heist Source: https://github.com/snapframework/snap/wiki/Book-Outline Illustrates how to integrate Heist for HTML templating within a Snap application, allowing for dynamic content generation. ```Haskell import Snap.Util.Heist -- Assuming 'heistConfig' is properly set up for Heist -- and 'myTemplate.tpl' exists in the template directory. -- This handler renders a Heist template. renderMyTemplate :: Snap () renderMyTemplate = renderText "myTemplate" -- Example of passing context to a template: -- renderWithContext :: Snap () -- renderWithContext = -- let context = [("name", HS.string "World")] -- in renderWithContext "myTemplate" context ``` -------------------------------- ### Specialize to App (Not Recommended) Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets An approach where a snaplet's handlers are specialized to the application's base state (`Handler App v a`). This makes it easy to use `withTop` but prevents snaplet reusability. ```Haskell Handler App v a ``` -------------------------------- ### Build Haddock Documentation for Snap Source: https://github.com/snapframework/snap/blob/master/README.md Commands to generate Haddock documentation for the Snap project. It can be built for the main snap package or the entire project including submodules. ```Shell cabal haddock snap ``` ```Shell cabal haddock-project ``` -------------------------------- ### Haskell: Passing Specific Handlers to Initializer Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Demonstrates how to pass specific handler functions from a logger snaplet to another snaplet's initializer, promoting independence from the logger implementation. ```Haskell data Wiki b = Wiki { writeLogHandler :: Handler b b () , clearLogHandler :: Handler b b () , ... } initWiki writeHandler clearHandler = makeSnaplet ... $ do ... return $ Wiki writeHandler clearHandler ... ``` -------------------------------- ### Using 'with' to call Snaplet Functions Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Illustrates how to use the `with` function from the `MonadSnaplet` type class to call functions from a nested snaplet. This requires a lens to access the snaplet within the application state. ```Haskell with :: Lens v (Snaplet v') -> m b v' a -> m b v a ``` -------------------------------- ### Pass a Lens to Initializer (Recommended) Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets The recommended approach where a lens to another snaplet is passed to the initializer and stored in the snaplet's state. This allows handlers to easily access other snaplets using the stored lens. ```Haskell data Wiki b = Wiki { loggerLens :: Lens b (Snaplet Logger) , ... } initWiki lens = makeSnaplet ... $ do ... return $ Wiki lens ... wikiHandler :: Handler b (Wiki b) a wikiHandler = do lens <- gets loggerLens withTop lens $ writeLog ... ``` -------------------------------- ### Pass a Lens to Handlers (Annoying) Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Passing a lens as a parameter to each handler function that needs to access another snaplet. This is functional but leads to repetitive parameter passing. ```Haskell Lens b (Snaplet Logger) -> Handler b v a ``` -------------------------------- ### Haskell: HasLogger Type Class with Handlers Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Abstracts the pattern of passing specific handlers into a HasLogger type class, providing direct access to logging functions. ```Haskell class HasLogger b where writeLog :: Text -> Handler b b () clearLog :: Handler b b () ``` -------------------------------- ### CSRF Protection Splice (Naive Approach) Source: https://github.com/snapframework/snap/wiki/HTML-Templating-With-Heist A naive implementation of a splice to add CSRF protection to form tags. It demonstrates the basic structure but has a flaw where multiple hidden fields can be added. ```haskell secureForm1 :: MonadIO m => m Text -- ^ A computation in the runtime monad that gets the CSRF -- protection token. -> Splice m secureForm1 csrfToken = do stopRecursion n <- getParamNode token <- lift csrfToken let input = X.Element "input" [("type", "hidden"), ("name", "_csrf"), ("value", token)] [] case n of X.Element nm as cs -> return [X.Element nm as (input : cs)] _ -> return [n] -- "impossible" ``` -------------------------------- ### Adding a Snaplet to Application State Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Demonstrates how to declare a snaplet within an application's data structure. This involves adding a field of type `Snaplet ` to the main application state record. ```Haskell data App = App { _heist :: Snaplet (Heist App) , _foo :: Snaplet Foo } ``` -------------------------------- ### Haskell: HasLogger Type Class for Monadic Context Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Formulates a HasLogger type class for use in a generic monadic context, decoupling the API from the Handler monad for broader applicability. ```Haskell class (Monad m) => HasLogger m where writeLog :: Text -> m () clearLog :: m () -- Example constraint for IO operations: -- class (MonadIO m) => HasLogger m where ... ``` -------------------------------- ### Haskell: HasLogger Type Class with Lens Source: https://github.com/snapframework/snap/wiki/Organizing-Your-App-With-Snaplets Defines a HasLogger type class using a Lens to provide access to logger functions, allowing for an identity instance for direct logger usage. ```Haskell class HasLogger b where loggerLens :: Lens (Snaplet b) (Snaplet Logger) instance HasLogger Logger where loggerLens = id ``` -------------------------------- ### Handler Monad Definition Source: https://github.com/snapframework/snap/blob/master/design.md Defines the Handler monad, which is built upon LensT to provide request-local state management within the Snap framework. It uses lenses to allow for composable and scoped state modifications. ```Haskell newtype Handler b v a = Handler (LensT (Snaplet b) (Snaplet v) (Snaplet b) Snap a) ``` -------------------------------- ### LensT Monad Definition Source: https://github.com/snapframework/snap/blob/master/design.md Defines the LensT monad, a combination of ReaderT and StateT, used for managing state with lenses in the Snap framework. It provides MonadReader and MonadState instances for transparent state manipulation. ```Haskell newtype LensT b v s m a = LensT (RST (Lens b v) s m a) ``` -------------------------------- ### CSRF Protection Splice (Final Refinement) Source: https://github.com/snapframework/snap/wiki/HTML-Templating-With-Heist The final refined version of the CSRF protection splice. It correctly processes the node list to ensure the hidden CSRF field is added only once, addressing issues with attribute processing. ```haskell secureForm3 :: MonadIO m => m Text -- ^ A computation in the runtime monad that gets the CSRF -- protection token. -> Splice m secureForm3 csrfToken = do stopRecursion n <- getParamNode token <- lift csrfToken let input = X.Element "input" [("type", "hidden"), ("name", "_csrf"), ("value", token)] [] case n of X.Element nm as cs -> do cs' <- runNodeList cs let newCs = if take 1 cs' == [input] then cs' else (input : cs') return [X.Element nm as newCs] _ -> return [n] -- "impossible" ``` -------------------------------- ### CSRF Protection Splice (Improved with Check) Source: https://github.com/snapframework/snap/wiki/HTML-Templating-With-Heist An improved version of the CSRF protection splice that includes a check to prevent adding duplicate hidden fields. It examines the existing attributes of the form tag. ```haskell secureForm2 :: MonadIO m => m Text -- ^ A computation in the runtime monad that gets the CSRF -- protection token. -> Splice m secureForm2 csrfToken = do stopRecursion n <- getParamNode token <- lift csrfToken let input = X.Element "input" [("type", "hidden"), ("name", "_csrf"), ("value", token)] [] case n of X.Element nm as cs -> do let newCs = if take 1 cs == [input] then cs else (input : cs) return [X.Element nm as newCs] _ -> return [n] -- "impossible" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.