-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Native webserver that acts as a library. -- -- This package is a native implementation of the HTTP and HTTPS -- protocols. It lives as a library, exporting an interface reminiscent -- of CGI or FastCGI. Thus policy on how namespace is mapped to files -- and/or scripts is entirely up to the client application. -- -- This package is partially compatible with direct-fastcgi by the same -- author, but is intended more by way of a replacement for it than a -- companion to it, and makes several design decisions differently. The -- biggest is the use of MonadControlBase for exceptions. -- -- @package direct-http @version 0.5.3 -- | This module provides facilities for implementing webservers, in a -- servelet-like style. The general philosophy is that direct-http makes -- as few decisions as possible for the user code, allowing such things -- as URL routing and virtual-host policies to be implemented in any -- desired fashion. It focuses on providing a robust transport layer -- which can integrate well with any higher layer. module Network.HTTP -- | The monad within which each single request from a client is handled. -- -- Note that there is an instance MonadBaseControl IO -- HTTP, so that exceptions can be thrown, caught, and otherwise -- manipulated with the lifted primitives from lifted-base's -- Lifted. type HTTP = ReaderT HTTPState IO -- | An opaque type representing the state of the HTTP server during a -- single connection from a client. data HTTPState -- | The class of monads within which the HTTP calls are valid. You may -- wish to create your own monad implementing this class. Note that the -- prerequisite is MonadBaseControl IO m, which is similar -- to MonadIO m, but with, among other things, more capability for -- exception handling. class MonadBaseControl IO m => MonadHTTP m getHTTPState :: MonadHTTP m => m HTTPState -- | A record used to configure the server. Broken informally into the four -- categories of logging, job-control, concurrency, and networking. For -- logging, the configuration contains optional paths to files for the -- access and error logs (if these are omitted, logging is not done). For -- job-control, it contains a flag indicating whether to run as a daemon, -- and optionally the names of a Unix user and/or group to switch to in -- the process of daemonization. For concurrency, it contains a forking -- primitive such as forkIO or forkOS. Finally, for -- networking, it contains a list of parameters for ports to listen on, -- each of which has its own sub-configuration record. -- -- Notice that checking the value of the Host: header, and implementing -- virtual-host policies, is not done by direct-http but rather is up to -- the user of the library; hence, there is no information in the -- configuration about the hostnames to accept from the user-agent. -- -- If the access logfile path is not Nothing, acceptLoop opens -- this logfile in append mode and uses it to log all accesses; -- otherwise, access is not logged. -- -- If the error logfile path is not Nothing, acceptLoop opens this -- logfile in append mode and uses it to log all errors; otherwise, if -- not daemonizing, errors are logged to standard output; if daemonizing, -- errors are not logged. -- -- If the daemonize flag is True, acceptLoop closes the standard -- IO streams and moves the process into the background, doing all the -- usual Unix things to make it run as a daemon henceforth. This is -- optional because it might be useful to turn it off for debugging -- purposes. -- -- The forking primitive is typically either forkIO or -- forkOS, and is used by acceptLoop both to create -- listener threads, and to create connection threads. It is valid to use -- a custom primitive, such as one that attempts to pool OS threads, but -- it must actually provide concurrency - otherwise there will be a -- deadlock. There is no support for single-threaded operation. -- -- Notice that we take the forking primitive in terms of IO, even -- though we actually lift it (with liftBaseDiscard). This is -- because lifted-base, as of this writing and its version 0.1.1, only -- supports forkIO and not forkOS. -- -- The loop never returns, but will terminate the program with status 0 -- if and when it ever has no child threads alive; child threads for this -- purpose are those created through httpFork, which means all -- listener-socket and connection threads created by acceptLoop, -- as well as any threads created by client code through httpFork, -- but not threads created by client code through other mechanisms. -- -- The author of direct-http has made no effort to implement custom -- thread-pooling forking primitives, but has attempted not to preclude -- them. If anyone attempts to implement such a thing, feedback is hereby -- solicited. data HTTPServerParameters HTTPServerParameters :: Maybe FilePath -> Maybe FilePath -> Bool -> Maybe String -> Maybe String -> (IO () -> IO ThreadId) -> [HTTPListenSocketParameters] -> HTTPServerParameters serverParametersAccessLogPath :: HTTPServerParameters -> Maybe FilePath serverParametersErrorLogPath :: HTTPServerParameters -> Maybe FilePath serverParametersDaemonize :: HTTPServerParameters -> Bool serverParametersUserToChangeTo :: HTTPServerParameters -> Maybe String serverParametersGroupToChangeTo :: HTTPServerParameters -> Maybe String serverParametersForkPrimitive :: HTTPServerParameters -> IO () -> IO ThreadId serverParametersListenSockets :: HTTPServerParameters -> [HTTPListenSocketParameters] -- | A record used to configure an individual port listener and its socket -- as part of the general server configuration. Consists of a host -- address and port number to bind the socket to, and a flag indicating -- whether the listener should use the secure version of the protocol. data HTTPListenSocketParameters HTTPListenSocketParameters :: SockAddr -> Bool -> HTTPListenSocketParameters listenSocketParametersAddress :: HTTPListenSocketParameters -> SockAddr listenSocketParametersSecure :: HTTPListenSocketParameters -> Bool -- | Takes a server parameters record and a handler, and concurrently -- accepts requests from user agents, forking with the primitive -- specified by the parameters and invoking the handler in the forked -- thread inside the HTTP monad for each request. -- -- Note that although there is no mechanism to substitute another type of -- monad for HTTP, you can enter your own monad within the handler, much -- as you would enter your own monad within IO. You simply have to -- implement the MonadHTTP class. -- -- Any exceptions not caught within the handler are caught by -- acceptLoop, and cause the termination of that handler, but not -- of the connection or the accept loop. acceptLoop :: HTTPServerParameters -> (HTTP ()) -> IO () -- | Logs a message using the web server's logging facility, prefixed with -- a timestamp. httpLog :: MonadHTTP m => String -> m () -- | Forks a thread to run the given action, using the forking primitive -- that was passed in the configuration to acceptLoop, and -- additionally registers that thread with the main server thread, which -- has the sole effect and purpose of causing the server to not exit -- until and unless the child thread does. All of the listener-socket and -- connection threads created by the server go through this function. httpFork :: MonadHTTP m => m () -> m ThreadId -- | An exception originating within the HTTP infrastructure or the web -- server. data HTTPException -- | An exception thrown by operations which require the response headers -- not to have been sent yet. ResponseHeadersAlreadySent :: HTTPException -- | An exception thrown by operations which require the response headers -- to still be modifiable. ResponseHeadersNotModifiable :: HTTPException -- | An exception thrown by operations which produce output when output has -- been closed, as by httpCloseOutput. OutputAlreadyClosed :: HTTPException -- | An exception thrown when output is closed, as by -- httpCloseOutput, when the response headers imply that there -- will be a certain amount of data and there is not. OutputIncomplete :: HTTPException -- | An exception thrown by operations which are given a header that does -- not meet their requirement of being valid in a response. NotAResponseHeader :: Header -> HTTPException -- | An exception thrown by operations which are given cookie names that do -- not meet the appropriate syntax requirements. CookieNameInvalid :: String -> HTTPException -- | An exception thrown by operations which expect a connection to exist -- (as it always does within a handler), when none does. NoConnection :: HTTPException -- | Headers are classified by HTTP/1.1 as request headers, response -- headers, entity headers, or general headers. data Header -- | Request headers HttpAccept :: Header HttpAcceptCharset :: Header HttpAcceptEncoding :: Header HttpAcceptLanguage :: Header HttpAuthorization :: Header HttpExpect :: Header HttpFrom :: Header HttpHost :: Header HttpIfMatch :: Header HttpIfModifiedSince :: Header HttpIfNoneMatch :: Header HttpIfRange :: Header HttpIfUnmodifiedSince :: Header HttpMaxForwards :: Header HttpProxyAuthorization :: Header HttpRange :: Header HttpReferrer :: Header HttpTE :: Header HttpUserAgent :: Header -- | Response headers HttpAcceptRanges :: Header HttpAge :: Header HttpETag :: Header HttpLocation :: Header HttpProxyAuthenticate :: Header HttpRetryAfter :: Header HttpServer :: Header HttpVary :: Header HttpWWWAuthenticate :: Header -- | Entity headers HttpAllow :: Header HttpContentEncoding :: Header HttpContentLanguage :: Header HttpContentLength :: Header HttpContentLocation :: Header HttpContentMD5 :: Header HttpContentRange :: Header HttpContentType :: Header HttpExpires :: Header HttpLastModified :: Header HttpExtensionHeader :: ByteString -> Header -- | General headers HttpCacheControl :: Header HttpConnection :: Header HttpDate :: Header HttpPragma :: Header HttpTrailer :: Header HttpTransferEncoding :: Header HttpUpgrade :: Header HttpVia :: Header HttpWarning :: Header -- | Nonstandard headers HttpCookie :: Header HttpSetCookie :: Header -- | Queries the value from the user agent of the given HTTP/1.1 header. If -- the header is to be provided after the content as specified by the -- Trailer header, this is potentially time-consuming. getRequestHeader :: MonadHTTP m => Header -> m (Maybe String) -- | Returns an association list of name-value pairs of all the HTTP/1.1 -- request or entity headers from the user agent. If some of these -- headers are to be provided after the content as specified by the -- Trailer header, this is potentially time-consuming. getAllRequestHeaders :: MonadHTTP m => m [(Header, String)] -- | An object representing a cookie (a small piece of information, mostly -- metadata, stored by a user-agent on behalf of the server), either one -- received as part of the request or one to be sent as part of the -- response. data Cookie Cookie :: String -> String -> Int -> Maybe String -> Maybe String -> Maybe Int -> Bool -> Maybe String -> Cookie cookieName :: Cookie -> String cookieValue :: Cookie -> String cookieVersion :: Cookie -> Int cookiePath :: Cookie -> Maybe String cookieDomain :: Cookie -> Maybe String cookieMaxAge :: Cookie -> Maybe Int cookieSecure :: Cookie -> Bool cookieComment :: Cookie -> Maybe String -- | Returns a Cookie object for the given name, if the user agent -- provided one in accordance with RFC 2109. getCookie :: MonadHTTP m => String -> m (Maybe Cookie) -- | Returns all Cookie objects provided by the user agent in -- accordance RFC 2109. getAllCookies :: MonadHTTP m => m [Cookie] -- | A convenience method; as getCookie, but returns only the value -- of the cookie rather than a Cookie object. getCookieValue :: MonadHTTP m => String -> m (Maybe String) -- | Return the remote address, which includes both host and port -- information. They are provided in the aggregate like this because it -- is the most internet-protocol-agnostic representation. getRemoteAddress :: MonadHTTP m => m SockAddr -- | Return the request method. getRequestMethod :: MonadHTTP m => m String -- | Return the request URI. getRequestURI :: MonadHTTP m => m String -- | Return the server address and port, as a SockAddr. Useful for -- implementing virtual-hosting policies. getServerAddress :: MonadHTTP m => m SockAddr -- | Return the request content length, if this is knowable without -- actually receiving the content - in particular, if the Content-Length -- header was used. Otherwise, returns Nothing. getContentLength :: MonadHTTP m => m (Maybe Int) -- | Return the request content type, as provided by the user agent. getContentType :: MonadHTTP m => m (Maybe String) -- | Reads up to a specified amount of data from the content of the HTTP -- request, if any, and interprets it as binary data. If input has been -- closed, returns an empty bytestring. If no input is immediately -- available, blocks until there is some. If output has been closed, -- causes an OutputAlreadyClosed exception. httpGet :: MonadHTTP m => Int -> m ByteString -- | Reads up to a specified amount of data from the content of the HTTP -- request, if any, and interprets it as binary data. If input has been -- closed, returns an empty bytestring. If insufficient input is -- available, returns any input which is immediately available, or an -- empty bytestring if there is none, never blocking. If output has been -- closed, causes an OutputAlreadyClosed exception. httpGetNonBlocking :: MonadHTTP m => Int -> m ByteString -- | Reads all remaining data from the content of the HTTP request, if any, -- and interprets it as binary data. Blocks until all input has been -- read. If input has been closed, returns an empty bytestring. If output -- has been closed, causes an OutputAlreadyClosed exception. httpGetContents :: MonadHTTP m => m ByteString -- | Returns whether the content of the HTTP request potentially has data -- remaining, either in the buffer or yet to be read. httpIsReadable :: MonadHTTP m => m Bool -- | Sets the response status which will be sent with the response headers. -- If the response headers have already been sent, or are no longer -- modifiable (because of a call to httpPut or similar), causes a -- ResponseHeadersAlreadySent or -- ResponseHeadersNotModifiable exception. setResponseStatus :: MonadHTTP m => Int -> m () -- | Returns the response status which will be or has been sent with the -- response headers. getResponseStatus :: MonadHTTP m => m Int -- | Sets the given response header to the given string value, overriding -- any value which has previously been set. If the response headers have -- already been sent, or are no longer modifiable (because of a call to -- httpPut or similar), causes a ResponseHeadersAlreadySent -- or ResponseHeadersNotModifiable exception. If the header is not -- an HTTP/1.1 or extension response, entity, or general header, ie, is -- not valid as part of a response, causes a NotAResponseHeader -- exception. -- -- If a value is set for the HttpSetCookie header, this overrides -- all cookies set for this request with setCookie. setResponseHeader :: MonadHTTP m => Header -> String -> m () -- | Causes the given Header response header not to be sent, -- overriding any value which has previously been set. If the response -- headers have already been sent, or are no longer modifiable (because -- of a call to httpPut or similar), causes a -- ResponseHeadersAlreadySent or -- ResponseHeadersNotModifiable exception. If the header is not an -- HTTP/1.1 or extension response or entity header, ie, is not valid as -- part of a response, causes a NotAResponseHeader exception. -- -- Does not prevent the HttpSetCookie header from being sent if -- cookies have been set for this request with setCookie. unsetResponseHeader :: MonadHTTP m => Header -> m () -- | Returns the value of the given header which will be or has been sent -- with the response headers. If the header is not an HTTP/1.1 or -- extension response, entity, or general header, ie, is not valid as -- part of a response, causes a NotAResponseHeader exception. getResponseHeader :: MonadHTTP m => Header -> m (Maybe String) -- | Causes the user agent to record the given cookie and send it back with -- future loads of this page. Does not take effect instantly, but rather -- when headers are sent. Cookies are set in accordance with RFC 2109. If -- an HttpCookie header is set for this request by a call to -- setResponseHeader, this function has no effect. If the response -- headers have already been sent, or are no longer modifiable (because -- of a call to httpPut or similar), causes a -- ResponseHeadersAlreadySent or -- ResponseHeadersNotModifiable exception. If the name is not a -- possible name for a cookie, causes a CookieNameInvalid -- exception. setCookie :: MonadHTTP m => Cookie -> m () -- | Causes the user agent to unset any cookie applicable to this page with -- the given name. Does not take effect instantly, but rather when -- headers are sent. If an HttpCookie header is set for this -- request by a call to setResponseHeader, this function has no -- effect. If the response headers have already been sent, or are no -- longer modifiable (because of a call to httpPut or similar), -- causes a ResponseHeadersAlreadySent or -- ResponseHeadersNotModifiable exception. If the name is not a -- possible name for a cookie, causes a CookieNameInvalid -- exception. unsetCookie :: MonadHTTP m => String -> m () -- | Constructs a cookie with the given name and value. Version is set to -- 1; path, domain, and maximum age are set to Nothing; and the -- secure flag is set to False. Constructing the cookie does not -- cause it to be set; to do that, call setCookie on it. mkSimpleCookie :: String -> String -> Cookie -- | Constructs a cookie with the given parameters. Version is set to 1. -- Constructing the cookie does not cause it to be set; to do that, call -- setCookie on it. mkCookie :: String -> String -> (Maybe String) -> (Maybe String) -> (Maybe Int) -> Bool -> Cookie -- | Sets the HTTP/1.1 return status to 301 and sets the -- HttpLocation header to the provided URL. This has the effect of -- issuing a permanent redirect to the user agent. Permanent redirects, -- as opposed to temporary redirects, may cause bookmarks or incoming -- links to be updated. If the response headers have already been sent, -- or are no longer modifiable (because of a call to httpPut or -- similar), causes a ResponseHeadersAlreadySent or -- ResponseHeadersNotModifiable exception. permanentRedirect :: MonadHTTP m => String -> m () -- | Sets the HTTP/1.1 return status to 303 and sets the -- HttpLocation header to the provided URL. This has the effect of -- issuing a see-other or temporary redirect to the user agent. -- Temporary redirects, as opposed to permanent redirects, do not cause -- bookmarks or incoming links to be updated. If the response headers -- have already been sent, or are no longer modifiable (because of a call -- to httpPut or similar), causes a -- ResponseHeadersAlreadySent or -- ResponseHeadersNotModifiable exception. seeOtherRedirect :: MonadHTTP m => String -> m () -- | Ensures that the response headers have been sent. If they are already -- sent, does nothing. If output has already been closed, causes an -- OutputAlreadyClosed exception. Note that if the buffered -- identity output mode (the first mode of operation described for -- httpPut) is to be used, this function implies that there is no -- additional content beyond what has already been sent. sendResponseHeaders :: MonadHTTP m => m () -- | Returns whether the response headers have been sent, regardless of -- whether they are modifiable (they might not be because of a call to -- httpPut or similar). responseHeadersSent :: MonadHTTP m => m Bool -- | Returns whether the response headers are modifiable, a prerequisite of -- which is that they have not already been sent. (They might not be -- modifiable because of a call to httpPut or similar.) responseHeadersModifiable :: MonadHTTP m => m Bool -- | Appends data, interpreted as binary, to the content of the HTTP -- response. Makes the response headers no longer modifiable, effective -- immediately. If output has already been closed, causes an -- OutputAlreadyClosed exception. If the response -- Transfer-Encoding as set in the response headers is identity or -- omitted, and the response Content-Length is omitted, data is buffered -- until output is closed, then sent all at once with an appropriate -- Content-Length header. Otherwise - that is, if there is a -- Transfer-Encoding other than identity set, or if Content-Length -- is set - data is sent immediately. If Content-Length is set, and the -- provided data would cause the cumulative data sent to exceed that -- length, causes an OutputAlreadyClosed exception. At the time -- that data is actually sent, if the response headers have not been -- sent, first sends them. -- -- In other words, there are effectively three modes of operation for -- output. The first, simplest mode is used if the handler does nothing -- special. In this mode output is buffered and sent all at once; headers -- are not sent until this time. In this mode httpCloseOutput may -- be useful to force output to be sent before the handler returns, -- perhaps so that additional time-consuming processing can be done. This -- mode is easiest to use, in the sense that it requires no support on -- the handler's part, but probably the second mode should always be used -- instead. -- -- The second mode is used if the handler sets a Transfer-Encoding, for -- example chunked, and no Content-Length. In this case headers -- are sent immediately upon the first httpPut or -- httpPutStr, and output is sent as it is provided. Output in -- this mode is transformed by httpPut into the appropriate -- transfer encoding. Thus handler code need only specify a transfer -- encoding, not actually implement that encoding itself. This mode is -- advantageous to allow user agents to begin displaying partial content -- as it is received, and particularly useful when the content is quite -- large or takes significant time to generate. If you are unsure which -- mode to use, it should probably be this one. -- -- The third mode is used if the handler sets a Content-Length and no -- Transfer-Encoding. In this case headers are again sent immediately -- upon the first httpPut or httpPutStr, and output is -- again sent as it is provided. Output in this mode is not transformed. -- This may be more efficient than the second mode if output is generated -- in many small pieces, as it avoids computing and sending the length -- tags of the chunked encoding. However, it requires the content -- length to be known in advance of actually sending any content. It may -- be useful if you wish to have direct-http validate that the handler is -- well-behaved in sending a binary object of known size with no -- garbage inserted by spurious additional puts. httpPut :: MonadHTTP m => ByteString -> m () -- | Appends text, encoded as UTF8, to the content of the HTTP response. In -- all respects this behaves as httpPut, but for the fact that it -- takes text rather than binary data. httpPutStr :: MonadHTTP m => String -> m () -- | Informs the web server and the user agent that the request has -- completed. As side-effects, the response headers are sent if they have -- not yet been, any unread input is discarded and no more can be read, -- and any unsent output is sent. This is implicitly called, if it has -- not already been, after the handler returns; it may be useful within a -- handler if the handler wishes to return results and then perform -- time-consuming computations before exiting. If output has already been -- closed, causes an OutputAlreadyClosed exception. If the -- response headers imply that there will be a certain amount of data and -- there is not, causes an OutputIncomplete exception. httpCloseOutput :: MonadHTTP m => m () -- | Returns whether it is possible to write more data; ie, whether output -- has not yet been closed as by httpCloseOutput. httpIsWritable :: MonadHTTP m => m Bool instance Typeable ConnectionTerminatingError instance Typeable HTTPException instance Show Cookie instance Eq Header instance Ord Header instance Eq HeaderType instance Show HeaderType instance Show HTTPException instance Exception HTTPException instance Show Header instance MonadHTTP HTTP instance Show ConnectionTerminatingError instance Exception ConnectionTerminatingError