Happstack is the Haskell application server
stack. It is primarily used for web application development,
but it can be used for any type of application server.
Happstack's mission is to enable developers to prototype quickly,
deploy painlessly, scale massively, operate reliably, and change
easily.
Why You Should Read This
This guide is designed to provide you with a clear, practical
understanding of how to develop applications with Happstack. It is not
especially witty or entertaining, but it should be very easy to read
and pratical to apply. I have avoided any talk of theory and just
focused on how to get things done.
Every topic covered in the course comes with a small,
self-contained, fully-functional example which you can download directly
from the page. This should make it very easy to experiment and to
learn by doing.
I highly recommend you read this tutorial first rather than trying
to understand Happstack by looking at the source code and haddock
documentation. Learning Happstack by looking at the source and haddock
docs would be like trying to learn to drive by first opening up the
hood of the car and trying to understand what is going and then
reading the owners manual.
This guide will take you through all the practical aspects of using
Happstack, and keep you from accidentally focusing on unimportant
things like UnWebT
. This is a course for people who want
to drive the car, not open an auto shop.
This tutorial assumes that you will be deploying your application
on a VPS or dedicated server where you can have a server process that
is always running. However, many components of Happstack can be used
in a CGI / shared-server environment.
This tutorial is still a work in progress. If you want to contribute to this tutorial you can get the source via:
darcs get http://src.seereason.com/happstack-crashcourse
If you find mistakes or have difficulty following portions of this course, please let us know on the mailing list so that we can make fixes and improvements.
-
Hello, World!
-
Your first app!
-
How it works
-
Listening for HTTP requests
-
Configuring the HTTP listener
-
Processing a Request
-
Setting the HTTP response code
-
Creating a Response
-
Route Filters
-
Choosing between multiple ServerPartTs
-
Matching on static path segments
-
Using dir to match on static path components
-
Using dir to match on multiple components
-
Using dirs as shorthand to match on multiple components
-
Matching on variable path segments
-
path
-
FromReqURI: extending path
-
Matching on Request Method (GET, POST, etc)
-
methodM and methodOnly
-
Advanced method matching with MatchMethod
-
Other Routing Filters
-
Templating for HTML and Javascript
-
Using BlazeHtml
-
Using HSX/HSP
-
What does trhsx do?
-
Important HSX types and classes
-
the XMLGenT type
-
the XMLGen class
-
the XML m type synonym
-
the EmbedAsChild class
-
the EmbedAsAttr class
-
the XMLGenerator class
-
HSX by Example
-
HSX and do syntax
-
defaultTemplate
-
How to embed empty/nothing/zero
-
Creating a list of children
-
if .. then .. else ..
-
Lists of attributes & optional attributes
-
HSX and compilation errors
-
Line numbers are usually wrong
-
Overlapping Instances
-
Ambiguous Types
-
HSX + OverloadedStrings
-
HSP and internationalization (aka, i18n)
-
HSP + i18n Core Concept
-
the RenderMessage class
-
shakespeare-i18n translation files
-
Constructor arguments, #{ }, and plurals
-
Type Annotations
-
Variable Splices
-
Handling plurals and other language specifics
-
Translating Existing Types
-
Alternative Translations
-
Using messages in HSX templates
-
Detecting the preferred languages
-
Conclusions
-
Using Heist
-
Other Heist Features
-
JavaScript via JMacro
-
JMacro in a <script> tag
-
JMacro in an HTML attribute (onclick, etc)
-
Automatice escaping of </
-
Hygienic Variable Names
-
Non-Hygienic Variable Names
-
Declaring Functions
-
Splicing Haskell Values into JavaScript (Antiquotation)
-
Using ToJExpr to convert Haskell values to JavaScript
-
Using JMacro in external .js scripts
-
Links to demos
-
Alternative IntegerSupply instance
-
More Information
-
Parsing request data from the QUERY_STRING, cookies, and request body
-
Hello RqData
-
Handling missions
-
Why is decodeBody even needed?
-
Using BodyPolicy and defaultBodyPolicy to impose quotas
-
Using decodeBody
-
Other tips for using <form>
-
File Uploads
-
File uploads important reminder
-
Limiting lookup to QUERY_STRING or request body
-
Using the RqData Monad for better error reporting
-
Handling non-String request parameters
-
Using Read
-
Using checkRq
-
Other uses of checkRq
-
Looking up optional parameters
-
Working with Cookies
-
What are Cookies?
-
Simple Cookie Demo
-
Cookie Lifetime
-
Deleting a Cookie
-
Cookie Issues
-
Security issues
-
Delayed Effect
-
Cookie Size
-
Server Clock Time
-
Cookie Updates are Not Atomic
-
Other Cookie Features
-
Serving Files from Disk
-
Serving Files from a Directory
-
File Serving Security
-
Serving a Single File
-
Advanced File Serving
-
Type-Safe Form processing using reform
-
Brief History
-
Hello Form!
-
Using the Form
-
reform function
-
Cross-Site Request Forgery (CSRF) Protection
-
Benefits So Far
-
Form with Simple Validation
-
Separating Validation and Views
-
Type Indexed / Parameterized Applicative Functors
-
Using Proofs in unproven Forms
-
Conclusion
-
main
-
Web Routes
-
Web Routes Demo
-
Web Routes + Type Families
-
Web Routes Boomerang
-
web-routes and HSP
-
Still to come
-
acid-state
-
How acid-state works
-
acid-state counter
-
IxSet: a set with multiple indexed keys
-
Defining the indexing keys
-
Inserting a Record
-
Updating a Record
-
Looking up a value by its indexed key
-
Ordering the Results and the Proxy type
-
Summary
-
Rest of the Example Code
-
IxSet and Data.Lens
-
Creating Lenses
-
Getters
-
Lens is an instance of Category
-
Setters
-
Modifiers
-
Updating Nested Records
-
Other Modifiers
-
Lens for IxSet
-
Using a getter with IxSet
-
Inserting an element into an IxSet
-
Deleting an element from an IxSet
-
Using a modifier with IxSet
-
Using `partial-lens` with IxSet
-
Using a setter and modifier with IxSet in an acid-state event
-
Passing multiple AcidState handles around transparently
-
Optional Plugins/Components
-
Using Template Haskell