u}3      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                            splitBy (== ':') "ab:c:def"  ==> ["ab", "c", "def"]  ! joinWith ":" ["ab", "c", "def"]  ==> "ab:c:def"   trim (== '_') "__ab_c__def___"  ==> "ab_c__def"  c is  iff c is one of SP, HT, CR  and LF.   quoteStr "abc"  ==> "\"abc\""  quoteStr "ab\"c"  ==> "\"ab\\\"c\""  * parseWWWFormURLEncoded "aaa=bbb&ccc=ddd" & ==> [("aaa", "bbb"), ("ccc", "ddd")] %    a0 is obviously a parser which parses and returns a.    is just a synonym for   .   p bstr parses bstr with p and returns (# result,  remaining #).   p str packs str and parses it.  p makes p& treat reaching EOF a normal failure. CThis is the backtracking alternation. There is no non-backtracking  equivalent.   !"#  !"#    !"#   !"# $$ c is ! iff 0x20 <= c < 0x7F. %% c is  iff c is one of HTTP  separators. && c is  iff c <= 0x7f. '' c is equivalent to not ($ c || %  c) (( p is similar to  p  ( ',') but it allows any 2 occurrences of LWS before and after each tokens. )) is equivalent to  $   ' ** is an HTTP LWS: #?  (! | ")+ ++" accepts one character which doesn' t satisfy $. ,,' accepts one character which satisfies %. --1 accepts a string surrounded by double quotation . marks. Quotes can be escaped by backslashes. .. accepts a so-called qvalue. $%&'()*+,-. $%&'()*+,-. $%&'()*+,-./0/ major minor represents "HTTP/ major.minor". 012/012/012/0012"#3 Format a System.Time.CalendarTime to RFC 1123 Date and Time  string. 4 Format a System.Time.ClockTime" to HTTP Date and Time. Time zone ' will be always UTC but prints as GMT. 5Parse an HTTP Date and Time. Limitation: RFC 2616 (HTTP/%1.1) says we must accept these three  formats:  =Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 ?Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 'Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format:...but currently this function only supports the RFC 1123 A format. This is a violation of RFC 2616 so this should be fixed  later. What a bother! $345345345%&'()%'()%'()*+,-./0123456789:;<=>*+,-./2579:<=>*+,-./+,-./2579:<=>6'This is the definition of HTTP reqest. 789:;<=This is the definition of HTTP request methods, which shouldn't  require any description. =>?@ABCDEF?@A6789:;<=>?@ABCDEF<EDCBA@?>=6789:;F6789:;789:;< EDCBA@?>==>?@ABCDEFBCDBCDBCD>GHIJKL,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. MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{E|| sc is  iff sc < 200. }} sc is  iff 200 <= sc < 300. ~~ sc is  iff 300 <= sc < 400.  sc is  iff 400 <= sc  sc is  iff 400 <= sc < 500.  sc is  iff 500 <= sc. F sc1 returns an unboxed tuple of numeric and textual  representation of sc. <GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~<Lzyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMGHIJK{|}~<GHIJKHIJKL.zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "major" "minor" [("name", "value")]  represents "major/minor; name=value". Parse  from a G. This function throws an  exception for parse error.  H from extension to MIME Type. Guess the MIME Type of file. (Read an Apache mime.types and parse it. IJ extMap moduleName variableName generates a : Haskell source code which contains the following things:  A definition of module named  moduleName.  variableName :: % whose content is a serialization of  extMap.  The module .Network.HTTP.Lucu.MIMEType.DefaultExtensionMap is ' surely generated using this function.   >An entity tag is made of a weakness flag and a opaque string. )The weakness flag. Weak tags looks like W/"blahblah" and  strong tags are like "blahblah". =An opaque string. Only characters from 0x20 (sp) to 0x7e (~)  are allowed. This is equivalent to  !. If you want to ) generate an ETag from a file, try using  1Network.HTTP.Lucu.StaticFile.generateETagFromFile. This is equivalent to  .  7 is just a string which must not contain any non-ASCII  letters. 7 is just a string which must not contain colon and any  non-ASCII letters. 3Authorization credential to be sent by client with  " Authorization" header. See  +Network.HTTP.Lucu.Resource.getAuthorization. @ is just a string which must not contain any non-ASCII letters. 2Authorization challenge to be sent to client with  "WWW-Authenticate" header. See  -Network.HTTP.Lucu.Resource.setWWWAuthenticate.  ,Configuration record for HTTPS connections. 6A port ID to listen to HTTPS clients. Local addresses : (both for IPv4 and IPv6) will be derived from the parent  . *An SSL context for accepting connections. 9Configuration record for the Lucu httpd. You need to use  3 or setup your own configuration to run the httpd. *A string which will be sent to clients as "Server" field. 8The host name of the server. This value will be used in  built-in pages like " 404 Not Found". ;A port number (or service name) to listen to HTTP clients. 4Local IPv4 address to listen to both HTTP and HTTPS  clients. Set this to (K 0.0.0.0) if you want to accept # any IPv4 connections. Set this to L to disable IPv4. 4Local IPv6 address to listen to both HTTP and HTTPS  clients. Set this to (K ::) if you want to accept any  IPv6 connections. Set this to L to disable IPv6. Note A that there is currently no way to assign separate ports to IPv4  and IPv6 server sockets. .Configuration for HTTPS connections. Set this L to  disable HTTPS. ;The maximum number of requests to accept in one connection ? simultaneously. If a client exceeds this limitation, its last  request won'1t be processed until a response for its earliest - pending request is sent back to the client. >The maximum length of request entity to accept in bytes. Note ? that this is nothing but the default value which is used when   Network.HTTP.Lucu.Resource.input and such like are applied to  'Network.HTTP.Lucu.Resource.defaultLimit, so there is no ? guarantee that this value always constrains all the requests. =The maximum length of chunk to output. This value is used by  !Network.HTTP.Lucu.Resource.output and such like to limit the @ chunk length so you can safely output an infinite string (like  a lazy stream of /dev/random) using those actions. <Whether to dump too late abortion to the stderr or not. See   Network.HTTP.Lucu.Abortion.abort. =A mapping from extension to MIME Type. This value is used by  'Network.HTTP.Lucu.StaticFile.staticFile to guess the MIME : Type of static files. Note that MIME Types are currently  guessed only by file name. >Guessing by file magic is indeed a wonderful idea but that is  not implemented (yet). But, don't you think it's better a file = system got a MIME Type as a part of inode? Or it might be a  good idea to use GnomeVFS  ( 5http://developer.gnome.org/doc/API/2.0/gnome-vfs-2.0/)  instead of vanilla FS. CThe default configuration. Generally you can use this value as-is, * or possibly you just want to replace the  and  +. SSL connections are disabled by default.  *MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv*MNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv*MNSRQPOOPQRSTUVWXYZ[\]^_`abcdefghijklmnUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyzwxywxy Computation of  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  {&. The exception will be caught by the  Lucu system.   If the #Network.HTTP.Lucu.Resource.Resource is in the / Deciding  Header/4 or any precedent states, it is possible to use the  status4 and such like as a HTTP response to be sent to the  client.  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  . Note that the status code doesn'"t have to be an error code so you E can use this action for redirection as well as error reporting e.g.  abort MovedPermanently - [("Location", "http://example.net/")] 1 (Just "It has been moved to example.net") This is similar to  but computes it with  |. Computation of  status headers msg just computes   in a Control.Monad.STM.STM monad. Computation of  -< (status, (headers, msg)) just  computes  in an }.  ~<This data type represents a form entry name, form value and ! possibly an uploaded file name. /The  monad. This monad implements  Control.Monad.Trans.MonadIO so it can do any   actions. Get the  value which is used for  the httpd. Get the ! of the remote host. If you want $ a string representation instead of , use  . @Get the string representation of the address of remote host. If  you want a  instead of G,  use . 'Resolve an address to the remote host. /Return the X.509 certificate of the client, or L if:  This request didn't came through an SSL stream.  The client didn't send us its certificate.  The  OpenSSL.Session.VerificationMode of  OpenSSL.Session.SSLContext in   has not been set to  OpenSSL.Session.VerifyPeer. Get the 76 value which represents ' the request header. In general you don't have to use this action. Get the < value of the request. Get the URI of the request. %Get the HTTP version of the request. Get the path of this  (to be exact,  +Network.HTTP.Lucu.Resource.Tree.ResourceDef ) in the  'Network.HTTP.Lucu.Resource.Tree.ResTree. The result of this 2 action is the exact path in the tree even if the  +Network.HTTP.Lucu.Resource.Tree.ResourceDef is greedy.  Example: 3 main = let tree = mkResTree [ (["foo"], resFoo) ] ' in runHttpd defaultConfig tree   resFoo = ResourceDef {  resIsGreedy = True 6 , resGet = Just $ do requestURI <- getRequestURI 8 resourcePath <- getResourcePath 4 pathInfo <- getPathInfo @ -- uriPath requestURI == "/foo/bar/baz" 9 -- resourcePath == ["foo"] @ -- pathInfo == ["bar", "baz"]  ...  , ...  } 3This is an analogy of CGI PATH_INFO. The result is  URI-unescaped. It is always [] if the  +Network.HTTP.Lucu.Resource.Tree.ResourceDef is not greedy. See  . (Assume the query part of request URI as  application/1x-www-form-urlencoded, and parse it. This action  doesn't parse the request body. See . BGet a value of given request header. Comparison of header name is D case-insensitive. Note that this action is not intended to be used - so frequently: there should be actions like  for  every common headers. Get a list of  enumerated on  header "Accept". Get a list of (contentCoding, qvalue) enumerated on header  "Accept-Encoding",. The list is sorted in descending order by  qvalue. 4Check whether a given content-coding is acceptable. Get the header " Content-Type" as  . Get the header " Authorization" as  . Tell the system that the  found an entity for the E request URI. If this is a GET or HEAD request, a found entity means E a datum to be replied. If this is a PUT or DELETE request, it means C a datum which was stored for the URI up to now. It is an error to  compute  if this is a POST request. Computation of  performs "If-Match" test or  " If-None-Match". test if possible. When those tests fail, the  computation of  immediately aborts with status "412  Precondition Failed" or "304 Not Modified" depending on the  situation. "If this is a GET or HEAD request,  automatically puts  "ETag" and " Last-Modified" headers into the response. Tell the system that the  found an entity for the ' request URI. The only difference from  is that   doesn' t (and can't) put " Last-Modified" header into  the response. -This action is not preferred. You should use  whenever  possible. Tell the system that the  found an entity for the ' request URI. The only difference from  is that   performs "If-Modified-Since" test or  "If-Unmodified-Since" test instead of "If-Match" test or  " If-None-Match"- test. Be aware that any tests based on last E modification time are unsafe because it is possible to mess up such 2 tests by modifying the entity twice in a second. -This action is not preferred. You should use  whenever  possible. Computation of  mStr tells the system that the  & found no entity for the request URI. mStr is an 5 optional error message to be replied to the client. If this is a PUT request,  performs "If-Match"  test and aborts with status "412 Precondition Failed" when it 9 failed. If this is a GET, HEAD, POST or DELETE request,   always aborts with status " 404 Not Found". Computation of  limit# attempts to read the request body  up to limit bytes, and then make the  transit to  Deciding Header/ state. When the actual size of body is larger  than limit bytes, computation of  immediately aborts  with status "413 Request Entity Too Large". When the request has  no body,  returns an empty string. limit6 may be less than or equal to zero. In this case, the  default limitation value  () is used. See  .  Note that  is more efficient than  so you should  use it whenever possible. This is mostly the same as  but is more  efficient.  returns a Data.ByteString.Lazy.ByteString  but it';s not really lazy: reading from the socket just happens at  the computation of , not at the evaluation of the  Data.ByteString.Lazy.ByteString. The same goes for  . Computation of  limit attempts to read a part of  request body up to limit* bytes. You can read any large request by / repeating computation of this action. When you've read all the  request body, ' returns an empty string and then make  the  transit to Deciding Header state. limit6 may be less than or equal to zero. In this case, the  default limitation value  () is used. See  .  Note that  is more efficient than  so you " should use it whenever possible. This is mostly the same as  but is more  efficient. See . Computation of  limit attempts to read the request  body with  and parse it as  application/"x-www-form-urlencoded or multipart/form-data. If the  request header " Content-Type" is neither of them,   makes  abort with status "415 Unsupported Media  Type". If the request has no " Content-Type", it aborts with  "400 Bad Request". This is just a constant -1. It's better to say    than to say  (-1) but these are exactly  the same. BSet the response status code. If you omit to compute this action, & the status code will be defaulted to "200 OK". @Set a value of given resource header. Comparison of header name B is case-insensitive. Note that this action is not intended to be 2 used so frequently: there should be actions like   for every common headers. #Some important headers (especially "Content-Length" and  "Transfer-Encoding",) may be silently dropped or overwritten by > the system not to corrupt the interaction with client at the C viewpoint of HTTP protocol layer. For instance, if we are keeping D the connection alive, without this process it causes a catastrophe  to send a header "Content-Length: 10" and actually send a body of D 20 bytes long. In this case the client shall only accept the first D 10 bytes of response body and thinks that the residual 10 bytes is ( a part of header of the next response. Computation of  code uri sets the response status to  code and "Location" header to uri. The code must satisfy  ~ or it causes an error. Computation of  mType sets the response header  " Content-Type" to mType. Computation of  uri sets the response header  "Location" to uri. Computation of  codings sets the response  header "Content-Encoding" to codings. Computation of  challenge sets the response  header "WWW-Authenticate" to  challenge. Computation of  str writes str as a response body,  and then make the  transit to Done state. It is safe to  apply 1 to an infinite string, such as a lazy stream of  /dev/random.  Note that  is more efficient than  so you should  use it whenever possible. This is mostly the same as  but is more efficient. Computation of  str writes str as a part of D response body. You can compute this action multiple times to write . a body little at a time. It is safe to apply  to an  infinite string.  Note that  is more efficient than  so & you should use it whenever possible. This is mostly the same as  but is more efficient. //*: is an opaque structure which is a map from resource path  to .  is basically a set of   monads for each HTTP methods. Whether to run a  on a  native thread (spawned by ) or to % run it on a user thread (spanwed by  ). Generally you don't need to set  this field to . 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. A  to be run when a GET ) request comes for the resource path. If  is Nothing,  the system responds "405 Method Not Allowed" for GET  requests. %It also runs for HEAD request if the  is Nothing. In  this case  and such like  don'"t actually write a response body. A  to be run when a HEAD ) request comes for the resource path. If  is Nothing,  the system runs  instead. If  is also Nothing,  the system responds "405 Method Not Allowed" for HEAD  requests. A  to be run when a POST ) request comes for the resource path. If  is Nothing,  the system responds "405 Method Not Allowed" for POST  requests. A  to be run when a PUT ) request comes for the resource path. If  is Nothing,  the system responds "405 Method Not Allowed" for PUT  requests. A  to be run when a 0 DELETE request comes for the resource path. If  is  Nothing, the system responds "405 Method Not Allowed" for  DELETE requests. 2 is an extra resource handler for resources which  can'<t be statically located somewhere in the resource tree. The C Lucu httpd first search for a resource in the tree, and then call = fallback handlers to ask them for a resource. If all of the  handlers returned L, the httpd responds with 404  Not Found. ) is a resource definition with no actual  handlers. You can construct a  by selectively  overriding . It is defined as follows:  ! emptyResource = ResourceDef { 1 resUsesNativeThread = False 1 , resIsGreedy = False 3 , resGet = Nothing 3 , resHead = Nothing 3 , resPost = Nothing 3 , resPut = Nothing 3 , resDelete = Nothing  }  converts a list of  (path, def) to a  e.g.   mkResTree [ ([] , 'Network.HTTP.Lucu.StaticFile.staticFile "/usr/include/stdio.h" ) -- /  , (["unistd"], 'Network.HTTP.Lucu.StaticFile.staticFile "/usr/include/unistd.h") -- /unistd  ]  fpath is a   which serves the file  at fpath on the filesystem. Computation of  fpath serves the file at  fpath on the filesystem. The   must be in the / Examining  Request1 state before the computation. It will be in the Done/  state after the computation. /If you just want to place a static file on the  , you had better use   instead of this. Computation of  fpath generates a strong ' entity tag from a file. The file doesn't necessarily have to be a E regular file; it may be a FIFO or a device file. The tag is made of ' inode ID, size and modification time. CNote that the tag is not strictly strong because the file could be C modified twice at a second without changing inode ID or size, but  it'>s not really possible to generate a strict strong ETag from a  file since we don'1t want to simply grab the entire file and use it C as an ETag. It is indeed possible to hash it with SHA-1 or MD5 to  increase strictness, but it'(s too inefficient if the file is really  large (say, 1 TiB).  dir is a   which maps all files  in dir1 and its subdirectories on the filesystem to the  . Computation of  dir maps all files in dir 1 and its subdirectories on the filesystem to the  . The   must be in the / Examining  Request1 state before the computation. It will be in the Done/  state after the computation. 9If you just want to place a static directory tree on the  , you had better use   instead of this. BThis is the entry point of Lucu httpd. It listens to a socket and # waits for clients. Computation of  never stops by itself C so the only way to stop it is to raise an exception in the thread  computing it.  Note that + automatically makes SIGPIPE be ignored by  computing      L1. This can hardly cause a problem but it may do.  Example:  module Main where  import Network.HTTP.Lucu   main :: IO () & main = let config = defaultConfig 7 resources = mkResTree [ ([], helloWorld) ]  in ( runHttpd config resourcees []   helloWorld :: ResourceDef  helloWorld = ResourceDef { , resUsesNativeThread = False , , resIsGreedy = False  , resGet A = Just $ do setContentType $ read "text/plain" 5 output "Hello, world!" $ , resHead = Nothing $ , resPost = Nothing $ , resPut = Nothing $ , resDelete = Nothing  }  LMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyzNLzyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONM!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPPQRSTUVVWXYZ[\]^_`abcdeffghijklmnopqrstuvwxyz{|}~                     !"#$%&'()*+,-./01234+567869:;./<=>?@ABCDEFGHIIJKLMNOPQRSTUVWXYZ[\]^67_`ab c d6ef6eghijklmnoopqrstuvwxyz{|}~66.66Lucu-0.5Network.HTTP.Lucu.UtilsNetwork.HTTP.Lucu.ParserNetwork.HTTP.Lucu.Parser.HttpNetwork.HTTP.Lucu.HttpVersion!Network.HTTP.Lucu.RFC1123DateTimeNetwork.HTTP.Lucu.RequestNetwork.HTTP.Lucu.ResponseNetwork.HTTP.Lucu.MIMEType Network.HTTP.Lucu.MIMEType.Guess.Network.HTTP.Lucu.MIMEType.DefaultExtensionMapNetwork.HTTP.Lucu.ETagNetwork.HTTP.Lucu.AuthorizationNetwork.HTTP.Lucu.ConfigNetwork.HTTP.Lucu.AbortionNetwork.HTTP.Lucu.ResourceNetwork.HTTP.Lucu.Resource.TreeNetwork.HTTP.Lucu.StaticFileNetwork.HTTP.Lucu.HttpdNetwork.HTTP.Lucu.FormatNetwork.HTTP.Lucu.HandleLikeNetwork.HTTP.Lucu.SocketLikeNetwork.HTTP.Lucu.ContentCodingNetwork.HTTP.Lucu.HeadersNetwork.HTTP.Lucu.ChunkNetwork.HTTP.Lucu.InteractionNetwork.HTTP.Lucu.DefaultPageNetwork.HTTP.Lucu.MultipartFormNetwork.HTTP.Lucu.Postprocess Network.HTTP.Lucu.ResponseWriterNetwork.HTTP.Lucu.PreprocessNetwork.HTTP.Lucu.RequestReaderNetwork.HTTP.LucusplitByjoinWithtrim isWhiteSpacequoteStrparseWWWFormURLEncoded ParserResult ReachedEOF IllegalInputSuccessParserfailPparseparseStranyChareofallowEOFsatisfycharstring<|>choiceoneOf notFollowedBydigithexDigitmanymanyCharmany1countoptionsepBysepBy1sphtcrlfisCtl isSeparatorisCharisTokenlistOftokenlwstext separator quotedStrqvalue HttpVersion httpVersionPhPutHttpVersionformatRFC1123DateTimeformatHTTPDateTimeparseHTTPDateTimeRequest reqMethodreqURI reqVersion reqHeadersMethodExtensionMethodCONNECTTRACEDELETEPUTPOSTHEADGETOPTIONSrequestPResponse resVersion resStatus resHeaders StatusCodeInsufficientStorageHttpVersionNotSupportedGatewayTimeoutServiceUnavailable BadGatewayNotImplementedInternalServerErrorFailedDependencyLockedUnprocessableEntitiyExpectationFailedRequestRangeNotSatisfiableUnsupportedMediaTypeRequestURITooLargeRequestEntityTooLargePreconditionFailedLengthRequiredGoneConflictRequestTimeoutProxyAuthenticationRequired NotAcceptableMethodNotAllowedNotFound ForbiddenPaymentRequired Unauthorized BadRequestTemporaryRedirectUseProxy NotModifiedSeeOtherFoundMovedPermanentlyMultipleChoices MultiStatusPartialContent ResetContent NoContentNonAuthoritativeInformationAcceptedCreatedOk ProcessingSwitchingProtocolsContinue hPutResponseisInformational isSuccessful isRedirectionisError isClientError isServerError statusCodeMIMETypemtMajormtMinormtParams parseMIMEType mimeTypeP mimeTypeListPExtMapguessTypeByFileNameparseExtMapFileserializeExtMapdefaultExtensionMapETag etagIsWeak etagToken strongETagweakETageTagP eTagListPPasswordUserIDAuthCredentialBasicAuthCredentialRealm AuthChallengeBasicAuthChallengeauthCredentialP SSLConfig sslServerPort sslContextConfigcnfServerSoftware cnfServerHost cnfServerPortcnfServerV4AddrcnfServerV6Addr cnfSSLConfigcnfMaxPipelineDepthcnfMaxEntityLengthcnfMaxOutputChunkLengthcnfDumpTooLateAbortionToStderrcnfExtToMIMEType defaultConfigAbortion aboStatus aboHeaders aboMessageabort abortPurelyabortSTMabortA abortPageFormDatafdName fdFileName fdContentResourcerunRes getConfig getRemoteAddrgetRemoteAddr' getRemoteHostgetRemoteCertificate getRequest getMethod getRequestURIgetRequestVersiongetResourcePath getPathInfo getQueryForm getHeader getAcceptgetAcceptEncodingisEncodingAcceptablegetContentTypegetAuthorization foundEntity foundETagfoundTimeStamp foundNoEntityinputinputLBS inputChunk inputChunkLBS inputForm defaultLimit setStatus setHeaderredirectsetContentType setLocationsetContentEncodingsetWWWAuthenticateoutput outputLBS outputChunkoutputChunkLBSdriftToResTree ResourceDefresUsesNativeThread resIsGreedyresGetresHeadresPostresPut resDeleteFallbackHandler emptyResource mkResTree findResource runResource staticFilehandleStaticFilegenerateETagFromFile staticDirhandleStaticDirrunHttpdfmtIntfmtDecfmtDec2fmtDec3fmtDec4fmtHexpadStr intToChar HandleLikehGetLBShPutLBShGetBShPutBShPutCharhPutStr hPutStrLn hGetPeerCerthFlushhClose SocketLikeHandleaccept socketPortghc-primGHC.BoolTrue ParserStatePSTpstInput pstIsEOFFatal runParserbaseGHC.BasefailGHC.Err undefinedcount'FalsemonthStrweekStr httpDateTimeacceptEncodingListPaccEncPnormalizeCodingunnormalizeCodingorderAcceptEncodings HasHeaders getHeaders setHeaders deleteHeaderNCBSHeaderstoNCBSfromNCBS noCaseCmp noCaseCmp'noCaseEq noCaseEq' emptyHeaders toHeaders mkHeaders fromHeadersheadersP hPutHeaders requestLinePmethodPuriP chunkHeaderP chunkFooterP chunkTrailerP hPutStatusdoesMeetStringcontainers-0.3.0.0Data.MapMapextMapPcompile Data.MaybeJustNothingInteractionQueueInteractionStateDone DecidingBodyDecidingHeader GettingBodyExaminingRequest Interaction itrConfig itrLocalPort itrRemoteAddr itrRemoteCertitrResourcePath itrRequest itrResponseitrRequestHasBodyitrRequestIsChunkeditrExpectedContinueitrReqChunkLengthitrReqChunkRemainingitrReqChunkIsOveritrReqBodyWanteditrReqBodyWasteAllitrReceivedBodyitrWillReceiveBodyitrWillChunkBodyitrWillDiscardBody itrWillClose itrBodyToSend itrBodyIsNullitrStateitrWroteContinueitrWroteHeadernewInteractionQueuedefaultPageContentTypenewInteractionwriteItrreadItrreadItrF updateItr updateItrFgetDefaultPagewriteDefaultPage mkDefaultPagegetMsg GHC.Exception ExceptionGHC.IOunsafePerformIO hxt-8.5.4Control.Arrow.ArrowIOArrowIO ContDispoPartmultipartFormPpartPbodyPpartToFormDatapartName partFileNamegetContDispoFormData getContDispo contDispoP postprocesscompleteUnconditionalHeaderscachegetCurrentDate GHC.TypesIOunResgetInteractionnetwork-2.2.1.7Network.Socket.InternalSockAddrpairToFormData setHeader'ResNode ResSubtreeControl.ConcurrentforkOSGHC.ConcforkIOresponseWriter preprocess requestReader unix-2.4.0.2System.Posix.SignalsinstallHandlersigPIPEIgnore