Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d89826b982 | ||
|
|
94350fdde6 | ||
|
|
230eb3630c |
@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file. From versio
|
||||
|
||||
## Unreleased
|
||||
|
||||
## [14.5] - 2026-02-12
|
||||
|
||||
### Added
|
||||
|
||||
- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
|
||||
- Add a `HINT` when the LISTEN channel stops working due to a PostgreSQL bug by @laurenceisla in #4581
|
||||
- Add string slicing operator for `jwt-role-claim-key` by @taimoorzaeem in #4599
|
||||
- Log host, port and pg version of listener database connection by @mkleczek in #4617 #4618
|
||||
- Optimize requests with `Prefer: count=exact` that do not use ranges or `db-max-rows` by @laurenceisla in #3957
|
||||
+ Removed unnecessary double count when building the `Content-Range`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Don't hide async exceptions in logs by @stevechavez in #4646
|
||||
|
||||
### Changed
|
||||
|
||||
- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
|
||||
+ Now fails at startup. Prior to this, it failed with `PGRST205` on requests related to these schemas.
|
||||
|
||||
## [14.4] - 2026-01-29
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -16,7 +16,7 @@ Supported PostgreSQL versions
|
||||
=============================
|
||||
|
||||
=============== =================================
|
||||
**Supported** PostgreSQL >= 12
|
||||
**Supported** PostgreSQL >= 13
|
||||
=============== =================================
|
||||
|
||||
PostgREST works with all PostgreSQL versions still `officially supported <https://www.postgresql.org/support/versioning/>`_.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name: postgrest
|
||||
version: 14.4
|
||||
version: 14.5
|
||||
synopsis: REST API for any Postgres database
|
||||
description: Reads the schema of a PostgreSQL database and creates RESTful routes
|
||||
for tables, views, and functions, supporting all HTTP methods that security
|
||||
|
||||
+26
-4
@@ -9,18 +9,24 @@ Some of its functionality includes:
|
||||
- Producing HTTP Headers according to RFCs.
|
||||
- Content Negotiation
|
||||
-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
module PostgREST.App
|
||||
( postgrest
|
||||
, run
|
||||
) where
|
||||
|
||||
|
||||
import GHC.IO.Exception (IOErrorType (..))
|
||||
import System.IO.Error (ioeGetErrorType)
|
||||
|
||||
import Control.Monad.Except (liftEither)
|
||||
import Data.Either.Combinators (mapLeft, whenLeft)
|
||||
import Data.Maybe (fromJust)
|
||||
import Data.String (IsString (..))
|
||||
import Network.Wai.Handler.Warp (defaultSettings, setHost, setPort,
|
||||
import Network.Wai.Handler.Warp (defaultSettings, setHost,
|
||||
setOnException, setPort,
|
||||
setServerName)
|
||||
|
||||
import qualified Data.Text.Encoding as T
|
||||
@@ -63,7 +69,6 @@ type Handler = ExceptT Error
|
||||
|
||||
run :: AppState -> IO ()
|
||||
run appState = do
|
||||
let observer = AppState.getObserver appState
|
||||
conf@AppConfig{..} <- AppState.getConfig appState
|
||||
|
||||
AppState.schemaCacheLoader appState -- Loads the initial SchemaCache
|
||||
@@ -79,7 +84,24 @@ run appState = do
|
||||
address <- resolveSocketToAddress (AppState.getSocketREST appState)
|
||||
observer $ AppServerAddressObs address
|
||||
|
||||
Warp.runSettingsSocket (serverSettings conf) (AppState.getSocketREST appState) app
|
||||
Warp.runSettingsSocket (serverSettings conf & setOnException onWarpException) (AppState.getSocketREST appState) app
|
||||
where
|
||||
observer = AppState.getObserver appState
|
||||
|
||||
onWarpException :: Maybe Wai.Request -> SomeException -> IO ()
|
||||
onWarpException _ ex =
|
||||
when (shouldDisplayException ex) $
|
||||
observer $ WarpErrorObs $ show ex
|
||||
|
||||
-- Similar to wai defaultShouldDisplayException in
|
||||
-- https://github.com/yesodweb/wai//blob/8c3882c60f6abe043889fc20c7efd3fa9747fa4a/warp/Network/Wai/Handler/Warp/Settings.hs#L251-L258
|
||||
-- but without omitting AsyncException since it's important to log for ThreadKilled, StackOverflow and other cases.
|
||||
-- We want to reuse this to avoid flooding the logs for some transient failure cases.
|
||||
shouldDisplayException :: SomeException -> Bool
|
||||
shouldDisplayException se
|
||||
| Just (_ :: Warp.InvalidRequest) <- fromException se = False
|
||||
| Just (ioeGetErrorType -> et) <- fromException se, et == ResourceVanished || et == InvalidArgument = False
|
||||
| otherwise = True
|
||||
|
||||
serverSettings :: AppConfig -> Warp.Settings
|
||||
serverSettings AppConfig{..} =
|
||||
|
||||
@@ -63,6 +63,7 @@ data Observation
|
||||
| PoolRequestFullfilled
|
||||
| JwtCacheLookup Bool
|
||||
| JwtCacheEviction
|
||||
| WarpErrorObs Text
|
||||
|
||||
data ObsFatalError = ServerAuthError | ServerPgrstBug | ServerError42P05 | ServerError08P01
|
||||
|
||||
@@ -157,6 +158,8 @@ observationMessage = \case
|
||||
"Looked up a JWT in JWT cache"
|
||||
JwtCacheEviction ->
|
||||
"Evicted entry from JWT cache"
|
||||
WarpErrorObs txt ->
|
||||
"Warp server error: " <> txt
|
||||
where
|
||||
showMillis :: Double -> Text
|
||||
showMillis x = toS $ showFFloat (Just 1) x ""
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import re
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from postgrest import run
|
||||
|
||||
@@ -54,6 +55,25 @@ def test_openapi_in_big_schema(defaultenv):
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_stackoverflow_is_logged(defaultenv):
|
||||
"Stack overflow errors should be logged with the Warp error message"
|
||||
|
||||
env = {
|
||||
**defaultenv,
|
||||
"PGRST_DB_SCHEMAS": "apflora",
|
||||
"PGRST_DB_ANON_ROLE": "postgrest_test_anonymous",
|
||||
}
|
||||
|
||||
with run(env=env, wait_max_seconds=30, no_startup_stdout=False) as postgrest:
|
||||
with pytest.raises(requests.exceptions.ConnectionError):
|
||||
postgrest.session.get("/")
|
||||
|
||||
output = postgrest.read_stdout(nlines=10)
|
||||
output.extend(postgrest.read_stdout(nlines=10))
|
||||
|
||||
assert any("Warp server error: stack overflow" in line for line in output)
|
||||
|
||||
|
||||
# See: https://github.com/PostgREST/postgrest/issues/3329
|
||||
def test_should_not_fail_with_stack_overflow(defaultenv):
|
||||
"requesting a non-existent relationship should not fail with stack overflow due to fuzzy search of candidates"
|
||||
|
||||
Reference in New Issue
Block a user