Provide backend-specific types and use row polymorphism everywhere else
Given that Request includes a backend-specific request object, it might be better to redefine that type via row polymorphism:
newtype Request otherRows
= Request { method :: H.Method
, rawPathInfo :: String
, httpVersion :: H.HttpVersion
, rawQueryString :: String
, requestHeaders :: H.RequestHeaders
, isSecure :: Boolean
, remoteHost :: String
, pathInfo :: Array String
, queryString :: Object String
, body :: Aff (Maybe Buffer)
, bodyLength :: RequestBodyLength
, headerHost :: String
, headerRange :: Maybe String
, headerReferer :: Maybe String
, headerUserAgent :: Maybe String
, rawHeader :: Maybe Buffer
| otherRows
}
newtype RequestNodeJs =
RequestNodeJs (Request (nodeRequest :: Maybe HTTP.Request))
defaultRequest would need to be changed. There's two ways:
- change it to a
RecordBuilderAPI, so that one can build it - specify a backend-specific one for each
Hey @JordanMartinez, I really appreciate having you jump in! The only problem that I have with this approach is that we need to add params to the Request type. I want a solution that avoids end-user having to pass a tag around.
I am looking for a solution that keeps the type very simple without leaking the internal type. End-users should only access it if they know what they are doing.
With the help of @paluh, I was thinking about keeping it simple and go with this approach:
newtype Request
= Request { method :: H.Method
, rawPathInfo :: String
, httpVersion :: H.HttpVersion
, httpType :: String
, rawQueryString :: String
, requestHeaders :: H.RequestHeaders
, isSecure :: Boolean
, remoteHost :: String
, pathInfo :: Array String
, queryString :: Object String
, body :: Aff (Maybe Buffer)
, bodyLength :: RequestBodyLength
, headerHost :: String
, headerRange :: Maybe String
, headerReferer :: Maybe String
, headerUserAgent :: Maybe String
, rawHeader :: Maybe Buffer
, nodeRequest :: Maybe Foreign
}
Have a function like nodeHttpRequest :: Request -> Maybe HTTP.Request which allows one to extract the node request object using the httpType field by pattern matching.
Someone else suggested that I follow Hyper's approach https://github.com/purescript-hyper/hyper/blob/master/src/Hyper/Node/Server.purs#L53-L54
I think @paluh's approach makes sense. On second thought, I don't think it's worth it to try to keep things backend-unspecific yet because we don't yet have strong compiler support for non-JS backends.
Just for a reference (and possible further discussion) I've also proposed this quite lightweight type safe form of extensible existential:
https://try.purescript.org/?gist=d0bff9054bfe49a916365f2b431afa0c