Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell as REST server

I would like to try Haskell on a smallish project which should be well suited to it. I would like to use it as a backend to a small ajax application.

Haskell backend should be able to do authentication (basic, form, whatever, ...), keep track of user session (not much data there except for username) and to dispatch request to handlers based on uri and request type. It should also be able to serialize response to both xml and json format, depending on request parameter.

I suppose the handlers are ideally suited for Haskell, since the service is basically stateless, but I don't know where to start for the rest of the story.

Searching hackage didn't give me much hints.

Solution for pure haskell server would be prefered.

like image 917
Marko Avatar asked Apr 06 '10 13:04

Marko


4 Answers

I've recently written a production quality web service for internal use. I used the following packages:

  • CGI & FastCGI — for basic web server interfacing
  • UrlDisp — for URL based dispatching
  • HDBC & HDBC-mysql — for database access
  • hexpat — for XML parsing (some requests/responses were XML based)
  • parsec — for configuration file parsing (on the server side)
  • binary &/or cereal — for binary data parsing (some requests/responses were binary based) (though I'd probably use attoparsec now)

Also, for a different project, I'm also using:

  • xhtml — XHTML combinator library

None of these are the highest level components available for Haskell, but they are all quite workable and fairly complete. I avoided the higher-level abstractions since I needed to fit this into an existing larger system, and these packages work just like similar components I've used in other web service projects.

I ran the service as a fastCGI based handler for Apache2 w/mod_fcgid. This appears to be a reliable and efficient set up. I suppose a Haskell based server, compiled together with the service might be faster, but this was pretty reasonable with very little work. I got > 1,400 requests per second on a quad-cpu, 2.6GHz, Linux server.

There are several Haskell pure servers. Most have their own APIs for your service code, though they are all pretty similar. Take a look at:

  • hack and hack-handler-simpleserver (which has an adapter to call code written to CGI/FastCGI directl: hack-handler-cgi, hack-handler-fastcgi)
  • Happstack
  • hyena (which uses the wai interface, and see wai-extra).

That's probably a lot to chew on. Let us know how it goes!

Meanwhile, if you want more information you can visit the HaskellWiki.

like image 193
MtnViewMark Avatar answered Oct 31 '22 09:10

MtnViewMark


It's now May 2011, just an update on current trends.

I think most web development today is done with yesod or the snap frame work. both are very good and very nice developed (thanks to all the people who are involved!!). further there is also the wrap package.

My small REST example (or resful server). (ok maybe the example is not a real restful server, but it shows how you can handle GET/PUT requests, the rest is up to you..)

If you open http://localhost:8000/mytest in a browser, then "Get request" is displayed. If you make a PUT request with a rest-client (also to localhost:8000/mytest), the content of the request body is stored in "/tmp/restrq.txt".

This code is part of the Site.hs file of the Snap-Framework:

- | Constants
tempFilePath :: String
tempFilePath = "/tmp/restrq.txt"


-- | Helper Functions

-- Bytestring Conversion
strictToLazy :: B.ByteString -> BL.ByteString
strictToLazy x
  | B.null x = BL.Empty
  | otherwise = BL.Chunk x BL.Empty

lazyToStrict :: BL.ByteString -> B.ByteString
lazyToStrict = B.concat . BL.toChunks

getRequestString :: MonadSnap m => m B.ByteString
getRequestString = do message <- getRequestBody
                      return (lazyToStrict message)


-- | Action for PUT request
action :: Application ()
action = do message <- getRequestString
            liftIO $ B.writeFile tempFilePath (B8.append (B8.pack "--- REST BODY ---\n") message)

-- | /mytest (GET and PUT requests possible)
mytest :: Application ()
mytest = method GET (writeBS "Get request") <|> method PUT action


-- | The main entry point handler.
site :: Application ()
site = route [ ("/",            index)
             , ("/mytest", mytest)
             ]
       <|> serveDirectory "resources/static"
like image 37
mrsteve Avatar answered Oct 31 '22 11:10

mrsteve


For a server that implements a JSON API I'm using scotty, which builds on WAI+Warp. It is incredibly easy to use, in particular if you've previously built applications with Sinatra.

like image 9
rekado Avatar answered Oct 31 '22 09:10

rekado


I'm not sure how low-level you are trying to go. If you want to write your own server you could start from something like this: http://lstephen.wordpress.com/2008/02/14/a-simple-haskell-web-server/

Alternately, if you are looking for a pre-built framework you could try HApps: http://happs.org/

There is also a Ruby-On-Rails port. Turbinado or something.

Lastly, there are some getting started w/ CGI type tutorials. I've used this one: http://www.haskell.org/haskellwiki/Practical_web_programming_in_Haskell (It was also suggested in @mdm's answer)

Good luck!

like image 2
Tim Perry Avatar answered Oct 31 '22 10:10

Tim Perry