Use read-only transaction mode for read requests (#561)

* Make middleware use ApiRequest rather than Request

* Fix outdated comments

* Use read-only transaction mode for read requests

This allows API requests against read replicas
This commit is contained in:
Joe Nelson
2016-04-15 12:26:40 -07:00
parent eae5857d0e
commit 5aadfba84b
4 changed files with 65 additions and 52 deletions
+6 -12
View File
@@ -5,13 +5,12 @@ module PostgREST.Middleware where
import Data.Aeson (Value (..))
import qualified Data.HashMap.Strict as M
import Data.Maybe (fromMaybe)
import Data.String.Conversions (cs)
import Data.Text
import Data.Time.Clock (NominalDiffTime)
import qualified Hasql.Transaction as H
import Network.HTTP.Types.Header (hAccept, hAuthorization)
import Network.HTTP.Types.Header (hAccept)
import Network.HTTP.Types.Status (status400, status415)
import Network.Wai (Application, Request (..),
Response, requestHeaders)
@@ -19,7 +18,7 @@ import Network.Wai.Middleware.Cors (cors)
import Network.Wai.Middleware.Gzip (def, gzip)
import Network.Wai.Middleware.Static (only, staticPolicy)
import PostgREST.ApiRequest (pickContentType)
import PostgREST.ApiRequest (ApiRequest(..), pickContentType)
import PostgREST.Auth (jwtClaims, claimsToSQL)
import PostgREST.Config (AppConfig (..), corsPolicy)
import PostgREST.Error (errResponse)
@@ -27,26 +26,21 @@ import PostgREST.Error (errResponse)
import Prelude hiding (concat, null)
runWithClaims :: AppConfig -> NominalDiffTime ->
(Request -> H.Transaction Response) ->
Request -> H.Transaction Response
(ApiRequest -> H.Transaction Response) ->
ApiRequest -> H.Transaction Response
runWithClaims conf time app req = do
let tokenStr = case split (== ' ') (cs auth) of
("Bearer" : t : _) -> t
_ -> ""
eClaims = jwtClaims jwtSecret tokenStr time
let eClaims = jwtClaims jwtSecret (iJWT req) time
case eClaims of
Left e -> clientErr e
Right claims ->
if M.null claims && not (null tokenStr)
if M.null claims && not (null $ iJWT req)
then clientErr "Invalid JWT"
else do
-- role claim defaults to anon if not specified in jwt
H.sql . mconcat . claimsToSQL $ M.union claims (M.singleton "role" anon)
app req
where
hdrs = requestHeaders req
jwtSecret = configJwtSecret conf
auth = fromMaybe "" $ lookup hAuthorization hdrs
anon = String . cs $ configAnonRole conf
clientErr = return . errResponse status400