Skip to content

Commit

Permalink
fix: incorrect parsing 4 fallback_application_name
Browse files Browse the repository at this point in the history
  • Loading branch information
steve-chavez committed Sep 29, 2023
1 parent cf7ee67 commit 55e43bf
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #2846, Fix error when requesting `Prefer: count=<type>` and doing null filtering on embedded resources - @laurenceisla
- #2959, Fix setting `default_transaction_isolation` unnecessarily - @steve-chavez
- #2929, Fix arrow filtering on RPC returning dynamic TABLE with composite type - @steve-chavez
- #2970, Fix incorrect URI parsing for adding `fallback_application_name` - @steve-chavez

## [11.2.0] - 2023-08-10

Expand Down
10 changes: 9 additions & 1 deletion nix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ To build PostgREST from your local checkout of the repository, run:

```bash
$ nix-build --attr postgrestPackage

```

This will create a `result` directory that contains the PostgREST binary at
Expand All @@ -22,6 +21,15 @@ build the `postgrestPackage` attribute from the Nix expression it finds in our
`default.nix` (see below for details). Nix will take care of getting the right
GHC version and all the build dependencies.

You can also build a statically linked binary with:

```bash
$ nix-build --attr postgrestStatic

$ ldd result/bin/postgrest
$ not a dynamic executable
```

## Binary cache

We recommend that you use the PostgREST binary cache on
Expand Down
31 changes: 21 additions & 10 deletions src/PostgREST/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ import Data.List.NonEmpty (fromList, toList)
import Data.Maybe (fromJust)
import Data.Scientific (floatingOrInteger)
import Network.URI (escapeURIString,
isUnescapedInURIComponent, parseURI,
uriQuery)
isUnescapedInURIComponent)
import Numeric (readOct, showOct)
import System.Environment (getEnvironment)
import System.Posix.Types (FileMode)
Expand Down Expand Up @@ -472,6 +471,8 @@ readPGRSTEnvironment =
M.map T.pack . M.fromList . filter (isPrefixOf "PGRST_" . fst) <$> getEnvironment

-- | Adds a `fallback_application_name` value to the connection string. This allows querying the PostgREST version on pg_stat_activity.
-- | This follows the same logic as libpq for parsing the URI https://github.com/postgres/postgres/blob/a829b704015104f49a11ea007957ef03a03dc0d4/src/interfaces/libpq/fe-connect.c#L5880-L5921
-- | If there's a postgres URI scheme designator prefix ("postgres://") then the connstring is considered an URI, if not, it's in key/value format.
--
-- >>> let ver = "11.1.0 (5a04ec7)"::ByteString
-- >>> let strangeVer = "11'1&0@#$%,.:\"[]{}?+^()=asdfqwer"::ByteString
Expand All @@ -496,15 +497,25 @@ readPGRSTEnvironment =
--
-- >>> addFallbackAppName strangeVer "postgres:///postgres?host=server&port=5432"
-- "postgres:///postgres?host=server&port=5432&fallback_application_name=PostgREST%2011%271%260%40%23%24%25%2C.%3A%22%5B%5D%7B%7D%3F%2B%5E%28%29%3Dasdfqwer"
--
-- Special chars in password
-- >>> addFallbackAppName ver "postgres:///postgres:pass=()[]&#?host=server&port=5432"
-- "postgres:///postgres:pass=()[]&#?host=server&port=5432&fallback_application_name=PostgREST%2011.1.0%20%285a04ec7%29"
addFallbackAppName :: ByteString -> Text -> Text
addFallbackAppName version dbUri = dbUri <>
case uriQuery <$> parseURI (toS dbUri) of
Nothing -> " " <> keyValFmt -- Assume key/value connection string if the uri is not valid
Just "" -> "?" <> uriFmt
Just "?" -> uriFmt
_ -> "&" <> uriFmt
if isPgURI dbUri
then case snd $ T.breakOn "?" dbUri of
"?" -> fallbackUriFmt
"" -> "?" <> fallbackUriFmt
_ -> "&" <> fallbackUriFmt
else " " <> fallbackKeyValFmt
where
uriFmt = pKeyWord <> toS (escapeURIString isUnescapedInURIComponent $ toS pgrstVer)
keyValFmt = pKeyWord <> "'" <> T.replace "'" "\\'" pgrstVer <> "'"
pKeyWord = "fallback_application_name="
fallbackUriFmt = key <> toS (escapeURIString isUnescapedInURIComponent $ toS pgrstVer)
fallbackKeyValFmt = key <> "'" <> T.replace "'" "\\'" pgrstVer <> "'"
key = "fallback_application_name="
pgrstVer = "PostgREST " <> T.decodeUtf8 version
isPgURI str =
let
uriDesignator = "postgresql://"
shortUriDesignator = "postgres://" in
uriDesignator `T.isPrefixOf` str || shortUriDesignator `T.isPrefixOf` str

0 comments on commit 55e43bf

Please sign in to comment.