|
|
|
|
|
Description |
Lucu is an HTTP daemonic library. It can be embedded in any
Haskell program and runs in an independent thread.
Features:
- Full support of HTTP\1.1/
- Lucu supports request pipelining,
chunked I/O, ETag comparison and "100 Continue".
- Performance
- Lucu doesn't fork/exec to handle requests like
CGI. It just spawns a new thread. Inter-process communication is
done with STM.
Lucu is not a replacement for Apache. It is intended to be used to
create an efficient web-based application without messing around
FastCGI. It is also intended to be run behind a reverse-proxy so it
doesn't have the following (otherwise essential) facilities:
- Logging
- Lucu doesn't log any requests from any clients.
- Client Filtering
- Lucu always accepts any clients. No IP
filter is implemented.
- SSL Support
- Lucu can handle only HTTP.
- Bandwidth Limitting
- Lucu doesn't limit bandwidth it consumes.
- Protection Against Wicked Clients
- Lucu is fragile against
wicked clients. No attacker should be able to cause a
buffer-overflow but can possibly DoS it.
|
|
Synopsis |
|
|
|
|
Entry Point
|
|
|
This is the entry point of Lucu httpd. It listens to a socket and
waits for clients. Computation of runHttpd never stops by itself
so the only way to stop it is to raise an exception in the thread
computing it.
Note that runHttpd automatically makes SIGPIPE be ignored by
computing installHandler
sigPIPE Ignore
Nothing. This can hardly cause a problem but it may do.
Example:
module Main where
import Network.HTTP.Lucu
main :: IO ()
main = let config = defaultConfig
resources = mkResTree [ ([], helloWorld) ]
in
runHttpd config resourcees []
helloWorld :: ResourceDef
helloWorld = ResourceDef {
resUsesNativeThread = False
, resIsGreedy = False
, resGet
= Just $ do setContentType $ read "text/plain"
output "Hello, world!"
, resHead = Nothing
, resPost = Nothing
, resPut = Nothing
, resDelete = Nothing
}
|
|
Configuration
|
|
module Network.HTTP.Lucu.Config |
|
Resource Tree
|
|
|
ResourceDef is basically a set of
Resource monads for each HTTP methods.
| Constructors | ResourceDef | | resUsesNativeThread :: !Bool | Whether to run a Resource on a
native thread (spawned by forkOS) or to
run it on a user thread (spanwed by
forkIO). Generally you don't need to set
this field to True.
| resIsGreedy :: !Bool | Whether to be greedy or not.
Say a client is trying to access /aaa/bbb/ccc. If there is a
greedy resource at /aaa/bbb, it is always chosen even if
there is another resource at /aaa/bbb/ccc. If the resource
at /aaa/bbb is not greedy, it is just ignored. Greedy
resources are like CGI scripts.
| resGet :: !(Maybe (Resource ())) | A Resource to be run when a GET
request comes for the resource path. If resGet is Nothing,
the system responds "405 Method Not Allowed" for GET
requests.
It also runs for HEAD request if the resHead is Nothing. In
this case output and such like
don't actually write a response body.
| resHead :: !(Maybe (Resource ())) | A Resource to be run when a HEAD
request comes for the resource path. If resHead is Nothing,
the system runs resGet instead. If resGet is also Nothing,
the system responds "405 Method Not Allowed" for HEAD
requests.
| resPost :: !(Maybe (Resource ())) | A Resource to be run when a POST
request comes for the resource path. If resPost is Nothing,
the system responds "405 Method Not Allowed" for POST
requests.
| resPut :: !(Maybe (Resource ())) | A Resource to be run when a PUT
request comes for the resource path. If resPut is Nothing,
the system responds "405 Method Not Allowed" for PUT
requests.
| resDelete :: !(Maybe (Resource ())) | A Resource to be run when a
DELETE request comes for the resource path. If resDelete is
Nothing, the system responds "405 Method Not Allowed" for
DELETE requests.
|
|
|
|
|
|
|
|
|
mkResTree converts a list of (path, def) to a ResTree e.g.
mkResTree [ ([] , Network.HTTP.Lucu.StaticFile.staticFile "/usr/include/stdio.h" ) -- /
, (["unistd"], Network.HTTP.Lucu.StaticFile.staticFile "/usr/include/unistd.h") -- /unistd
]
|
|
Resource Monad
|
|
module Network.HTTP.Lucu.Resource |
|
Things to be used in the Resource monad
|
|
Status Code
|
|
|
This is the definition of HTTP status code.
Network.HTTP.Lucu.Resource.setStatus accepts these named statuses
so you don't have to memorize, for instance, that "Gateway
Timeout" is 504.
| Constructors | Continue | | SwitchingProtocols | | Processing | | Ok | | Created | | Accepted | | NonAuthoritativeInformation | | NoContent | | ResetContent | | PartialContent | | MultiStatus | | MultipleChoices | | MovedPermanently | | Found | | SeeOther | | NotModified | | UseProxy | | TemporaryRedirect | | BadRequest | | Unauthorized | | PaymentRequired | | Forbidden | | NotFound | | MethodNotAllowed | | NotAcceptable | | ProxyAuthenticationRequired | | RequestTimeout | | Conflict | | Gone | | LengthRequired | | PreconditionFailed | | RequestEntityTooLarge | | RequestURITooLarge | | UnsupportedMediaType | | RequestRangeNotSatisfiable | | ExpectationFailed | | UnprocessableEntitiy | | Locked | | FailedDependency | | InternalServerError | | NotImplemented | | BadGateway | | ServiceUnavailable | | GatewayTimeout | | HttpVersionNotSupported | | InsufficientStorage | |
| Instances | |
|
|
Abortion
|
|
|
Computation of abort status headers msg aborts the
Network.HTTP.Lucu.Resource.Resource monad with given status,
additional response headers, and optional message string.
What this really does is to throw a special
Exception. The exception will be caught by the
Lucu system.
1. If the Network.HTTP.Lucu.Resource.Resource is in the /Deciding
Header/ or any precedent states, it is possible to use the
status and such like as a HTTP response to be sent to the
client.
2. Otherwise the HTTP response can't be modified anymore so the
only possible thing the system can do is to dump it to the
stderr. See
cnfDumpTooLateAbortionToStderr.
Note that the status code doesn't have to be an error code so you
can use this action for redirection as well as error reporting e.g.
abort MovedPermanently
[("Location", "http://example.net/")]
(Just "It has been moved to example.net")
|
|
|
This is similar to abort but computes it with
unsafePerformIO.
|
|
|
Computation of abortA -< (status, (headers, msg)) just
computes abort in an ArrowIO.
|
|
ETag
|
|
|
An entity tag is made of a weakness flag and a opaque string.
| Constructors | ETag | | etagIsWeak :: !Bool | The weakness flag. Weak tags looks like W/"blahblah" and
strong tags are like "blahblah".
| etagToken :: !String | An opaque string. Only characters from 0x20 (sp) to 0x7e (~)
are allowed.
|
|
| Instances | |
|
|
|
This is equivalent to ETag False. If you want to
generate an ETag from a file, try using
Network.HTTP.Lucu.StaticFile.generateETagFromFile.
|
|
|
This is equivalent to ETag True.
|
|
MIME Type
|
|
|
MIMEType "major" "minor" [("name", "value")]
represents "major/minor; name=value".
| Constructors | | Instances | |
|
|
Authorization
|
|
|
Authorization challenge to be sent to client with
"WWW-Authenticate" header. See
Network.HTTP.Lucu.Resource.setWWWAuthenticate.
| Constructors | | Instances | |
|
|
|
Authorization credential to be sent by client with
"Authorization" header. See
Network.HTTP.Lucu.Resource.getAuthorization.
| Constructors | | Instances | |
|
|
Utility
|
|
Static file handling
|
|
module Network.HTTP.Lucu.StaticFile |
|
Produced by Haddock version 2.4.2 |