happstack-0.2.1: RELEASE_NOTES
Happstack 0.2 Release Notes
================================================================================
Project / Code generation tool
-------------------------------
There is now a code generation tool for Happstack. This is inspired by the
'rails' command.
1. First install happstack (cabal install happstack)
2. Make sure the cabal bin dir is in your path
- in linux this is
~/.cabal/bin
- in windows this is
C:\Documents and Settings\<username>\Application Data\cabal\bin
where <username> is your windows username.
3. Run this command:
happstack new project <dir>
where <dir> is the folder you want to create the project in.
4. It will create several folders:
- bin (scripts for your project go here)
- dist (where deployment files will go)
- public (static files for the http server)
- src (project source code goes here)
- templates (HStringTemplate files go here)
5. There are three scripts to get your project kick-started
- bin/build (build a static compiled binary at dist/app)
- bin/run (run the project dynamically)
- bin/run-interactive (run the project interactively in ghci)
Each script has a .sh version if you are on *nix and a .bat version if
you are on windows.
6. By default, your project will bind to port 8000 on every ip address your
machine has.
7. There are five source files in the src folder by default
- AppControl.hs (routing and controller code goes here)
- AppState.hs (MACID state objects are defined here)
- AppView.hs (presentation / view code goes here)
- AppLogger.hs (controls logging for the hslogger system)
- Main.hs (entry point to your app, is has the routines needed to
run your application)
8. Enjoy!
The WebT/ServerPartT change
-------------------------------
WebT and ServerPartT have been substantially refactored. They are now built
from simpler monads. ServerPartT is now the only monad you have to deal
with, most of the time. I.e. you almost never have to look at WebT again.
You just have do blocks in ServerPartT. Inside ServerPartT you can get your
request (askRq), modify your request (localRq), exit immediately
(finishWith), exit failure (mzero), and alter your response filters
(composeFilter, setFilter, getFilter) It also lifts ErrorT, ReaderT, WriterT
and StateT, so you can embed one of those as well. As a bonus, nearly all
the functions you expected to take a WebT or to operate only within a WebT
can now work inside a ServerPartT directly. The monad stack handles all the
data threading.
That being said, here are a list of the non-backwards compatible changes.
ServerPartT, WebT, unServerPartT and unWebT now have different semantics. To
get existing code to compile you can change your methods like so:
ServerPartT -> withRequest
WebT -> mkWebT
unServerPartT -> runServerPartT
unWebT -> ununWebT or runWebT depending on what you're going for.
By just making the above changes, your existing code should continue to work
as before. However, at this point, any old code you have can be greatly
simplified. For example, you will never have to use anyRequest or
withRequest to change from ServerPartT to WebT. You never have to interact
with WebT directly. You can do everything in a ServerPartT do block. The
examples provided in the documentation (especially basicAuth') just barely
touch on the power of ServerPartT now. Notice that basicAuth' mixes reading
requests and altering responses all without exposing WebT, constructing a
ServerPartT, or really doing any data threading at all.
As a quick example:
This:
uriRest :: Monad m => (String -> ServerPartT m a) -> ServerPartT m a
uriRest handle = withRequest $ \rq ->
unServerPartT (handle (rqURL rq)) rq
Becomes this:
uriRest :: (ServerMonad m, Monad m) => (String -> m a) -> m a
uriRest handle = askRq >>= handle . rqURL
Every single function that uses withRequest, anyRequest, unServerPartT,
unWebT or ununWebT can be rewritten to take advantage of these simple monad
behaviors. Additionally, a lot of functions were added to make it easier to
work entirely inside a do block.
getHeaderM, addHeaderM, getData, getDataFn, escape', finishWith, getFilter,
setFilter, composeFilter, applyFilter, setResponseCode, guardRq, methodM,
methodOnly, nullDir, requireM
The following were deprecated since they duplicate functionality
noHandle -> Use mzero
multi -> Use msum
method -> you should be able to use methodSP though you'll need to fix
your typing
modifyResponse -> use composeFilter
Also, this release sees the return of simpleHTTP', though not as you knew it
before. simpleHTTP must take a ServerPartT IO a. simpleHTTP' lets you use
Any ServerPartT m a, as long as you provide a function for unwrapping your
interior monad into an IO monad. This is particularly important since
ServerPartT has lifting instances for WriterT, StateT, ErrorT, and ReaderT,
thus embedding your favorite monad transformer into ServerPartT is easier
than ever.
Documentation
-------------------------------
This release also adds substantial documentation for the package
Happstack.Server.SimpleHTTP which convers most of the new structures added,
as well as many of your old favorites. Be sure to check it out.
Removing list types from SimpleHTTP
-------------------------------
Having most of the methods in SimpleHTTP take array types was cumbersome,
since often you only had one part and had to wrap it up. All methods that
used to take a list of ServerPartTs now only take a single ServerPartT. To
convert your list of ServerPartT into a single ServerPartT, use msum.
For example:
simpleHTTP nullConf [spart1, spart2]
Becomes:
simpleHTTP nullConf $ msum [spart1, spart2]
The functions affected by this change are:
simpleHTTP, dir, path, anyPath, withData, withDataFn, require, requireM,
xslt, debugFilter, applyRequest, basicAuth, and errorHandlerSP
Gzip/Deflate encoding
------------------------------
There is now a ServerPartT for gzip/deflate encoding, in
Happstack.Server.Parts.compressedResponseFilter
Guidlines for porting existing HAppS and Happstack <= 0.1 code to 0.2
-------------------------------
The first change you should do is change the following functions
as described above.
ServerPartT -> withRequest
WebT -> mkWebT
unServerPartT -> runServerPartT
unWebT -> ununWebT
Next, work on prepending $ msum in front of every list of ServerPartTs, or
deleting lists that are no longer necessary.
After this point, you should be able to get your app compiled and running.
To further clean up your code and take advantage of the new functionality in
ServerPartT, the general procedure is as follows:
- consider studying the revised examples in happstack-server/Examples. They
all use the new idioms.
- delete your type signatures that reference WebT or ServerPartT, as after
the first step they will all have changed dramatically
- delete all uses of withRequest and anyRequest (they aren't needed anymore)
- change the idiom 'method m $' to 'methodM m >>'
- change 'withRequest \rq -> do ...' to 'do { rq <- askRq; ... }'
- change withData \myDat $ \dat -> do ... to
do dat <- getData >>= maybe mzero return
...
- change withDataFn fn \myDat $ \dat -> do ... to
do dat <- getDataFn fn >>= maybe mzero return
...
- change all references of noHandle to mzero
- you can probably benefit from some do blocks at this point
- if you're passing around the request explictly, stop. You can just
"rq <- askRq" whenever you need it.
- consider embedding your favorite monad transformer into your ServerPartTs.
To make this work, you'll want to read the documentation for simpleHTTP',
mapServerPartT, and WebT
- consider reading the newly minted documentation for
Happstack.Server.SimpleHTTP. Hopefully you'll learn something.
Windows Bin Path Caveats
------------------------------
By default when you install say ghc 6.8.3 or 6.10.1, windows won't setup the paths.
You need to perform these steps after running the installer for ghc:
1. Right Click on "My Computer"
2. Left Click on "Properties"
3. Advanced Tab
4. Environmental Variables
5. Add or Edit existing 'PATH' variable
If you have ghc 6.8.3 for instance:
1. Prepend "C:\ghc\ghc-6.8.3;C:\ghc\ghc-6.8.3\bin;" to the Variable value
2. Click OK
3. Restart and cmd windows you have open
6. Now all the commands should work i.e. ghci, ghc-pkg, perl etc.
7. You will need happy to compile happstack
Follow these steps:
1. Install happy via cabal install or the manual method
2. Prepend "C:\Documents and Settings\user\Application Data\cabal\bin"
to your Environment Path variable where user is your username.
3. Now any binaries installed by cabal packages will also be in your
command path.