packages feed

chu2-2012.11.18: src/Chu2.agda

module Chu2 where

open import Data.List using (List; [_])
open import Chu2.ByteString using (ByteString; pack; empty)
open import Foreign.Haskell using (Unit)
open import IO.Primitive using (IO)

data Tuple (A : Set)(B : Set) : Set where
    _,_ : A → B → Tuple A B


{-# IMPORT Chu2.FFI #-}
{-# COMPILED_DATA Tuple (,) (,) #-}

Header = Tuple ByteString ByteString

Headers = List Header

data RequestMethod : Set where
  OPTIONS   : RequestMethod
  GET       : RequestMethod
  HEAD      : RequestMethod
  POST      : RequestMethod
  PUT       : RequestMethod
  DELETE    : RequestMethod
  TRACE     : RequestMethod
  CONNECT   : RequestMethod
  

{-# COMPILED_DATA RequestMethod Chu2.FFI.RequestMethod
    Chu2.FFI.OPTIONS
    Chu2.FFI.GET
    Chu2.FFI.HEAD
    Chu2.FFI.POST
    Chu2.FFI.PUT
    Chu2.FFI.DELETE
    Chu2.FFI.TRACE
    Chu2.FFI.CONNECT
#-}

data Chu2UrlScheme : Set where
  HTTP HTTPS : Chu2UrlScheme
  
{-# COMPILED_DATA Chu2UrlScheme Chu2.FFI.Chu2UrlScheme
    Chu2.FFI.HTTP
    Chu2.FFI.HTTPS
#-}

ScriptName    =  ByteString
PathInfo      =  ByteString
QueryString   =  ByteString
ServerName    =  ByteString
ServerPort    =  ByteString
HttpHeaders   =  Headers
Chu2Input     =  ByteString
Chu2Errors    =  ByteString → IO Unit
Chu2Headers   =  Headers

private
  data EnvData : Set where
    envData : 
        RequestMethod  
      → ScriptName     
      → PathInfo       
      → QueryString    
      → ServerName     
      → ServerPort     
      → HttpHeaders    
      → Chu2UrlScheme  
      → Chu2Input      
      → Chu2Errors     
      → Chu2Headers   
      → EnvData

  {-# COMPILED_DATA EnvData Chu2.FFI.Env Chu2.FFI.Env #-}

record Env : Set where
  constructor env
  field
    requestMethod  : RequestMethod  
    scriptName     : ScriptName     
    pathInfo       : PathInfo       
    queryString    : QueryString    
    serverName     : ServerName     
    serverPort     : ServerPort     
    httpHeaders    : HttpHeaders    
    chu2UrlScheme  : Chu2UrlScheme  
    chu2Input      : Chu2Input      
    chu2Errors     : Chu2Errors     
    chu2Headers    : Chu2Headers   
    

private
  envDataToEnv : EnvData → Env
  envDataToEnv
    ( envData
        requestMethod  
        scriptName     
        pathInfo       
        queryString    
        serverName     
        serverPort     
        httpHeaders    
        chu2UrlScheme  
        chu2Input      
        chu2Errors     
        chu2Headers    
    ) =
  
    env
      requestMethod  
      scriptName     
      pathInfo       
      queryString    
      serverName     
      serverPort     
      httpHeaders    
      chu2UrlScheme  
      chu2Input      
      chu2Errors     
      chu2Headers    


  envToEnvData : Env → EnvData
  envToEnvData
    ( env
        requestMethod  
        scriptName     
        pathInfo       
        queryString    
        serverName     
        serverPort     
        httpHeaders    
        chu2UrlScheme  
        chu2Input      
        chu2Errors     
        chu2Headers    
    ) =
  
    envData
      requestMethod  
      scriptName     
      pathInfo       
      queryString    
      serverName     
      serverPort     
      httpHeaders    
      chu2UrlScheme  
      chu2Input      
      chu2Errors     
      chu2Headers  

data Status : Set where
  OK                        : Status
  Created                   : Status
  Accepted                  : Status
  NoContent                 : Status
  MultipleChoices           : Status
  MovedPermanently          : Status
  SeeOther                  : Status
  NotModified               : Status
  MovedTemporarily          : Status
  BadRequest                : Status
  Unauthorized              : Status
  Forbidden                 : Status
  NotFound                  : Status
  MethodNotAllowed          : Status
  NotAcceptable             : Status
  Conflict                  : Status
  Gone                      : Status
  PreconditionFailed        : Status
  RequestEntityTooLarge     : Status
  RequestURItooLong         : Status
  UnsupportedMediaType      : Status
  NotImplemented            : Status
  ServiceUnavailable        : Status

{-# COMPILED_DATA Status Chu2.FFI.Status
  Chu2.FFI.OK
  Chu2.FFI.Created
  Chu2.FFI.Accepted
  Chu2.FFI.NoContent
  Chu2.FFI.MultipleChoices
  Chu2.FFI.MovedPermanently
  Chu2.FFI.SeeOther
  Chu2.FFI.NotModified
  Chu2.FFI.MovedTemporarily
  Chu2.FFI.BadRequest
  Chu2.FFI.Unauthorized
  Chu2.FFI.Forbidden
  Chu2.FFI.NotFound
  Chu2.FFI.MethodNotAllowed
  Chu2.FFI.NotAcceptable
  Chu2.FFI.Conflict
  Chu2.FFI.Gone
  Chu2.FFI.PreconditionFailed
  Chu2.FFI.RequestEntityTooLarge
  Chu2.FFI.RequestURItooLong
  Chu2.FFI.UnsupportedMediaType
  Chu2.FFI.NotImplemented
  Chu2.FFI.ServiceUnavailable
#-}

Body = ByteString

private
  data ResponseData : Set where
    responseData : 
        Status
      → Headers
      → Body
      → ResponseData

  {-# COMPILED_DATA ResponseData Chu2.FFI.Response Chu2.FFI.Response #-}


record Response : Set where
  constructor response
  field
    status  : Status
    headers : Headers
    body    : Body

private
  responseToResponseData : Response → ResponseData
  responseToResponseData 
    ( response
        status
        headers
        body
    ) =
  
    responseData
      status
      headers
      body
    

  responseDataToResponse : ResponseData → Response
  responseDataToResponse 
    ( responseData
        status
        headers
        body
    ) =
  
    response
      status
      headers
      body 
    
defaultResponse : Response
defaultResponse = 
  record
    {
      status = OK
    ; headers = [(pack "Content-Type", pack "text/plain")]
    ; body = pack "Chu2!"
    }

Application = Env → IO Response
Middleware = Application → Application

private
  RawApplication = EnvData → IO ResponseData

RawMiddleware = RawApplication → RawApplication

private
  open IO.Primitive using (_>>=_; return)
  applicationToRawApplication : Application → RawApplication
  applicationToRawApplication app = 
    λ aEnvData → app (envDataToEnv aEnvData) >>= λ aResponse → return (responseToResponseData aResponse)

  rawApplicationToApplication : RawApplication → Application
  rawApplicationToApplication rawApp = 
    λ aEnv → rawApp (envToEnvData aEnv) >>= λ aRawResponse → return (responseDataToResponse aRawResponse)


Handler = Application → IO Unit
RawHandler = RawApplication → IO Unit

open import Function using (_∘_; _$_; id)


rawHandlerToHandler : RawHandler → Handler
rawHandlerToHandler h = h ∘ applicationToRawApplication



rawMiddlewareToMiddleware : RawMiddleware → Middleware
rawMiddlewareToMiddleware r app = rawApplicationToApplication $ r $ applicationToRawApplication app