Compare commits

..
648 Commits
Author SHA1 Message Date
renovate[bot]andWolfgang Walther 6df6725f45 chore(deps): update cachix/install-nix-action digest to 13d8dd5 2026-08-13 21:06:13 +00:00
renovate[bot]andWolfgang Walther 8df108907f chore(deps): update actions/checkout action to v7.0.1 2026-07-23 20:11:33 +00:00
renovate[bot]andWolfgang Walther 2b056c8fb8 chore(deps): update cachix/install-nix-action digest to 630ae54 2026-07-15 19:53:42 +00:00
renovate[bot]andWolfgang Walther bc409b350e chore(deps): update cachix/install-nix-action digest to a49548c 2026-07-10 20:26:29 +00:00
renovate[bot]andWolfgang Walther bba1ab065a chore(deps): update all dependencies to v7 2026-06-19 19:07:59 +00:00
renovate[bot]andWolfgang Walther c250942709 chore(deps): update all dependencies to v6.0.3 2026-06-03 07:40:36 +00:00
renovate[bot]andWolfgang Walther 1772c035d9 chore(deps): update cachix/install-nix-action digest to 8aa0397 2026-05-05 15:54:02 +00:00
renovate[bot]andWolfgang Walther 6065405bd9 chore(deps): update cachix/install-nix-action digest to ab73962 2026-04-28 11:32:17 +00:00
Wolfgang Walther 0cabe3a675 docs: fix broken link 2026-04-15 09:30:51 +02:00
renovate[bot]andWolfgang Walther df32bbfeae chore(deps): update cachix/install-nix-action digest to 6165592 2026-04-09 08:57:51 +00:00
renovate[bot]andWolfgang Walther a307ab9297 chore(deps): update cachix/install-nix-action digest to 96951a3 2026-03-30 09:58:17 +00:00
renovate[bot]andWolfgang Walther 9f63518117 chore(deps): update cachix/install-nix-action digest to 51f3067 2026-03-24 12:38:02 +00:00
renovate[bot]andWolfgang Walther c8772b54fa chore(deps): update all dependencies 2026-03-12 21:03:40 +00:00
renovate[bot]andWolfgang Walther edcf6d7644 chore(deps): update cachix/install-nix-action digest to 4e002c8 2025-12-11 20:00:52 +00:00
renovate[bot]andWolfgang Walther e0891cd457 chore(deps): update actions/checkout action to v6.0.1 2025-12-03 19:29:37 +00:00
renovate[bot]andWolfgang Walther bcab873a8f chore(deps): update actions/checkout action to v6 2025-11-21 17:29:04 +00:00
renovate[bot]andWolfgang Walther 1308f1bf60 chore(deps): update cachix/install-nix-action digest to 0b0e072 2025-11-18 17:48:47 +00:00
renovate[bot]andWolfgang Walther 3ddf506df2 chore(deps): update actions/checkout action to v5.0.1 2025-11-18 09:38:19 +00:00
renovate[bot]andWolfgang Walther 6df8db6485 chore(deps): update cachix/install-nix-action digest to fd24c48 2025-10-15 11:03:59 +00:00
renovate[bot]andWolfgang Walther 6cd519cb2b chore(deps): update cachix/install-nix-action digest to 7ab6e7f 2025-10-14 09:42:58 +00:00
renovate[bot]andWolfgang Walther cb712a8706 chore(deps): update cachix/install-nix-action digest to 9280e7a 2025-10-02 18:58:58 +00:00
renovate[bot]andWolfgang Walther 57b4cd0ade chore(deps): update cachix/install-nix-action digest to a809471 2025-09-21 14:01:32 +00:00
renovate[bot]andWolfgang Walther 457edcedfd chore(deps): update cachix/install-nix-action digest to 7be5dee 2025-09-13 09:46:20 +00:00
renovate[bot]andWolfgang Walther c1418ef910 chore(deps): update cachix/install-nix-action digest to 56a7bb7 2025-09-06 14:27:52 +00:00
renovate[bot]andWolfgang Walther af08f3a181 chore(deps): update actions/checkout action to v5 2025-08-11 15:32:17 +00:00
renovate[bot]andWolfgang Walther fa55469ae8 chore(deps): update cachix/install-nix-action digest to c134e4c 2025-07-23 21:04:53 +00:00
renovate[bot]andWolfgang Walther 7ffbbc6a74 chore(deps): update cachix/install-nix-action digest to f0fe604 2025-07-12 14:36:35 +00:00
renovate[bot]andWolfgang Walther 7ebeb3ce7f chore(deps): update cachix/install-nix-action digest to cebd211 2025-07-12 08:07:33 +00:00
renovate[bot]andWolfgang Walther 8cf0e5b2f3 chore(deps): update cachix/install-nix-action digest to f0fe604 2025-07-09 07:08:27 +00:00
renovate[bot]andWolfgang Walther eaf8c1b4bf chore(deps): update cachix/install-nix-action digest to 17fe5fb 2025-06-02 06:15:16 +00:00
Wolfgang Walther 6d79090e4a docs: remove outdated "in production" links
Moat has been bought by Oracle. The advertising subpage redirects to
oracle.com, but pointing at that would be a bit misleading.

No need to keep failing links either.
2025-05-28 09:19:36 +02:00
renovate[bot]andWolfgang Walther 0152afd796 chore(deps): update cachix/install-nix-action digest to 5261181 2025-05-14 19:40:42 +00:00
renovate[bot]andWolfgang Walther 0c3b4c0bba chore(deps): update cachix/install-nix-action digest to d1ca217 2025-04-01 19:55:20 +00:00
renovate[bot]andWolfgang Walther 87bfcedae0 chore(deps): update cachix/install-nix-action action to v31 2025-03-27 08:44:20 +00:00
Wolfgang Walther 4caea2f75d docs: Remove broken link 2025-03-26 17:01:38 +01:00
Wolfgang Walther 3cb6529eb7 docs: Fix outdated links 2025-02-22 16:12:33 +01:00
Laurence IslaandWolfgang Walther bc594f4fbd docs: fix broken links for old GUC settings
No longer links but embeds the old settings in a details html element.
2024-12-25 11:43:19 +01:00
renovate[bot]andWolfgang Walther 5a8f8c1d9c chore(deps): update all dependencies 2024-10-24 05:13:14 +02:00
renovate[bot]andWolfgang Walther ad1a998709 chore(deps): update actions/checkout action to v4.2.2 2024-10-24 05:09:03 +02:00
Wolfgang Walther 8c326f810f docs: Remove broken link
https://github.com/PostgREST/postgrest/actions/runs/11136795565/job/30949162312
2024-10-04 16:03:55 +02:00
renovate[bot]andWolfgang Walther c9b6c9f66f chore(deps): update dependency urllib3 to v2.2.3 2024-09-12 21:00:56 +02:00
steve-chavezandWolfgang Walther 1396077dd7 chore: remove links to gitter
We'll now use github discussions for support.
2024-07-13 17:14:11 +02:00
steve-chavezandWolfgang Walther 05878e78d0 chore: remove paypal links
It was tied to a personal account and donations there have been too rare.
2024-07-10 21:13:50 +02:00
Wolfgang Walther 075b0c309f docs: Fix linkcheck
Some URLs are still forbidden for our linkcheck tool, so disabling them
again.

Others are permanently redirected, so adjusting them.
2024-06-19 08:42:02 +02:00
renovate[bot]andWolfgang Walther 16a486710f chore(deps): update dependency urllib3 to v2.2.2 2024-06-17 21:03:49 +02:00
renovate[bot]andWolfgang Walther 8a809044a9 chore(deps): update actions/checkout action to v4.1.7 2024-06-13 08:46:10 +02:00
renovate[bot]andWolfgang Walther 861d387c67 chore(deps): update cachix/install-nix-action action to v27 2024-05-17 08:27:57 +02:00
renovate[bot]andWolfgang Walther 576be00536 chore(deps): update actions/checkout action to v4.1.6 2024-05-17 08:09:48 +02:00
renovate[bot]andWolfgang Walther a47bfe66e7 chore(deps): update actions/checkout action to v4.1.5 2024-05-09 13:37:34 +02:00
Wolfgang WaltherandWolfgang Walther 25a4250bb3 ci: Remove all CI except docs on EOL branches 2024-05-04 13:34:42 +02:00
renovate[bot]andWolfgang Walther 9af4a4f599 chore(deps): update all dependencies 2024-05-04 12:21:06 +02:00
renovate[bot]andWolfgang Walther b91aa4ead6 chore(deps): update all dependencies 2024-04-26 08:33:09 +02:00
renovate[bot]andWolfgang Walther a6c851aa3d chore(deps): update actions/download-artifact action to v4.1.7 2024-04-24 20:54:10 +02:00
renovate[bot]andWolfgang Walther c09eeeefab chore(deps): update all dependencies 2024-04-22 21:30:06 +02:00
Wolfgang Walther 0834bc2ca5 ci: Use explicit runner image versions 2024-04-22 21:26:45 +02:00
renovate[bot]andWolfgang Walther 51017c2702 chore(deps): update all dependencies 2024-04-20 12:46:02 +02:00
renovate[bot]andWolfgang Walther a8079f5a41 chore(deps): update codecov/codecov-action action to v4.2.0 2024-04-04 07:17:48 +02:00
renovate[bot]andWolfgang Walther bcbd61f770 chore(deps): update codecov/codecov-action action to v4.1.1 2024-03-26 19:49:59 +01:00
renovate[bot]andWolfgang Walther 865e73eeed chore(deps): update actions/cache action to v4.0.2 2024-03-20 09:08:03 +01:00
renovate[bot]andWolfgang Walther 6633badfc6 chore(deps): update ubuntu:jammy docker digest to 77906da 2024-03-08 16:30:05 +01:00
renovate[bot]andWolfgang Walther e3695cb22d chore(deps): update cachix/install-nix-action action to v26 2024-03-08 16:29:49 +01:00
renovate[bot]andWolfgang Walther e314e73ba7 chore(deps): update actions/download-artifact action to v4.1.4 2024-03-02 12:10:31 +01:00
Wolfgang Walther 7d1fa8570e chore: Add full semver comment to used actions 2024-03-01 09:00:49 +01:00
renovate[bot]andWolfgang Walther 96a2ac3799 chore(deps): update actions/cache digest to ab5e6d0 2024-03-01 08:12:19 +01:00
Wolfgang Walther ce7aa885fd nix: Remove broken docker-based nix development environment
It used to be possible to spin up a nix environment via docker container this way,
but the upstream nixos/nix image has changed and the docker build doesn't succeed
anymore. Since nobody complained about that, we can assume it is not being used
anyway.
2024-02-29 08:23:17 +01:00
renovate[bot]andWolfgang Walther 43949211f7 chore(deps): update all dependencies 2024-02-26 22:15:40 +01:00
Wolfgang Walther 8a9b7030cd ci: Use actions/download-artifact instead of dawidd6/action-download-artifact 2024-02-24 21:58:51 +01:00
renovate[bot]andWolfgang Walther d3a27beadc chore(deps): pin dependencies 2024-02-24 21:54:49 +01:00
renovate[bot]andWolfgang Walther 6734855b9f chore(deps): update all dependencies 2024-02-24 19:45:52 +01:00
Wolfgang Walther 0a0d3943c2 chore: Update docs/.gitignore to make branch switching easier 2024-02-24 18:44:25 +01:00
Wolfgang Walther 4b5bdbc496 chore(deps): update codecov/codecov-action action to v4 2024-02-24 18:43:40 +01:00
Wolfgang Walther 7359be8dd5 docs: Display version number more prominently
Resolves https://github.com/PostgREST/postgrest-docs/issues/734
2024-02-19 21:52:51 +01:00
Wolfgang Walther 52f7ae6dc8 chore: Add .docs-build to .gitignore to allow switching branches easily
This is only used on the latest main branch, but switching to release branches
is annoying otherwise.
2024-02-19 21:52:19 +01:00
Wolfgang Walther 7b43d8a139 ci: Change names for release branches from rel-MAJOR.MINOR to vMAJOR
This naming scheme gives us the best support for readthedocs.

References #2814
2024-02-17 17:48:19 +01:00
Wolfgang Walther 53123bdbb4 ci: Refactor conditions to check for branch events 2024-02-17 17:48:19 +01:00
steve-chavezandWolfgang Walther 216ded00c3 chore: readthedocs doesn't build anymore
Pin the python version to solve it.
2024-02-17 16:17:32 +01:00
Wolfgang Walther 02ec17a990 ci: Add freebsd executable to releases
This was temporarily disabled, because of timeouts in Cirrus. This seems to work well again.
2024-02-17 15:27:30 +01:00
Wolfgang Walther 8df3dfeba9 ci: Fix FreeBSD build on cirrus 2024-02-17 15:27:30 +01:00
Robert VollmertandWolfgang Walther a41b48135f ci: authenticate GitHub API request (fixes #2607) 2024-02-17 15:27:30 +01:00
Wolfgang Walther 8a6c8cde6d Merge branch 'docs/v10.2' into rel-10.2 2024-02-17 13:47:20 +01:00
Wolfgang Walther a14559647b chore: Run postgrest-style on docs files
This prevents CI from failing after the merge.
2024-02-17 13:43:27 +01:00
Wolfgang Walther 33c57506b4 chore: Prepare merge of postgrest-docs into postgrest main repo
This avoids some merge conflicts to allow git blame to detect renames properly.
2024-02-17 13:43:27 +01:00
Laurence IslaandGitHub e2f3a862be Fix version to v10.2 2023-04-25 14:55:56 -05:00
Steve ChavezandGitHub 291da1a41f Clarify pool connection features 2023-04-21 19:20:46 -05:00
d5a9e5d41f Add documentation for v10.2.0
Co-authored-by: Steve Chavez <stevechavezast@gmail.com>
2023-04-21 18:52:56 -05:00
Laurence IslaandLaurence Isla 1b218a97f4 Add a warning when working with computed relationships 2023-04-21 18:52:56 -05:00
Steve ChavezandLaurence Isla 0a3a20347b snippet for computed rel overload 2023-04-21 18:52:56 -05:00
Steve ChavezandLaurence Isla 49cd1f3447 Remove public from schema cache event trigger 2023-04-21 18:52:56 -05:00
Steve ChavezandLaurence Isla 593b8bf385 remove wrong claim about CSV being faster (#595) 2023-04-21 18:52:56 -05:00
Steve ChavezandLaurence Isla 1139031858 fix: PGRST003 status code to 504 (#594) 2023-04-21 18:52:56 -05:00
Laurence IslaandLaurence Isla a74552a1c4 Add HTTP status codes to PGRST errors (#590) 2023-04-21 18:52:56 -05:00
Laurence IslaandLaurence Isla bd11334df7 Add db-pool-acquisition-timeout configuration parameter 2023-04-21 18:52:56 -05:00
Franz-Josef FärberandLaurence Isla 1e353dc4d2 Minor improvements to sql-user-management-using-postgres-users-and-passwords.rst 2023-04-21 18:52:56 -05:00
fjf2002andLaurence Isla 1a03ece441 how-to: SQL User Management using postgres’ users and passwords (#581) 2023-04-21 18:52:56 -05:00
Andrea BernicchiaandLaurence Isla 5fb9e81969 LICENSE file added (#579) 2023-04-21 18:52:56 -05:00
dependabot[bot]Laurence Isladependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
865dd12836 Bump cachix/install-nix-action from 19 to 20 (#597)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 19 to 20.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v19...v20)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-13 19:04:16 -05:00
dependabot[bot]Laurence Isladependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
165e0acf24 Bump cachix/install-nix-action from 18 to 19 (#593)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 18 to 19.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v18...v19)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-13 19:04:16 -05:00
dependabot[bot]andLaurence Isla 4d256ce5db Bump cachix/install-nix-action from 17 to 18
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 17 to 18.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v17...v18)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-13 19:04:16 -05:00
Laurence IslaandLaurence Isla 9c075e5e52 Fix info on updates without filters 2023-04-13 19:04:16 -05:00
Laurence Islaandsteve-chavez e07807deab bump version to 10.2.0 2023-04-12 12:49:39 -05:00
steve-chavez bd50b1e4d3 ci: pin Nix version to avoid error
To 2.13.3
2023-04-12 12:49:39 -05:00
Robert Vollmertandsteve-chavez f26cdd5151 feat: use hasql-pool-0.9, add db-pool-max-lifetime (fixes #2638)
- db-pool-acquisition-timeout is no longer optional, defaults to 10s
- new option db-pool-max-lifetime limits the maximal lifetime of a
  postgresql connection, defaults to 30m
2023-04-12 12:49:36 -05:00
Steve Chavez b869dd7be9 fix: log to stderr on AcquisitionTimeoutUsageError (#2667)
* refactor: remove uneeded type on checkIsFatal
* dry with a logPgrstError function
2023-04-12 12:49:04 -05:00
RobertandLaurence Isla 97a4402911 Update nixpkgs, dependencies (#2612)
* relax upper bounds on HTTP, hspec, lens-aeson, optparse-applicative (fixes #2580)
* upgrade stackage snapshot to latest LTS, with GHC 9.2.5
* bump nixpkgs to 2023-01-12
* fix complaints due to updated linters
2023-04-12 09:52:08 -05:00
RobertandLaurence Isla a101d27c9c bump postgresql-libpq (#2599)
For https://github.com/PostgREST/postgresql-libpq/pull/2.
2023-04-12 09:52:08 -05:00
steve-chavezandLaurence Isla 519dbc75f3 refactor: delete QueryCost, instead use PlanSpec 2023-04-12 09:52:08 -05:00
steve-chavezandLaurence Isla ae3c784921 refactor: add planCost and planHdr for tests 2023-04-12 09:52:08 -05:00
steve-chavez f56bed2a75 bump version to 10.1.2 2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez af8e436732 Add missing fixes to the changelog 2023-02-02 03:30:15 -05:00
steve-chavez 98a29bee04 fix: NOTIFY pgrst not reoading the catalog cache 2023-02-02 03:30:15 -05:00
Tuan LeandSteve Chavez 557285b659 fix: consider authentication failure as a fatal error 2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez 81501aefa0 fix: FK pointing to VIEW instead of TABLE in OpenAPI output 2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez 12c1d4a8e4 Add upsert headers for POST requests to the OpenAPI output 2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez 8aa7368786 fix: Add required OpenAPI items object when the paramater is an array 2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez 9d4ff812c9 Add suggestions with fuzzy text search when no relationship is found (#2583) 2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez 171dd313d9 fix: clarify error messages for functions
Move explanation on single unnamed parameters to the error details
2023-02-02 03:30:15 -05:00
Laurence IslaandSteve Chavez fd24a7374b feat: hint function names/parameters on error 2023-02-02 03:30:15 -05:00
steve-chavez a525790c4c fix: bad M2M embed on RPC 2023-02-02 03:30:15 -05:00
Steve Chavez df2cde81ca Add db-plan-enabled recommendation (#588)
* fix broken links
2023-01-28 20:37:16 -05:00
Laurence Islaandsteve-chavez 1e09b9f06d Fix broken links and dictcheck 2023-01-28 20:37:08 -05:00
Laurence Islaandsteve-chavez 08228fa2fc Fix auth page due to anonymous requests not allowed when db-anon-role is not set 2023-01-28 20:36:25 -05:00
Laurence Islaandsteve-chavez aecb7910de Fix step 3 of the tutorial 0 2023-01-28 20:34:48 -05:00
Laurence Islaandsteve-chavez 0a5ae531a4 Add information on preflight requests in CORS subsection 2023-01-28 20:31:24 -05:00
Laurence Islaandsteve-chavez 45ba35657b Shorten explanations for the working with types section 2023-01-28 20:30:30 -05:00
mdr1384andsteve-chavez a65d387a31 Fix example code in computed relationships
Looks like a copy-paste error - the `films.id` column should be associated with the `premieres.film_id` column.
2023-01-28 20:28:50 -05:00
Andrea BernicchiaandGitHub e7413f3aea Update heroku installation docs
* Heroku installation docs aligned with https://github.com/PostgREST/postgrest-heroku/pull/40
* Update install.rst
2022-10-27 10:58:17 -05:00
Steve ChavezandGitHub 9128c8602a Refine docs for v10
* shorten release page

* shorten explain docs

* add limited update/delete to release page

* refine relationships

* refine disambiguation

* refine release page

* remove migration guide

* add author to WWT how-to
2022-08-26 16:08:08 -05:00
Laurence IslaandGitHub a0c463b998 Add missing changes/fixes/features for v10 2022-08-23 21:59:48 -05:00
steve-chavez eb100cc746 clarify * as an alias of % for LIKE 2022-08-05 18:36:25 -05:00
Laurence IslaandGitHub 2592639d1b Reword and clarify embedding on views 2022-07-19 10:51:36 -05:00
steve-chavez bba960d4c6 new m2m relationship detection 2022-07-12 00:02:09 -05:00
Laurence IslaandGitHub b37bacb19a Add Limezest/postgrest-cloud-run to ecosystem 2022-07-08 12:27:14 -05:00
fjf2002andGitHub 06ece64cb0 HOW-TO for SOAP (#554) 2022-06-29 10:11:15 -05:00
Laurence IslaandGitHub 65c2754719 Modify GeoJSON examples from views to functions (#551) 2022-06-21 17:38:29 -05:00
Steve ChavezandGitHub 360cfa3fbd clarify errors (#550) 2022-06-20 13:50:47 -05:00
steve-chavez 13ce0f3354 add bulk update 2022-06-16 11:11:37 -05:00
steve-chavez 5305998a95 disallowed full table update 2022-06-16 11:11:37 -05:00
steve-chavez a9baa5bc9f lowercase upsert 2022-06-16 11:11:37 -05:00
Laurence IslaandGitHub 580184532b Add 9.0.1 changelog 2022-06-14 10:40:10 -05:00
Franz-Josef FärberandSteve Chavez 48783087de RPC POST for function w/single unnamed XML param, postgrest-PR #2300 2022-06-03 11:53:38 -05:00
Laurence IslaandGitHub 96c169e593 Add bytea to working with types and improve img example (#542) 2022-05-27 17:12:47 -05:00
Laurence IslaandGitHub 209b70cbfc Add disclaimer on $ usage in jwt-secret values (#543) 2022-05-25 17:29:52 -05:00
Laurence IslaandSteve Chavez 06956c1994 Add explicit use of special timestamp values 2022-05-24 23:06:46 -05:00
Laurence IslaandGitHub 06ab9fbd67 Add how to work with array columns (#538) 2022-05-20 03:37:27 +02:00
Laurence IslaandGitHub 340c96883e Fix main explanation on views with joins (#537)
* Fix indentation and example view
* Change films.id to just id
2022-05-19 23:44:31 +02:00
Laurence IslaandGitHub 496a1734ec Add documentation on embedding views containing joins 2022-05-18 20:50:06 -05:00
Franz-Josef FärberandSteve Chavez 6e24e23b4b Allow returning XML 2022-05-05 10:57:38 -05:00
Laurence IslaandGitHub 9c23ac2f39 Reorganize error groups 2022-05-02 23:14:24 -05:00
steve-chavez 5f3284eed0 fix broken links 2022-05-02 19:42:02 -05:00
steve-chavez 72bffddbf1 Add limited updates/deletions
Also move updates to its own section
2022-05-02 19:42:02 -05:00
dependabot[bot]andSteve Chavez f6c68ddafb Bump cachix/install-nix-action from 16 to 17
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 16 to 17.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v16...v17)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 13:22:12 -05:00
Michael Kane JunckerandWolfgang Walther 6f79b41bc1 feat(api): add match/imatch operators for regular expression support - refs PostgREST/postgrest#2236 2022-04-11 08:56:45 +02:00
Christopher AhlersandSteve Chavez 06156eb797 Update ecosystem.rst
Fixed incorrect link for the swift library in Client-Side Libraries section. It now links properly to: https://github.com/supabase-community/postgrest-swift
2022-04-04 20:14:05 -05:00
Laurence IslaandGitHub e1c987dc5f Add latest page (#521)
* better highlight for composite/array reference
2022-03-27 17:54:48 +02:00
Laurence IslaandGitHub eb4c428da6 Fix unordered list styles 2022-03-25 00:14:18 -05:00
Laurence IslaandGitHub 5688bc1521 Add JSON, Composite and Ranges types to the working with types how-to 2022-03-24 17:48:43 -05:00
Laurence IslaandGitHub a8034df2bf Add how to on PostGIS and hstore data types (#516) 2022-03-22 11:30:45 +01:00
Steve ChavezandGitHub f56373313e Fix not reloading on ALTER TYPE (#517) 2022-03-22 10:57:04 +01:00
Laurence IslaandGitHub 8f98948078 Add Errors reference (#430)
* Adds PostgREST' error codes 

* Move error information to a dedicated reference page

* Organize errors into tables
2022-03-14 21:03:01 +01:00
Laurence IslaandGitHub 1489fc84b8 Recommend specifying host names for health check (#514)
In case of multiple network interfaces
2022-03-14 20:56:34 +01:00
dependabot[bot]andGitHub ea58095e92 Bump actions/checkout from 2.4.0 to 3 (#512) 2022-03-08 01:56:21 +01:00
Laurence IslaandGitHub 98976e4d57 Add how-to for working with PostgreSQL data types 2022-03-04 20:04:49 -05:00
Wolfgang WaltherandWolfgang Walther e9ef876433 Add hint on how to prevent exposing computed columns as RPCs
Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-02-28 13:14:53 +01:00
Laurence IslaandGitHub 4aff0caa59 Add documentation on the minimal health check 2022-02-23 17:25:07 -05:00
Adam KlimentandGitHub fbe317b244 Update auth.rst (#507) 2022-02-22 11:48:22 -05:00
Laurence IslaandGitHub abe0daa3dc Add example for array and composite type columns 2022-02-15 14:20:12 -05:00
Steve ChavezandGitHub b209731ff3 Add admin section on file descriptors (#504) 2022-02-09 14:17:22 -05:00
ElectronoobandWolfgang Walther 9049ed1f71 updated the example config switch
replacing postgrest 2 with postgrest -e
2022-02-08 08:54:05 +01:00
Wolfgang WaltherandWolfgang Walther 6aeb5065f8 Add docs about accessing array items and fields of composite types with JSON operators.
Added in https://github.com/PostgREST/postgrest/pull/2145

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-02-04 22:31:28 +01:00
Wolfgang WaltherandWolfgang Walther 4d6909a08f Mention computed columns can be on the extra search path.
Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-02-04 22:31:28 +01:00
Wolfgang WaltherandWolfgang Walther 9c0db849ce Move JSON Columns and Computed Columns sections one level up
Both of those are about select and filters - so do not belong into "Vertical Filtering" only.

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-02-04 22:31:28 +01:00
Wolfgang WaltherandWolfgang Walther 71dd891d2f fix postgrest-serve after move to docs/ folder
Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-02-04 22:31:28 +01:00
Wolfgang WaltherandWolfgang Walther 43a92d4e6b ci: Only run linkcheck in pull requests to main branch
Avoids running linkcheck on back branches, where links are outdated anyway.

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-01-30 16:32:14 +01:00
Wolfgang WaltherandWolfgang Walther e7e102bc42 ci: switch to GitHub Actions
Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-01-30 16:32:14 +01:00
Wolfgang WaltherandWolfgang Walther 91f1580f95 Fix warning when using docker host network
Resolves #491

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-01-30 14:24:51 +01:00
Wolfgang WaltherandWolfgang Walther a4db05aeba Improve docker install examples
Removes the PGRST_DB_SCHEMA variable which is public by default now.

Removes the PGRST_DB_ANON_ROLE variable, because using the authenticator role or even a superuser is very bad practice.

Replaces the postgres superuser with app_user, because using a superuser to connect to postgres is very bad practice.

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-01-30 14:24:51 +01:00
Wolfgang WaltherandWolfgang Walther a85dfe9558 chore: Move *.rst files to docs/ folder
Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-01-30 13:35:55 +01:00
Wolfgang WaltherandWolfgang Walther 0ae86b7e74 Fix references to full documents instead of first section
Resolves #492

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2022-01-30 13:31:20 +01:00
NileshandGitHub 49ca91cc3c Improving docs for setting response headers like content-type (#494) 2022-01-27 19:27:19 -05:00
Wolfgang WaltherandWolfgang Walther 0824139069 Add order of precedence for config parameters 2022-01-24 10:24:39 +01:00
Wolfgang WaltherandWolfgang Walther 5f938dbe1a Run PostgREST with zero config. Related to https://github.com/PostgREST/postgrest/pull/2112 2022-01-24 10:24:39 +01:00
Wolfgang WaltherandWolfgang Walther 5187eadd0b Restructure configuration reloading section 2022-01-24 10:24:39 +01:00
Steve ChavezandGitHub 9d23cfde9d Add finer-grained event trigger (#489) 2022-01-12 12:52:34 -05:00
Wolfgang WaltherandWolfgang Walther 737ad76dfd Clarify in-database configuration example regarding IN DATABASE 2022-01-08 22:25:31 +01:00
Wolfgang WaltherandWolfgang Walther 4bd090ba13 add user to logging example 2022-01-08 11:31:41 +01:00
Wolfgang WaltherandWolfgang Walther 540ef4ad9f Update configuration page 2022-01-08 11:29:20 +01:00
Wolfgang WaltherandWolfgang Walther 62726ddcfd force colored output in build and linkcheck tools 2022-01-08 10:50:48 +01:00
Wolfgang WaltherandWolfgang Walther 6c382c5985 replace permanently redirected URIs 2022-01-08 10:50:48 +01:00
Wolfgang WaltherandWolfgang Walther 0187410882 remove dead link to v5 docs 2022-01-07 20:33:06 +01:00
Wolfgang Walther cfde95b0aa remove reference to heroku app.json in main repo 2022-01-01 15:13:57 +01:00
Wolfgang Walther 04e7020ae3 fix database-configuration ALTER ROLE example, resolves #481 2021-12-24 12:06:34 +01:00
Laurence Isla 66e49f0ea2 Update config.py version/release 2021-12-23 17:08:54 -05:00
Devin SteinandGitHub 1b24eb34ee Add missing = in log-level docs 2021-12-10 18:08:51 -05:00
Laurence IslaandSteve Chavez d5fb73bf9b Fix GUC names using the old syntax 2021-11-30 18:17:40 -05:00
Laurence IslaandGitHub c46c3b7a86 Bump to PostgREST v9 (#468)
* Add highlights and modify changelog structure

* Rename upcoming page to v9.0.0

* Classify features, edit breaking changes and fixes

* Highlight top-level filtering

* Clarify PostgreSQL 14 breaking change

* Add devops to doc improvements

* Add curl snippets to doc improvements
2021-11-29 03:27:38 -05:00
Wolfgang WaltherandWolfgang Walther 9eac683e51 Drop support for PG 9.5.
Related: https://github.com/PostgREST/postgrest/pull/2038
2021-11-24 19:43:26 +01:00
Laurence IslaandGitHub 35d9b98bff Remove the db-embed-default-join config 2021-11-23 22:12:29 -05:00
Laurence IslaandGitHub c946f02607 Remove partitions from the schema cache 2021-11-22 14:43:24 -05:00
Laurence IslaandGitHub d12974339a Allow unknown for is operator 2021-11-18 17:34:51 -05:00
Laurence IslaandGitHub 06c0180e4f Add the Logical Operators section to Horizontal Filtering 2021-11-15 17:36:29 -05:00
Laurence IslaandGitHub 4720cfc1d3 Add example to rpc unnamed single bytea parameter 2021-11-11 17:02:17 -05:00
Laurence IslaandGitHub 4e4458eb95 Allow POST rpc with a single unnamed parameter 2021-11-10 19:35:44 -05:00
Laurence IslaandGitHub 8b74e14c4f Use tabs to show different installation methods 2021-11-08 12:27:22 -05:00
Laurence IslaandGitHub 7cc3d319bc Fix broken styles 2021-10-29 15:11:39 -05:00
Laurence IslaandGitHub a0bdcb706c Add curl examples alongside http snippets 2021-10-28 18:06:52 -05:00
Laurence IslaandGitHub 23ad30a20a Add templates section to the ecosystem 2021-10-28 17:47:21 -05:00
Laurence IslaandGitHub b15dd8783e Add Retry-After header when recovering the connection 2021-10-21 21:08:29 -05:00
Laurence IslaandGitHub 8e11b6f5df Allow escaping inside double quotes with a backslash (#447) 2021-10-20 16:13:49 -05:00
Wolfgang WaltherandWolfgang Walther 7e7d4df93b docker-compose: remove optional quotes around environment variable
Resolves #446
2021-10-20 13:17:41 +02:00
laurenceislaandGitHub c6ef4305b1 Allow top-level resource with embed filter 2021-10-19 11:34:18 -05:00
laurenceislaandGitHub ee1ec780d2 Add nested embedding examples 2021-10-18 17:34:49 -05:00
laurenceislaandGitHub ec7ace2e73 Add compatibility with PostgreSQL v14 2021-10-13 14:31:49 -05:00
Bartłomiej SzostekandLaurence Isla ad13e00f64 Typo in api.rst, correct ignore_privileges
The correct setting name is `ignore-privileges`, with dash in between the words.
2021-10-04 10:46:02 -05:00
laurenceislaandGitHub a6a088e9f0 Specify external connection poolers 2021-09-30 17:18:58 -05:00
Boris KorzunandGitHub 09ca21d032 Updated FreeBSD dependencies
Update FreeBSD dependencies as in bsd.default-versions.mk
2021-09-22 12:52:37 -05:00
Laurence Isla 5fb11e37a3 Add devops links to helm charts 2021-09-15 19:45:47 -05:00
Laurence Isla aea3b24b31 Update example apps 2021-09-03 15:05:15 -05:00
laurenceislaandGitHub 34958e723a Add link and explanation to download the latest unreleased builds 2021-09-03 13:04:21 -05:00
laurenceislaandGitHub 91152ebad0 Add partitioned tables in the schema cache 2021-08-13 17:31:01 -05:00
Laurence Isla f7108e8612 Add example apps to ecosystem
Add postgres-postgrest-cloudflared-example and svelte-postgrest-template
2021-08-11 20:13:04 -05:00
steve-chavez 0d23be7731 Fix logging blocks not showing on RTD 2021-08-10 00:37:25 -05:00
steve-chavez fcabf4012b Reorder release notes for v8.0 2021-08-10 00:26:24 -05:00
Laurence Isla ff30d4d417 Update config.py version/release 2021-08-09 18:29:37 -05:00
laurenceislaandGitHub 98350e2941 Update docker configuration 2021-08-09 18:06:45 -05:00
steve-chavez 42656edfd9 Improve wording in some sections 2021-08-09 14:10:46 -05:00
Laurence IslaandSteve Chavez 37c2a8aa7b Make the landing page wider
* Add max-width for logos only

* Fix margin on sponsor images and add reference to the PostgREST team

* Fix information on v8 changelog
2021-08-09 14:10:46 -05:00
Laurence IslaandSteve Chavez 21e54aacda Rename upcoming to v8.0.0 2021-08-09 14:10:46 -05:00
Laurence IslaandSteve Chavez 12f8852183 Add fixes and sponsors to upcoming page 2021-08-09 14:10:46 -05:00
steve-chavez 254a2f7f36 Add in-db config plus reloading 2021-08-09 14:10:46 -05:00
steve-chavez 698db87590 Reorder configuration reloading 2021-08-09 14:10:46 -05:00
steve-chavez 8d4bc76aab Add entry for OPTIONS on views
* Also clarify the schema cache page
2021-08-09 14:10:46 -05:00
steve-chavez 52cdd50561 Show timestamps for server diagnostic information 2021-08-09 14:10:46 -05:00
steve-chavez 57d725bab6 Add Bearer without capitalization 2021-08-09 14:10:46 -05:00
steve-chavez 9543e746ec Mention log-level=crit/error increase throughput 2021-08-09 14:10:46 -05:00
steve-chavez 33f0da0509 Add no downtime schema cache reload 2021-08-09 14:10:46 -05:00
Laurence Isla 20bee2ec34 Fix log-level value for status 4xx errors 2021-08-02 18:33:50 -05:00
Duncan OgilvieandGitHub c4387ec7dd Mention environment variables in the configuration section 2021-08-02 11:45:12 -05:00
Laurence IslaandSteve Chavez 6909e3435e Add changelog for embedding views recursively 2021-07-25 14:49:42 -05:00
laurenceislaandGitHub 2e50a22e64 Add config reloading with SIGUSR2 2021-07-24 18:52:52 -05:00
laurenceislaandGitHub 5cbabe4a21 Add database notification functionality and configuration variables for schema reloading 2021-07-24 16:27:02 -05:00
laurenceislaandGitHub 77faf9e9bc Add explicit headers-only POST request using Prefer header and default the request to minimal 2021-07-23 17:15:30 -05:00
laurenceislaandGitHub 41325fd9ba Add db-prepared-statements config option 2021-07-23 11:41:47 -05:00
laurenceislaandGitHub f5c5094d7d Add db-tx-end config option 2021-07-21 19:49:41 -05:00
laurenceislaandGitHub a7cddd8ece Add log-level config option 2021-07-21 14:40:34 -05:00
laurenceislaandGitHub 204b0ed259 Add improved error messages for RPC on a stale schema
Error message for a not found RPC.

Unsupported overloaded RPC with the same argument names but different types.
2021-07-20 16:40:45 -05:00
laurenceislaandGitHub 8562f48a37 Add openapi-mode configuration option 2021-07-20 16:15:17 -05:00
Laurence Isla 3f2a58ab76 Add Oblivious as a sponsor 2021-07-12 19:59:59 -05:00
laurenceislaandGitHub f7f3aadab8 Reorganize the Schema Cache information into a separate reference page (#404) 2021-06-18 12:10:31 -05:00
laurenceislaandGitHub 326019cca2 Add reference for OPTIONS on the API page (#407)
* Add CORS documentation
* Add options requests to upcoming page
2021-06-14 19:30:22 -05:00
Wolfgang WaltherandWolfgang Walther a9dbd9e14f Add user-agent to sphinx config to fix some linkchecks 2021-06-03 16:55:10 +02:00
Wolfgang WaltherandWolfgang Walther 8e0b67ed09 Sort ecosystem 2021-06-03 16:55:10 +02:00
Wolfgang WaltherandWolfgang Walther 7447b03295 Fix broken links 2021-06-03 16:55:10 +02:00
Wolfgang WaltherandWolfgang Walther 574e57d01a Upgrade nixpkgs to enable linkcheck in CI 2021-06-03 16:55:10 +02:00
Murat Mirgün ERCANandsteve-chavez 07cc6547ee Add Supabase-go Library Ecosystem 2021-05-29 20:20:48 -05:00
Lee Yi Jie JoelandSteve Chavez 92c5066a79 docs: add elixir client library 2021-05-28 10:19:48 -05:00
steve-chavez 2768019710 Add GNUHost as a sponsor 2021-04-23 17:16:11 -05:00
AmandaandGitHub 038fcc02b2 Adding a hint to Hello World
This note helps people who are hitting this error `{"hint":null,"details":null,"code":"42P01","message":"relation \"api.todos\" does not exist"}`

https://github.com/PostgREST/postgrest/issues/1009
2021-04-19 10:04:34 +02:00
steve-chavez 535ebba219 Remove subzero link 2021-04-09 23:34:54 -05:00
Wolfgang WaltherandWolfgang Walther 7e4810f0a6 change Master to Main in heroku deploy steps 2021-04-06 16:31:24 +02:00
Wolfgang Walther 8273e270f2 Change http to https in README.md 2021-04-06 15:43:32 +02:00
Wolfgang Walther d5b9f6cc88 fix postgrest repo link in CONTRIBUTING.md 2021-04-06 11:09:33 +02:00
Wolfgang WaltherandWolfgang Walther aa38221fc1 Add linkcheck to CI 2021-04-06 10:19:44 +02:00
Wolfgang WaltherandWolfgang Walther 92395eae8a added postgrest-docs-linkcheck; clean up links
* removed outdated links
* updated permanent redirections
* updated postgres docs links to current version
* sort links in ecosystems by repo-name
* change http:// to https://
2021-04-06 10:19:44 +02:00
Wolfgang WaltherandWolfgang Walther a1178a8016 move "Build from Source" to installation chapter and remove "Running the Test Suite" 2021-04-06 10:19:44 +02:00
Wolfgang WaltherandGitHub 2a2a4fdd92 remove translation section from readme
TODO: implement a proper translation workflow
2021-04-05 21:52:31 +02:00
steve-chavez 9f50e1d2d7 Add Supabase as a sponsor 2021-03-25 20:53:59 -05:00
Alexis Panagiotopouosandsteve-chavez d77da6bd49 Update api.rst
Changed SET LOCAL to SELECT set_config( ... ) so that the value of the header can be dynamically calculated. Supported in versions 9.6 and above.
2021-03-12 10:07:56 -05:00
steve-chavez 82e9895e1f Update CYBERTEC logo and url 2021-02-25 18:19:51 -05:00
CoppleandGitHub 5728bbc4b9 Add Supabase to In Production and client libraries (#389) 2021-02-18 09:16:19 -05:00
Max HandGitHub 89942601e4 Fix headline numbering in tutorial 1 2021-01-21 08:33:58 +01:00
Gurjeet SinghandSteve Chavez c3ad07fcc0 Minor grammar fix 2020-12-27 10:57:46 -05:00
Joshua TaillonandWolfgang Walther a4fe838308 Fix outdated environment variable for docker compose
Also removed a deprecated `links` setting from the docker-compose, since that's not needed any more
2020-12-08 21:09:46 +01:00
Wolfgang WaltherandWolfgang Walther b0ba2f709c remove Makefile and Pipfile 2020-11-30 21:35:33 +01:00
Wolfgang WaltherandWolfgang Walther d6caa5dae9 make docs full-width, resolves #351 2020-11-29 23:55:41 +01:00
Wolfgang WaltherandWolfgang Walther 881170b9ff Fix build warnings to satisfy postgrest-docs-build 2020-11-29 23:54:48 +01:00
Wolfgang WaltherandWolfgang Walther 634a0c70b7 Fix spelling to satisfy postgrest-docs-spellcheck 2020-11-29 23:54:48 +01:00
Wolfgang WaltherandWolfgang Walther 84e5597091 Add postgrest-docs-dictcheck to remove obsolete words from postgrest.dict 2020-11-29 23:54:48 +01:00
Wolfgang WaltherandWolfgang Walther b83ee94fae Add nix-shell tools, fix circleci, resolves #322 2020-11-29 23:54:48 +01:00
Miodrag Milićandsteve-chavez ea2e166aa1 Add chocolatey installation method
#369
2020-11-28 18:51:25 -05:00
Wolfgang WaltherandSteve Chavez 9f15044e63 Add note about embedding of view-chains and the interaction with db-extra-search-path 2020-11-22 18:10:04 -05:00
Francois-Guillaume Ribreauandsteve-chavez fbef0078d5 Update index.rst
- add netwo
- add how to guide :)
- fix my name :')
2020-11-02 14:02:49 -05:00
Wolfgang WaltherandSteve Chavez 06dba3953f calling variadic functions 2020-10-27 21:03:12 -05:00
ExahilosysandSteve Chavez 15d5b8a292 Moved aiodata to Extensions 2020-10-24 22:18:28 -05:00
ExaandSteve Chavez a05aed9b3e Added aiodata 2020-10-24 22:18:28 -05:00
Gergely Mészárosandsteve-chavez 32173bed4d Missing library dependency
Without zlib1g-dev the build process fails.
2020-09-28 10:10:34 -05:00
Severin Ibarluzeaandsteve-chavez 57200320c3 add postgrest-vercel and postgrest-node 2020-09-21 11:27:11 -05:00
Saltuk AlakusandGitHub 089895ac27 Improvements for Auth0 documentation. (#350)
Update for Auth0 integration with the OIDC flow using APIs
2020-08-26 19:23:54 -05:00
Vikas Prasadandsteve-chavez 5b59e79dc9 Mention --install-ghc flag is needed only for the first time. (#347) 2020-08-20 14:23:14 -05:00
Geoffrey van Wykandsteve-chavez 92f76722cc Fix order of options in tar command (#345)
With the current order, the tar command thinks the name of the archive is J.
This happens on Windows 10 WSL2 with tar 1.29.
2020-08-20 13:50:30 -05:00
Sam KhawaseandSteve Chavez 47bd27badb Updated the link to the blog post for PostgREST + Auth0 tutorial 2020-08-17 20:45:21 -05:00
Wolfgang WaltherandGitHub 49bc82bfca Clarify function volatility and location header (#339)
* clarify location header only available with PK

* clarify function volatility and GET/POST

* improve stable/immutable for post and get

* add 405 for read only transaction error
2020-08-13 10:29:32 -05:00
Aleš NajmannandGitHub c7e623549d Add Windows installation using Scoop to install page (#342) 2020-08-04 12:02:44 -05:00
vbalasuandsteve-chavez 7f67cf78e7 Update ecosystem.rst (#341)
Added pg-notify-webook
2020-07-28 11:31:59 -05:00
Tad LispyandGitHub 5811682025 Fix #334: Alter default privileges (#338)
* Suggest granting execute on all functions in schema api

* Suggest to permanently alter default privileges on functions
2020-07-17 11:36:45 -05:00
Teemu SirviöandSteve Chavez 4c92fc7bca Update links to pg-safeupdate
Change broken links to Bitbucket to GitHub.
2020-07-09 11:28:10 -05:00
steve-chavez c518585259 Add FreeBSD port to install page 2020-06-28 13:46:39 -05:00
steve-chavez 7e3c14a71a Update community tutorials
- Description to keycloak tutorial
- Correct gisops tutorial link
2020-06-16 13:52:43 -05:00
Mathieu Passenaudandsteve-chavez 864a1440be added https://www.mathieupassenaud.fr/codeless_backend/ tutorial 2020-06-16 13:43:45 -05:00
Andrew HallandSteve Chavez 702df3218d add redux-postgrest to client-side libraries
As per https://github.com/andytango/redux-postgrest/issues/7
2020-06-12 19:41:54 -05:00
Bobbie SoedirgoandSteve Chavez 78bd10acc9 Add supabase/postgrest-rs client library 2020-06-11 08:54:47 -05:00
steve-chavez 94441c70c0 Add upcoming page 2020-06-05 14:35:45 -05:00
Steve ChavezandGitHub a869734140 reference: Add response.status GUC (#329)
Related to https://github.com/PostgREST/postgrest/pull/1541
2020-06-05 13:01:52 -05:00
waltherjjandSteve Chavez ff8fd648bb Add new JS (Vue) client to /ecosystem
Hey! We developed a Vue.js library, happy to be part of this. Thank you for postgREST!
2020-05-27 12:54:16 -05:00
Oskar OldorfandGitHub f03be6d2d0 Fix typo (#325) 2020-05-27 12:36:16 -05:00
Steve ChavezandGitHub b965f32137 Update v7.0.1.rst 2020-05-23 19:28:28 -05:00
steve-chavez 0b998e91d6 Add notice about single Linux static executable
Reorder development page in the toctree
2020-05-22 14:36:56 -05:00
steve-chavez 5e44c8160f Add package managers in installation
Fixes https://github.com/PostgREST/postgrest-docs/issues/319

* Add development page
* Clear installation page from admin and development concerns
2020-05-22 14:36:56 -05:00
steve-chavez 516809f2de Add favicon.ico 2020-05-22 14:36:56 -05:00
steve-chavez f8991b0794 Fix broken link in schema structure 2020-05-22 14:36:56 -05:00
steve-chavez 20bb295237 Add v7.0.1 release 2020-05-22 14:36:56 -05:00
steve-chavez 40bffc6950 Add subheading to db-schema 2020-05-12 13:24:40 -05:00
RemoandGitHub 8dc16eef27 Documentation on how to run the test suite locally (#316)
Uses the `with_tmp_db` script added in https://github.com/PostgREST/postgrest/pull/1476.
2020-05-06 11:41:14 -05:00
steve-chavez 622ff7b708 Note schema structure page is a work in progress 2020-05-04 11:46:54 -05:00
Nick Santosandsteve-chavez 1315584de5 Fix link to DigitalOcean PostgREST Contact List video
Old playlist is gone - linked to first video in series instead
2020-05-04 11:43:14 -05:00
Steve PhillipsandSteve Chavez b6c03f3658 api.rst: formatting tweaks 2020-04-30 17:20:48 -05:00
steve-chavez 469e01f77b Add release page for v7.0.0 2020-04-21 15:16:21 -05:00
steve-chavez 3af6df743b Reorder calling func with array 2020-04-21 15:16:21 -05:00
steve-chavez ef36ec10a1 Put warning in db-schema and clarify search_path 2020-04-21 15:16:21 -05:00
steve-chavez 3328b6059f Consolidate schema structure page 2020-04-21 15:16:21 -05:00
steve-chavez 79f2af08e3 Add wording for schema structure 2020-04-21 15:16:21 -05:00
steve-chavez 7714bd9623 Move HTTPS section from auth to admin
It fits better into administration concerns
2020-04-21 15:16:21 -05:00
steve-chavez 055b7820b3 Add schema structure diagram 2020-04-21 15:16:21 -05:00
steve-chavez 5eca88fd87 Refine function privileges section 2020-04-21 15:16:21 -05:00
steve-chavez 6b72da38e6 Move some api notes to best practices 2020-04-21 15:16:21 -05:00
steve-chavez c2ff7ffb62 Redorder insertions before stored procedures 2020-04-21 15:16:21 -05:00
steve-chavez 750c22cd1c Add mounting config file to docker 2020-04-21 15:16:21 -05:00
steve-chavez 4d623986ea Alternative to bulk call 2020-04-21 15:16:21 -05:00
steve-chavez a5af8dc68f Add return=rep to DELETE section 2020-04-21 15:16:21 -05:00
steve-chavez 467b22cb29 Fix required pg minimum version
Fixes https://github.com/PostgREST/postgrest-docs/issues/317
2020-04-21 15:16:21 -05:00
steve-chavez 87f883b793 Add multiple schemas feature 2020-04-21 15:16:21 -05:00
steve-chavez 3292fce732 Update schema reloading section
Fixes https://github.com/PostgREST/postgrest-docs/issues/243
2020-04-21 15:16:21 -05:00
steve-chavez 33768c509c Add reference for rpc with array literals
Fixes https://github.com/PostgREST/postgrest-docs/issues/258
2020-04-21 15:16:21 -05:00
steve-chavez dd7e182b12 Update config.py version/release
Fixes https://github.com/PostgREST/postgrest-docs/issues/260
2020-04-21 15:16:21 -05:00
steve-chavez 9f5ab4a8ba Add reference for filtering on json column
Fixes https://github.com/PostgREST/postgrest-docs/issues/266
2020-04-01 11:36:28 -05:00
fiatjafandGitHub b7ee8f1cf0 mention that JSON operators work for row filtering (#314) 2020-04-01 11:00:05 -05:00
Sam KhawaseandGitHub 36c453d6de Added the link to tutorial to configure and integrate Auth0 to PostgREST (#312) 2020-03-30 12:48:20 -05:00
Duncan OgilvieandGitHub e23b7afa3c Fix the 'Roles for Each Web User' example (#313)
Add missing `ALTER TABLE ... ENABLE ROW LEVEL SECURITY;`
2020-03-23 11:48:09 -05:00
Patrik KellerandGitHub 334dda611c Tutorial: Providing images for <img> (#307) 2020-03-17 12:59:40 -05:00
yangandGitHub a343536539 Add type basic_auth.jwt_token. (#308)
Or the function login will show error.
2020-03-12 12:58:07 -05:00
Steve ChavezandGitHub 0d3dc8509c Add sompani to production list (#306) 2020-03-12 10:39:15 -05:00
H20-17andGitHub 66e0e88539 Clarify function privileges section (#303)
* Add best_practices.rst file

* Move function privileges to best_practices.rst
2020-02-18 17:04:17 -05:00
steve-chavez 53f35f638c Add on_conflict query parameter 2020-02-15 13:56:38 -05:00
steve-chavez f34a480a99 Add misc header improvements to upcoming 2020-02-15 13:56:38 -05:00
steve-chavez 1d54b8b07d Add fixes to upcoming 2020-02-15 13:56:38 -05:00
steve-chavez 2aae1a3894 Add unix socket changes 2020-02-15 13:56:38 -05:00
steve-chavez 87528412c0 Add overriding provided headers note 2020-02-15 13:56:38 -05:00
steve-chavez 5fd86e682b Add setting headers via pre-request 2020-02-15 13:56:38 -05:00
steve-chavez 1f40492d64 Add request path/method GUC 2020-02-15 13:56:38 -05:00
steve-chavez 0ed1d31c72 Add embedding disambiguation in upcoming 2020-02-15 13:56:38 -05:00
steve-chavez c4005ad8f2 Change server-proxy-uri 2 openapi-server-proxy-uri 2020-02-15 13:56:38 -05:00
steve-chavez 878752faee Correct join table paragraph 2020-02-08 14:52:28 -05:00
Wouter ScherphofandSteve Chavez f6c67ffdc1 correction url embedded resources through join tables 2020-02-08 14:40:15 -05:00
Coppleandsteve-chavez 95fccbb00f Add supabase/postgrest-js client library 2020-02-03 12:44:40 -05:00
Ivan GabrieleandSteve Chavez 1caf114e5a Add postgrester client library 2020-01-23 18:13:15 -05:00
RemoandSteve Chavez da1cf9f76d Add postgrest-sessions-example to Example Apps (#294) 2020-01-19 14:17:55 -05:00
Steve ChavezandGitHub 4cd05681dd Add embedding disambiguation section (#290) 2020-01-06 09:43:54 -05:00
steve-chavez e47d19d4dc Fix livereload host 2019-12-28 11:21:30 -05:00
Steve ChavezandGitHub 4eefe14706 Add GISOPS community tutorial (#291) 2019-12-23 13:46:22 -05:00
CoppleandSteve Chavez 8dba0dcc11 Remove fragment from Nimbus blog post URL (#288) 2019-12-17 12:28:44 -05:00
Steve ChavezandGitHub 1b166ce048 Add Community Tutorials section (#287)
Include DO video series
2019-12-16 12:39:57 -05:00
Dmitry WaginandSteve Chavez 458960f7c3 change server-unix-socket-mode 755 -> 660 (#286) 2019-12-16 08:38:25 -05:00
ycheng2020andSteve Chavez 30d241fcff Fixed the pg_listen syntax (#285)
* Fixed the pg_listen syntax

Can't run killall -SIGUSR1 postgrest: No such file or directory

Error happens because pg_listen needs the full path to killall.
2019-12-08 01:00:02 -05:00
Jean SIMARDandSteve Chavez a0091f61a1 Typo (repeated word) 2019-11-26 11:33:28 -05:00
Danilo AmorosoandSteve Chavez e1c9b8fe76 added documentation for server-unix-socket-mode config option 2019-11-26 11:24:43 -05:00
steve-chavez a0179cfd4b Remove keepalive nginx recommendation 2019-11-22 10:59:24 -05:00
Evan SilbermanandSteve Chávez dbbba4e51a Specify units for the pool timeout setting 2019-11-14 14:52:35 -05:00
Fedor OrtyanovandSteve Chávez 2fc0e2f8cb fix api.rst other status from 500 to 400 2019-10-22 10:26:53 -05:00
Steve ChávezandGitHub 22b6ff764d Credit howtos/tuts authors (#264) 2019-10-18 11:03:32 -05:00
steve-chavez 3325a1bbc6 Add reference for mutation embed 2019-09-30 08:47:22 -05:00
steve-chavez 6afed0b30d Add reference for stored proc embedding 2019-09-30 08:47:22 -05:00
Lorenz HenkandSteve Chávez 4f1f80d4f2 Replace estimated with planned
The names changed according to https://github.com/PostgREST/postgrest/issues/1378#issuecomment-531506803
2019-09-19 11:47:22 -05:00
steve-chavez 5ef1db42ef Add estimated count reference 2019-09-18 14:19:40 -05:00
steve-chavez 476af62326 Add planned count reference 2019-09-18 14:19:40 -05:00
steve-chavez 2186a7e1a8 Add upcoming release page
* Add HEAD support mention
* Add change for bulk call
2019-09-18 14:19:40 -05:00
Reuben Thomas-DavisandSteve Chávez 1a18ef5a20 add server proxy uri env var for smoother swagger-ui use with docker-compose 2019-09-16 09:52:51 -05:00
Steve ChávezandGitHub bc6e181d03 Add params=multiple-objects to api reference (#253) 2019-09-11 12:05:51 -05:00
Steve Chávez 126236c3d0 Update v6.0.2.rst 2019-08-26 13:54:25 -05:00
steve-chavez e81ab0d0bb Fix #246, add CONTRIBUTING.md
Also add structure section on README.md
2019-08-26 13:37:11 -05:00
Steve Chávez 7dd37c0bc4 Update index.rst 2019-08-26 12:04:33 -05:00
steve-chavez 0d4b1d8f92 Add release notes for v6.0.2
Also add relase notes section at index.
2019-08-26 10:28:03 -05:00
steve-chavez b9c9aee645 Reorder configuration section 2019-08-26 10:28:03 -05:00
steve-chavez 5942db7fa7 Collapse index sections and improve the wording 2019-08-26 10:28:03 -05:00
steve-chavez 7805b99d57 Fix #213, reorganize index 2019-08-26 10:28:03 -05:00
steve-chavez 8271885bb2 Remove some elements of the index page
As mentioned in https://github.com/PostgREST/postgrest-docs/issues/249,
the embracing the relational model sectin would better fit in a
page about our REST style.

The shared improvements section no longer seems relevant since
we're already an established open source project.

Release notes are not removed but hidden from the index page.
2019-08-26 10:28:03 -05:00
steve-chavez 4fe34079d8 Reorganize ecosystem section 2019-08-26 10:28:03 -05:00
steve-chavez 2d6c16c2a6 Fix #234, reference for raw-media-types 2019-08-26 10:28:03 -05:00
steve-chavez b38e29c3d1 Add text/plain reference
Also move binary output to a top heading.
2019-08-26 10:28:03 -05:00
steve-chavez afff7a00a4 Put accessing and setting headers together 2019-08-26 10:28:03 -05:00
steve-chavez 51c0ad3e0c Add specify columns reference 2019-08-26 10:28:03 -05:00
steve-chavez 2414c7f7f0 Add bulk call reference 2019-08-26 10:28:03 -05:00
steve-chavez a8b2ed313e Add db-pool-timeout config 2019-08-26 10:28:03 -05:00
steve-chavez eca325c11b Add materialized views mention 2019-08-26 10:28:03 -05:00
steve-chavez f5868bc277 Add server-unix-socket config 2019-08-26 10:28:03 -05:00
steve-chavez abdc2ac2a9 Remove integrations section 2019-08-26 10:28:03 -05:00
steve-chavez bed1013ecd Fix #235, casting type to json object 2019-08-26 10:28:03 -05:00
steve-chavez cb2bf809a7 Fix #219, how-to for embedding table from other schema 2019-08-26 10:28:03 -05:00
steve-chavez 396b0468ce Refine embedding views section 2019-08-26 10:28:03 -05:00
steve-chavez 5c22846e12 Fix #172, add section on embedding views 2019-08-26 10:28:03 -05:00
steve-chavez aba2f43c10 Fix #230, make clear FKs are needed for embedding 2019-08-26 10:28:03 -05:00
steve-chavez 664604e6ca Fix #212, note about view with complex RULEs 2019-08-26 10:28:03 -05:00
steve-chavez a1509dc731 Fix #170, remove no performance penalty claim 2019-08-26 10:28:03 -05:00
steve-chavez e9712b0aff Fix #200, anon permissions on auth section 2019-08-26 10:28:03 -05:00
steve-chavez 91e44f12ec Fix #216, remove HUP reference 2019-08-26 10:28:03 -05:00
steve-chavez 7ccc8c4610 Fix #197, add note about axios url encoding 2019-08-26 10:28:03 -05:00
steve-chavez 3babff99b9 Fix #198, add note about nginx config location 2019-08-26 10:28:03 -05:00
steve-chavez 1fd06ff65d Fix #199, db-extra-search-path clarification 2019-08-26 10:28:03 -05:00
steve-chavez 03905a584e Fix #224, remove STRICT from example rpc 2019-08-26 10:28:03 -05:00
steve-chavez b07d07f17d Fix #231, add note about assuming text in rpc calls 2019-08-26 10:28:03 -05:00
steve-chavez f983e0af34 Fix #196, add virtual columns a.k.a. 2019-08-26 10:28:03 -05:00
steve-chavez 0b5e168c8d Fix #205, operators table with heading 2019-08-26 10:28:03 -05:00
Erwan ThomasandSteve Chávez f759b8bfc6 Fix miscellaneous Sphinx warnings (#244)
* /index.rst:24: WARNING: Line block ends without a blank line.

* /install.rst:300: WARNING: Explicit markup ends without a blank line; unexpected unindent.

* /admin.rst:273: WARNING: Could not lex literal_block as "http". Highlighting skipped.

* /tutorials/tut1.rst:150: WARNING: Could not lex literal_block as "json". Highlighting skipped.

* Remove extra newline

* Use integer value as epoch in JSON snippet

Even though using a string value is convenient (due to the lack of JSON
comments), it is confusing since the value should actually be an
integer. A slightly more verbose documentation is therefore preferable.
2019-08-18 16:32:08 -05:00
stefan8888andSteve Chávez ca456ecc51 Updated Docker section (#236)
* Updated Docker section

On macOS, it is also necessary to add the IP address in  pg_hba.conf
2019-07-29 18:15:00 +00:00
Eduardo JorgeandSteve Chávez 5ad1afbf73 Add websearch_to_tsquery doc (#226) 2019-07-24 16:02:58 +00:00
Eduardo JorgeandSteve Chávez 59816e6576 Add missing doc for the ov operator in array types (#225) 2019-07-04 15:14:18 -05:00
steve-chavez ecb4f15de0 Add CYBERTEC as Sponsor 2019-06-19 21:11:46 -05:00
steve-chavez c21e98c9ae Correct url 2019-06-16 15:09:49 -05:00
steve-chavez 2cc48151dd Add 2ndQuadrant as Sponsor 2019-06-15 18:10:37 -05:00
Anupam GargandSteve Chávez 93e457cd89 add Datrium client library and testimonial
we've been using PostgREST in internal production
infrastructure at Datrium for a few years now.
so, we're giving thanks in the form of a testimonial,
and providing a link to a python-based postgrest client
we developed and use.
2019-06-01 23:05:26 -05:00
steve-chavez 3dde972d31 Add Nimbus - In Production 2019-05-27 11:28:19 -05:00
Steve ChávezandGitHub 7d8bceea10 Update README.md 2019-05-23 17:55:07 -05:00
krasergeandsteve-chavez 3b8ec49fba SQL inside pgjwt (#207)
Correct url https://github.com/michelp/pgjwt/blob/master/pgjwt--0.1.0.sql
2019-04-14 11:13:06 -05:00
Hao Wuandsteve-chavez b77149d48e update doc based on postgrest/issues/1253 (#206) 2019-03-15 08:54:05 -05:00
Paulo VieiraandSteve Chávez 3d734c44cf clarify the usage of upsert when the table uses a surrogate key 2019-03-14 09:55:41 -05:00
steve-chavez f32c9c7967 Remove Explicit Qualification section 2019-03-06 10:30:41 -05:00
steve-chavez c0fe0a5ce1 Add repo in default.nix 2019-03-05 11:36:14 -05:00
steve-chavez a8d209cd1c Add translations section 2019-03-05 10:42:06 -05:00
Steve ChávezandGitHub 1c357179fd Add TimescaleDB tutorial (#201)
* Add TimescaleDB sponsorship
2019-03-01 16:18:20 -05:00
steve-chavez 44b825b939 Add Simply Connected Systems 2019-01-24 19:07:54 -05:00
steve-chavez a106edc5d0 Add release notes 2019-01-06 20:58:07 -05:00
steve-chavez 367b259bd4 Further clarify db-extra-search-path 2019-01-06 20:58:07 -05:00
steve-chavez 4119538ab7 Add section for table/columns with spaces 2019-01-06 20:58:07 -05:00
steve-chavez 2dcb5ee746 Fix #180, note about volatility marker 2019-01-06 20:58:07 -05:00
steve-chavez 474b8e6426 Add chinese translation link 2019-01-06 20:58:07 -05:00
steve-chavez 9e9f913c9e Fix #150, add example for url encoded payload 2019-01-06 20:58:07 -05:00
steve-chavez 24a5a27977 Fix #183, change immediate revocation request to PATCH 2019-01-06 20:58:07 -05:00
steve-chavez 14cb86d147 Fix #182, change default port of tutorials to 5433 2019-01-06 20:58:07 -05:00
steve-chavez ff74567473 Fix #145, add authenticator role to tutorials 2019-01-06 20:58:07 -05:00
steve-chavez a163828c6c Fix #192, Add section for quoting filters.
Also reorder the Unicode Support section.
2019-01-06 20:58:07 -05:00
steve-chavez 702e055d43 Fix #191, Add db-extra-search-path config 2019-01-06 20:58:07 -05:00
steve-chavez 93c3c59134 Fix #190, Add option for db-uri from file 2019-01-06 20:58:07 -05:00
Lee Johnsonandsteve-chavez 3220373803 renamed to postgrest.conf 2018-11-26 09:32:02 -05:00
Lee Johnsonandsteve-chavez fed4c8c9af Added link to variables settings 2018-11-26 09:31:43 -05:00
Lee Johnsonandsteve-chavez eb81bbc464 Update to include Heroku deploy steps 2018-11-26 09:31:27 -05:00
Russell DaviesandSteve Chávez 6d1adaaa54 Clarify config and auth sections on JWKS.
See PostgREST/postgrest#1205.
2018-11-15 11:11:24 -05:00
steve-chavez 9475f53fd7 Clarify important note about SIGHUP 2018-11-08 10:42:51 -05:00
Steve ChávezandGitHub 215bc80ff1 Move intro to index and add shields (#184)
* Add supporting development section
2018-10-21 17:54:21 -05:00
steve-chavez 89c62aa7e3 Add a workaround for RLS in views 2018-09-24 09:09:24 -05:00
Kyle JohnsonandSteve Chávez f2e81062a0 Further clarify view RLS interaction 2018-09-24 08:38:55 -05:00
Kyle JohnsonandSteve Chávez 8752069934 Tweak view RLS warning 2018-09-24 08:38:55 -05:00
Kyle JohnsonandSteve Chávez dc9a285825 Note Postgres' (current) RLS limitations for views 2018-09-24 08:38:55 -05:00
steve-chavez 73e59a1643 Add pipenv instructions 2018-09-21 13:46:53 -05:00
steve-chavez 518b465ffa Fix highlighting and move running the server header 2018-09-20 10:47:52 -05:00
steve-chavez a1d4b3ed34 Add #fff background for snippets 2018-09-20 10:47:52 -05:00
steve-chavez 4b37af8f73 Fix #104, default privileges on functions 2018-09-20 10:47:52 -05:00
steve-chavez 7cff51c002 Fix some code highlighting and add computed col ref 2018-09-20 10:47:52 -05:00
steve-chavez d5365b6ead Reorder stored procedures section 2018-09-20 10:47:52 -05:00
steve-chavez d0c0312e35 Change server-host default 2018-09-20 10:47:52 -05:00
steve-chavez efb39e5e12 Add SIGHUP deprecation notice 2018-09-20 10:47:52 -05:00
steve-chavez 7052446abf Fix #160, reorder reloading note for functions 2018-09-20 10:47:52 -05:00
steve-chavez cf220c5a91 Fix #164, overloaded functions/named parameters 2018-09-20 10:47:52 -05:00
steve-chavez 83183ec8c6 Fix #171, postgres logging in docker 2018-09-20 10:47:52 -05:00
steve-chavez 0ec963b295 Fix #105, correct command for running postgrest 2018-09-20 10:47:52 -05:00
steve-chavez 8670ce6ffe Highlight 32 chars long and fix indentation 2018-09-20 10:47:52 -05:00
steve-chavez 9337f63823 Fix #153, add systemd service file 2018-09-20 10:47:52 -05:00
steve-chavez d78862996f Fix #165, add schemas for sign/login 2018-09-20 10:47:52 -05:00
steve-chavez 5e2f3b8d59 Fix #166, reorder docker instructions 2018-09-20 10:47:52 -05:00
steve-chavez bca1ddf0d6 Fix #168, Rename SSL to HTTPS 2018-09-20 10:47:52 -05:00
steve-chavez a924c4b12f Fix #173, add ref for jwt claim access 2018-09-20 10:47:52 -05:00
steve-chavez c9816f1661 Hyperlink config settings 2018-09-20 10:47:52 -05:00
steve-chavez 38610e0349 Change type of notes for reloading and deleting/updating 2018-09-20 10:47:52 -05:00
steve-chavez 99d878b13e Fix #175, add important note for computed column 2018-09-20 10:47:52 -05:00
steve-chavez 48ab4e91be Add header for JSON select feature 2018-09-20 10:47:52 -05:00
steve-chavez 24f796a329 Remove app.settings mention of being session scoped 2018-09-20 10:47:52 -05:00
steve-chavez c4e926af2d Update postgrest repo links 2018-09-20 10:47:52 -05:00
steve-chavez 54436e2dc6 Add default.nix and udpate README 2018-09-10 10:47:03 -05:00
steve-chavez bba1d35ade Fix #178, Add livereload script 2018-09-10 10:46:38 -05:00
steve-chavez 512862918f Change default theme to readthedocs 2018-09-10 09:55:45 -05:00
steve-chavez 02f7cba3d2 Fix install broken link and add rst cheatsheet 2018-09-06 13:26:48 -05:00
Steve PhillipsandSteve Chávez 7845bdce8c auth.rst typo: paramter -> parameter 2018-08-06 10:27:16 -05:00
PJLindsayandSteve Chávez a7fd694f19 Update tut0.rst (#159)
* Update tut0.rst

Add hint about port mapping for users with pre-existing PostgreSQL DB
2018-07-13 13:06:04 -05:00
steve-chavez cfaf588bba Add json operators to vertical filtering section 2018-06-19 12:40:08 -05:00
steve-chavez be039152f2 Improve explicit qualification section 2018-06-15 11:52:39 -05:00
steve-chavez c7c6ee40e4 Add entries to the dict 2018-06-14 09:29:12 -05:00
ASVBPREAUBVandSteve Chávez 0e16f34eef Make swagger-gui an optional step in installation 2018-06-14 09:09:13 -05:00
Francois-Guillaume RibreauandSteve Chávez 92cc815e9d Add MotionDynamic (PostgREST + SubZero) 2018-06-10 14:25:10 -05:00
steve-chavez f84b79ce41 Add stored function explicit qualification 2018-05-31 10:18:16 -05:00
steve-chavez d03770d352 Bump version to v5.0.0 2018-05-28 17:37:11 -05:00
steve-chavez c71bbba979 Some corrections and better wording 2018-05-28 17:25:21 -05:00
steve-chavez b11f9ef386 Fix #137, unix socket connection 2018-05-28 13:26:18 -05:00
steve-chavez 625a0b2393 Fix #136, sslmode on db-uri 2018-05-28 13:26:18 -05:00
steve-chavez 338e8a1ae3 Add casting example 2018-05-28 13:26:18 -05:00
steve-chavez 036cc1c5d7 Fix #107, Alias column with : 2018-05-28 13:26:18 -05:00
steve-chavez ed028234cc Add example of filtering function response 2018-05-28 13:26:18 -05:00
steve-chavez 121f192b93 Fix #127, RPC cache dependency 2018-05-28 13:26:18 -05:00
steve-chavez 7255f02610 Fix #126, update note about arrays 2018-05-28 13:26:18 -05:00
steve-chavez 6e7a2ca26c Fix #135, clarify usage of GET/POST RPC 2018-05-28 13:26:18 -05:00
steve-chavez 5e856a22a8 Fix #132, remove deprecation notices 2018-05-28 13:26:18 -05:00
steve-chavez 7948730770 Add embeds alias feature 2018-05-28 13:26:18 -05:00
steve-chavez 1108aede5b Install only necessary deps for BSD and OSX 2018-05-28 13:26:18 -05:00
steve-chavez c0f8e64bbb Add limit/offset and and/or to embedded resources 2018-05-28 13:26:18 -05:00
steve-chavez dbec5e08aa Fix #131, SCHEMA comment and summary/description 2018-05-28 13:26:18 -05:00
steve-chavez 2f699fa115 Add foreign tables in OpenAPI feature 2018-05-28 13:26:18 -05:00
steve-chavez 6f0a25520a Add UPSERT feature 2018-05-28 13:26:18 -05:00
steve-chavez e56313196b Add role-claim-key feature 2018-05-28 13:26:18 -05:00
steve-chavez 736a5020b0 Add app.settings.* config value feature 2018-05-28 13:26:18 -05:00
agent3boodandsteve-chavez b32ba7a409 Add volume to docker-compose 2018-05-23 09:17:27 -05:00
agent3boodandsteve-chavez e0e4d68185 update PGRST_DB_ANON_ROLE in docker-compose
anon should not be the default db user
2018-05-23 09:16:47 -05:00
Ken Fehlingandsteve-chavez 28c39e976c Update docker-compose example to version 3
Adds "depends_on"
2018-05-21 08:11:45 -05:00
Hasan PekdemirandSteve Chávez 88e3c8c4b6 add triggerfs to production apps in examples 2018-05-17 10:23:47 -05:00
Joe Nelson 1fb9e34c9c Add new oauth server 2018-03-29 00:40:54 -05:00
ThomasandJoe Nelson 0bae76f05e Remove iAdvize from In Production list (#125) 2018-03-14 12:12:03 -05:00
Joe NelsonandGitHub 7b2ab948be Schema auto-reload instructions (#124) 2018-03-11 12:26:16 -05:00
Christopher BowmanandJoe Nelson 16cf1ef45c Replace 'to to ' with 'to the ' (#122) 2018-03-09 19:42:01 -06:00
Camille RousselandJoe Nelson 7151e62499 Update tut0.rst with improved instructions for windows installs (#120) 2018-02-03 21:52:51 -08:00
Joe Nelson 911417471e Add Eric's testimonial 2018-02-03 13:55:32 -08:00
Joe Nelson 7dbd5f799e Update name of diogob's websocket adapter 2018-02-02 19:57:24 -08:00
Joe Nelson 362ee5a4ed Bump version 2018-01-18 10:59:27 -06:00
Joe NelsonandGitHub e10599d065 Changes in 4.4 release (#121)
* Updated full-text search

* Calling RPC with GET

* Customizing HTTP status codes and headers

* Move the admin section to bottom of TOC

* Revise JWT signing section of tutorial

* Selecting pkeys in embedding no longer required
2018-01-18 10:48:34 -06:00
Damien BryandJoe Nelson f0bf51efc2 Added Elyios as using PostgREST in production (#119) 2017-12-27 21:56:04 -06:00
Captain JustinandJoe Nelson d9e7620160 Update intro.rst (#118) 2017-11-28 23:48:31 -06:00
Joe NelsonandGitHub f93e2723e3 Add note that windows people need postgres on path (#117) 2017-11-25 22:00:55 -06:00
Joe Nelson e48a206075 Use parens for IN operator
Paren-free is deprecated
2017-11-04 23:17:39 -05:00
Brian ThorneandJoe Nelson 82d2d781be Fix typo in api.rst (#113) 2017-11-04 00:59:04 -05:00
Joe Nelson 59ab74b861 Add items to ecosystem 2017-10-08 13:35:35 -05:00
Joe NelsonandGitHub a3d87edda3 Explain how sql comments appear in the openapi output (#111) 2017-10-08 12:38:46 -05:00
Joe NelsonandGitHub 9598e3948d Show how to use a JWK literal in the config file (#110) 2017-10-07 19:59:30 -05:00
Joe NelsonandGitHub e7ddea0acf Document long jwt secrets as required (#109)
* Use long jwt secrets as required

* Fix spelling and adjust custom dictionary
2017-10-07 13:03:30 -05:00
Russell DaviesandJoe Nelson 922ae0e0c9 Update JWT configuration section for JWK and aud (#106) 2017-09-29 00:53:03 -05:00
Joe Nelson edefd3040c Section about new FTS features
Fixes #61
2017-09-09 21:27:36 -05:00
Joe Nelson a93ddbee5a Unicode
Fixes #62
2017-09-09 20:52:12 -05:00
Joe Nelson 45ddafc2a8 How to determine server version
Fixes #63
2017-09-09 20:36:10 -05:00
Joe Nelson 5185a92798 Move config section to install page
Document special host binding addresses

Fixes #83
2017-09-09 20:21:46 -05:00
Joe Nelson 0da8cb230f Proper error code for failed content negotiation
Fixes #95
2017-09-09 19:49:42 -05:00
Joe Nelson e4741d43e4 Note for windows users 2017-09-09 19:30:20 -05:00
Joe Nelson 5fc48057f8 Actually pg 9.5 is needed, not 9.3 2017-09-09 15:41:05 -05:00
Joe Nelson 973e7cb90e How to use docker 2017-09-09 15:40:49 -05:00
Will O'BrienandJoe Nelson 4b1e594270 Add notice about reverting OIDC default (#99) 2017-09-05 22:25:43 -05:00
Russell DaviesandJoe Nelson 3fdf6acc45 Range operators and deprecation of symbol operators (#98) 2017-08-20 14:49:27 -05:00
Joe NelsonandGitHub 66ce8e8b18 Exp claim must be an int, not a string
Pointed out by @nileshtrivedi
2017-08-20 14:15:59 -05:00
Russell DaviesandJoe Nelson aedaca1290 Clarify resource embedding constraints (#97) 2017-08-13 11:39:18 -05:00
Priyank PurohitandJoe Nelson 84bfa2d9ca Updated docs for complex logic API capability (#94) 2017-08-05 20:42:31 -05:00
Steve ChávezandJoe Nelson 4be05649f4 Add documentation for binary output in rpc, Fix #84 (#92) 2017-07-20 00:06:57 -05:00
Joe Nelson cdf5dece65 Include link to next tutorial 2017-07-18 22:32:13 -05:00
Chris StryczynskiandJoe Nelson 49a62772c0 Single quotes give an error (#88)
of postgrest: ParseError "postgrest.config" "endOfInput"
2017-07-08 00:14:30 -05:00
Joe Nelson aa6e3afc0e Small edit and correct config file name 2017-07-04 22:49:19 -05:00
Joe Nelson cb4c54074a Tutorial 1 2017-07-04 22:28:17 -05:00
Richard FoxandJoe Nelson 71da89fdcc intro.rst: Correct first example app link (#87) 2017-07-04 17:48:54 -05:00
Joe Nelson 6382b597fa Zeroeth tutorial 2017-07-02 21:17:49 -05:00
Joe Nelson cee92cac05 How to read headers/cookies from a proc 2017-06-18 22:19:46 -05:00
Joe Nelson e8cdd4463b Example of quoted comma in IN operator 2017-06-18 21:52:53 -05:00
Joe Nelson 127fbb41d5 Note function volatility in RPC
Fixes #64
2017-06-18 12:06:21 -05:00
Joe Nelson 83e4ad41fe Deprecate {} for resource embedding 2017-06-18 11:49:08 -05:00
Leon du ToitandJoe Nelson f4c6a99adb Address JWT security in docs, related to postgrest issue #842 (#79) 2017-06-08 01:55:42 -05:00
Joe Nelson 174ccadb15 Update ecosystem 2017-05-29 18:09:08 -05:00
Steve PhillipsandJoe Nelson cb90e3e557 api.rst: de-duped a word, added commas (#78) 2017-05-29 17:28:37 -05:00
Steve PhillipsandJoe Nelson 49af7dcbc2 api.rst: Added example alluded to in docs (#77) 2017-05-29 17:28:31 -05:00
Michel PelletierandJoe Nelson e35f2d28c7 Use current_setting optional param to suppress raise (#70) 2017-05-29 17:27:18 -05:00
Steve PhillipsandJoe Nelson 6bb81b5d4b api.rst typo: Directories -> Directors (#74) 2017-05-27 10:26:45 -05:00
James DaltonandJoe Nelson 3cb2c0f297 switch tar command for xz instead of gzip (#73) 2017-05-24 22:56:29 -05:00
Matt BretlandJoe Nelson 1a5cadb855 auth.rst: minor fixes to example scripts (#68) 2017-05-16 22:02:07 -05:00
Steve PhillipsandJoe Nelson fc65694c0a api.rst typo: delting -> deleting (#54) 2017-04-23 22:31:03 -05:00
Steve PhillipsandJoe Nelson f2f392b0f4 api.rst typo: dahsboard -> dashboard (#53) 2017-04-23 22:30:51 -05:00
Joe Nelson 8f5a3f50c2 Another queue bridge 2017-04-23 21:45:47 -05:00
Joe Nelson 2ce053b69e Add some things people have said 2017-04-23 20:25:44 -05:00
Joe Nelson bfe6bd1165 Confirmed more production users 2017-04-23 20:12:42 -05:00
Will O'BrienandJoe Nelson f52829d165 App metadata instead of user metadata (#55)
From the [docs](https://auth0.com/docs/metadata):
> An authenticated user can modify data in their profile's user_metadata, but not in their app_metadata.

Seems role-type information should be stored in `app_metadata`.
2017-04-21 16:46:15 -05:00
Joe Nelson 625f2ce8d7 Update subzero message 2017-04-05 23:07:30 -05:00
Ruslan TalpaandJoe Nelson 42dd4ab607 subzero domain change (#47) 2017-04-05 22:57:48 -05:00
Steve ChávezandJoe Nelson 8a6b429c16 Add example for complex boolean logic (#52) 2017-04-04 23:25:22 -05:00
Dan KamenovandJoe Nelson 1cab8cf82d Fix Bad SQL coding practices in "Computed Columns" example (#51) 2017-03-29 21:51:39 -05:00
Dan KamenovandJoe Nelson 27bcd8074f Fix duplicate wording (#48) 2017-03-26 20:28:52 -07:00
Joe Nelson 0f87137387 More improvements
When to use RAISE in procs

Fix broken links
2017-03-26 16:05:12 -07:00
Joe Nelson e54fb2a264 Misc improvements
How to pass a single json object to stored proc

List HTTP codes for db errors

Point out 404 semantics of singular responses

OR query workaround

Include nginx example for singular rewrite
2017-03-25 22:57:27 -07:00
Steve ChávezandJoe Nelson 8e6410e55d Add section for binary output (#46) 2017-03-24 14:14:28 -07:00
Joe Nelson 708e0cd0b6 Another site in production 2017-03-16 00:33:54 -07:00
Joe NelsonandJoe Nelson 8b170afe49 More extensions, example apps, client side libs (#45) 2017-03-13 09:51:52 -07:00
Joe Nelson b8f2ffc0a3 Instructions for building docs locally 2017-02-27 09:38:21 -08:00
Sushant BajracharyaandJoe Nelson f1181cce73 Added a / after location /api (#44) 2017-02-26 08:38:26 -08:00
PeterandJoe Nelson ecbf49ad7f replace code:postgres by code:sql (#43)
Code blocks with code:postgres are not highlighted (see site navigation), not works. Replaced by code:sql that works "fine"
2017-02-20 14:33:37 -08:00
Joe Nelson d461e3387f Note the need for percent encoding in passwords 2017-02-19 18:11:40 -08:00
Tony AdamsandJoe Nelson 022e1101e7 fix a missing infinitive (typo) in intro.rst (#36) 2017-02-14 21:35:05 -08:00
Hugo DiasandJoe Nelson 6e1e8f02de fix: fix server-proxy-uri config (#35) 2017-02-10 09:49:56 -08:00
Joe Nelson 01def80937 Google translate example 2017-02-06 11:05:45 -08:00
Joe Nelson 7742891c26 safeupdate via PGXN 2017-02-06 10:56:41 -08:00
Joe Nelson b237a4943c More client side libs 2017-02-06 10:29:45 -08:00
Joe Nelson 07777ea76b Note websockets postgres integration
From https://github.com/begriffs/postgrest/issues/278
2017-02-03 16:56:25 -08:00
Joe Nelson 588b0bc7e1 Fix internal links 2017-02-03 16:37:24 -08:00
Joe Nelson e508f071b4 Bump copyright year 2017-02-03 16:14:41 -08:00
Lucas DesgouillesandJoe Nelson 892f4a8491 Override document title for index.rst (#34)
The index page has `<no-title> -- PostgREST 0.4.0.0 Documentation` for HTML title, using the `title` directive, we can force it to something nicer.
I'm not sure if this fixes it at the top of the page.

http://docutils.sourceforge.net/docs/ref/rst/directives.html#metadata-document-title
http://www.sphinx-doc.org/en/stable/rest.html#directives
2017-02-02 08:02:43 -08:00
philandJoe Nelson 404fcb6b27 Fix the plurality header docs for v0.4 (#32) 2017-01-26 07:32:27 -08:00
Leon du ToitandJoe Nelson 3262607b5b Document connect strings for older versions of libpq (#11) (#31) 2017-01-23 08:34:39 -08:00
Joe Nelson e56ffe7b5e Note json array vs native array args 2017-01-22 20:36:27 -08:00
Joe Nelson 19768064dd More prominent link to downloads 2017-01-22 20:16:57 -08:00
Joe Nelson 71816e64f8 Fix typos in auth section
Fixes #29
2017-01-22 17:32:38 -08:00
Joe Nelson e1e1ee2d31 pg-sns-bridge rename 2017-01-21 23:00:13 -08:00
Joe Nelson e37a2a569c Document rate limiting via nginx 2017-01-21 20:16:21 -08:00
Joe Nelson 58503af432 English and RST adjustments 2017-01-16 20:47:01 -08:00
Joe Nelson e0e604aa9f Fix install problems reported by @tnhu 2017-01-16 20:35:42 -08:00
Joe Nelson b3dfde5ecf Move admin section higher in TOC 2017-01-16 20:35:17 -08:00
Joe Nelson 360c90afe3 Auth0 no longer base64 encodes secrets 2017-01-16 20:35:01 -08:00
Joe Nelson 8706779b42 Document SSH session termination precautions 2017-01-16 20:34:39 -08:00
JeffreyandJoe Nelson f52fb70e3d Suggest swap file on systems with under 1GB of ram (#30) 2016-12-26 09:40:23 -08:00
NikolayandJoe Nelson b3fb9ff215 more about stored procedures (#26) 2016-12-20 21:14:05 -08:00
J Phani MaheshandJoe Nelson 4d8272fa0d fix typo in install.rst: s/text/text/ (#27) 2016-12-17 09:16:03 -08:00
Trevor BasingerandJoe Nelson 349726cdc0 Documentation b64 option #772 (#25) 2016-12-11 08:56:39 -08:00
Joe Nelson adb8522276 Sorting embedded resources 2016-12-05 16:14:28 -08:00
Joe Nelson e84b4cbcfe Fill out the API ops 2016-12-04 18:34:35 -08:00
Joe Nelson 6b255e9806 Mark inline code as code, not italics 2016-12-04 13:59:24 -08:00
Joe Nelson 564c51fe79 Stored procs 2016-12-04 13:34:33 -08:00
Joe Nelson 2c1eb9ab13 Add queueing bridges to docs 2016-12-02 15:50:02 -08:00
Joe Nelson 1f12dedce6 Include Ruslan's env_var helper function in note 2016-12-02 10:15:12 -08:00
Joe Nelson 8c2a95b98e Test suite instructions from @dsimunic 2016-11-30 21:21:57 -08:00
Joe Nelson 5b95d22e2a Base nginx conf from Ruslan 2016-11-27 12:28:10 -08:00
Joe Nelson 5a31320a8b TeX description 2016-11-25 15:02:00 -08:00
Joe Nelson 6a2ba25414 Custom CSS 2016-11-25 15:01:52 -08:00
Joe Nelson b35ffd4931 First draft of resource embedding 2016-11-21 23:04:06 -08:00
Joe Nelson 455dc5c8bc OpenAPI overview 2016-11-20 22:41:05 -08:00
Joe Nelson dacf39404e Singular or plural 2016-11-20 22:03:04 -08:00
Joe Nelson 216550e959 Content negotiation 2016-11-20 21:39:35 -08:00
Joe Nelson 2a77ff5714 Schema cache rewrite 2016-11-20 16:37:18 -08:00
Joe Nelson 684a9f9566 Spell check, WIP Circle CI for sphinx 2016-11-20 14:26:50 -08:00
Joe Nelson 79de60db58 The -c param is no more 2016-11-20 11:18:29 -08:00
Joe Nelson d1d6001a6d Alternate url structure 2016-11-19 12:04:10 -08:00
Raphael SchmittandJoe Nelson 954252ed16 corrected url (#24) 2016-11-18 09:22:51 -08:00
Joe Nelson aed5618d28 Suggest pg-safeupdate rather than nginx 2016-11-13 22:44:18 -08:00
Joe Nelson 8258631b03 Schema reloading 2016-11-13 18:11:50 -08:00
Joe Nelson 0ae281f15f Debugging steps (sql logging, ngrep) 2016-11-13 17:19:13 -08:00
Joe Nelson e5d4697507 Config section in admin page 2016-11-02 21:51:37 -07:00
Joe Nelson d38bfc8cf3 Notes for future admin section 2016-10-31 22:50:38 -07:00
Joe Nelson 5919a37197 Remove signups and user editing
Too complicated for this section
2016-10-31 22:43:41 -07:00
Joe Nelson 2c53cb4fae Fix highlighting, typo in current_user 2016-10-28 17:54:32 -07:00
Joe Nelson 8a606f7223 Discuss group/user roles 2016-10-28 17:18:41 -07:00
Joe Nelson 267c482cfe Use plpgsql language type when applicable 2016-10-24 15:26:40 -07:00
Joe Nelson fda3e58619 Fix code block lexing 2016-10-24 15:23:44 -07:00
Joe Nelson d152689038 More about schema isolation 2016-10-24 14:50:22 -07:00
Joe Nelson f882954019 SQL user management section 2016-10-24 14:23:44 -07:00
Joe Nelson 6e7349d76c SSL 2016-10-16 13:54:05 -07:00
Joe Nelson be869d3f54 JWT generation 2016-10-16 13:18:21 -07:00
Joe Nelson d00bb026b6 pre-request function docs 2016-10-15 22:48:22 -07:00
Joe Nelson 98a776f2dc Overview of role system 2016-10-15 16:54:36 -07:00
Joe Nelson 3025e18b3a Alpine linux warning 2016-10-14 13:37:51 -07:00
Joe Nelson 5cd719bdff Limits and offsets 2016-10-10 11:14:11 -07:00
Joe Nelson c0791a5f21 WIP: api page 2016-10-10 10:30:31 -07:00
Joe Nelson 6e82a55d68 Installation page 2016-10-10 09:56:55 -07:00
Joe Nelson 0060e8906d Allow RTD to use its nicer theme 2016-10-10 01:22:52 -07:00
Joe Nelson 577cf29f64 Intro section 2016-10-10 01:15:33 -07:00
Joe Nelson debf4dc715 Adjustment 2016-10-09 22:16:13 -07:00
Joe Nelson 7611308b0e Sphinx quickstart 2016-10-09 16:53:41 -07:00
179 changed files with 12204 additions and 5407 deletions
-15
View File
@@ -1,15 +0,0 @@
freebsd_instance:
image_family: freebsd-13-1
build_task:
name: Build FreeBSD (Stack)
install_script: pkg install -y postgresql13-client hs-stack git
stack_cache:
folders: /.stack
fingerprint_script: cat postgrest.cabal stack.yaml.lock
reupload_on_changes: false
build_script: stack build -j 1 --local-bin-path . --copy-bins
bin_artifacts:
path: postgrest
+1 -1
View File
@@ -2,5 +2,5 @@
When submitting a new feature or fix:
- Add a new entry to the CHANGELOG - https://github.com/PostgREST/postgrest/blob/main/CHANGELOG.md#unreleased
- If relevant, update the docs - https://github.com/PostgREST/postgrest-docs
- If relevant, update the docs
-->
-23
View File
@@ -1,23 +0,0 @@
name: Setup Nix
description: Installs nix, sets up cachix and installs a subset of tooling.
inputs:
authToken:
description: Token to pass to cachix
tools:
description: Tools to install with nix-env -iA <tools>
runs:
using: composite
steps:
- uses: cachix/install-nix-action@v18
with:
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
- uses: cachix/cachix-action@v12
with:
name: postgrest
authToken: ${{ inputs.authToken }}
- if: ${{ inputs.tools }}
run: nix-env -f default.nix -iA ${{ inputs.tools }}
shell: bash
-18
View File
@@ -1,18 +0,0 @@
codecov:
branch: main
require_ci_to_pass: false
comment: false
coverage:
status:
project:
default:
target: auto
threshold: 1%
only_pulls: false
patch:
default:
target: auto
threshold: 1%
only_pulls: true
-6
View File
@@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
-57
View File
@@ -1,57 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Get the FreeBSD PostgREST executable built by CirrusCI for the given GITHUB_COMMIT in GITHUB_REPOSITORY
# We use the GitHub API for 'check suites' to find the corresponding CirrusCI job, see:
# https://docs.github.com/en/rest/reference/checks#list-check-suites-for-a-git-reference
cirrus_artifact_name=bin
gh_auth_header="Authorization: Bearer $GITHUB_TOKEN"
gh_accept_header="Accept: application/vnd.github.v3+json"
get_gh_check_runs_url() {
gh_checks_list_url="https://api.github.com/repos/$GITHUB_REPOSITORY/commits/$GITHUB_COMMIT/check-suites"
>&2 echo "Getting list of check-suites from $gh_checks_list_url ..."
curl --fail -H "$gh_auth_header" -H "$gh_accept_header" "$gh_checks_list_url" \
| jq -r '.check_suites[] | select(.app.slug == "cirrus-ci") | .check_runs_url'
}
wait_for_cirrusci() {
gh_check_runs_url="$(get_gh_check_runs_url)"
>&2 echo "Waiting to CirrusCI run to complete (two hours maximum)..."
for _ in $(seq 1 120); do
echo "Checking for CirrusCI task status at $gh_check_runs_url ..."
status=$(curl --fail -H "$gh_auth_header" "$gh_check_runs_url" | jq -r '.check_runs[] | .status')
if [ "$status" == "completed" ]; then
break
else
echo "CirrusCI task is still $status, waiting..."
sleep 60
fi
done
}
# The CirrusCI taskid can change if a new check run is started for the same commit,
# e.g. when pushing both a branch and tag. We make sure that we have the very
# latest taskid by re-loading the 'gh_check_runs_url' and the 'check run' itself.
get_cirrus_taskid() {
gh_check_runs_url="$(get_gh_check_runs_url)"
>&2 echo "Getting the CirrusCI task id from $gh_check_runs_url ..."
curl --fail -H "$gh_auth_header" -H "$gh_accept_header" "$gh_check_runs_url" \
| jq -r '.check_runs[] | .external_id'
}
download_artifact() {
cirrus_task_id="$(get_cirrus_taskid)"
cirrus_artifact_url="https://api.cirrus-ci.com/v1/artifact/task/$cirrus_task_id/$cirrus_artifact_name.zip"
>&2 echo "Attemping to download the CirrusCI artifact from $cirrus_artifact_url ..."
curl --fail "$cirrus_artifact_url" -o freebsd.zip
}
wait_for_cirrusci
download_artifact
echo "Unpacking executable..."
unzip freebsd.zip -d .
rm -rf freebsd.zip
-12
View File
@@ -1,12 +0,0 @@
#!/usr/bin/env bash
# Tag a release that will be built with Github Actions. The version is
# read from 'postgrest.cabal'.
version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
echo "Tagging version v$version"
git tag -f "v$version"
echo "Pushing tag..."
git push -f origin "refs/tags/v$version"
-66
View File
@@ -1,66 +0,0 @@
#!/bin/bash
# This script builds PostgREST in a remote ARM server
[ -z "$1" ] && { echo "Missing 1st argument: PostgREST github commit SHA"; exit 1; }
[ -z "$2" ] && { echo "Missing 2nd argument: Build environment directory name"; exit 1; }
PGRST_GITHUB_COMMIT="$1"
SCRIPT_DIR="$2"
DOCKER_BUILD_DIR="$SCRIPT_DIR/docker-env"
CABAL_VERSION="3.6.0.0"
GHC_VERSION="9.2.4"
install_packages() {
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y git build-essential curl libffi-dev libffi7 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5 llvm libnuma-dev zlib1g-dev libpq-dev jq gcc
sudo apt-get clean
}
install_ghcup() {
export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
export BOOTSTRAP_HASKELL_MINIMAL=1
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
source ~/.ghcup/env
}
install_cabal() {
ghcup upgrade
ghcup install cabal $CABAL_VERSION
ghcup set cabal $CABAL_VERSION
}
install_ghc() {
ghcup upgrade
ghcup install ghc $GHC_VERSION
ghcup set ghc $GHC_VERSION
}
install_packages
# Add ghcup to the PATH for this session
[ -f ~/.ghcup/env ] && source ~/.ghcup/env
ghcup --version || install_ghcup
ghcup set cabal $CABAL_VERSION || install_cabal
ghcup set ghc $GHC_VERSION || install_ghc
cd ~/$SCRIPT_DIR
# Clone the repository and build the project
git clone https://github.com/PostgREST/postgrest.git
cd postgrest
git checkout $PGRST_GITHUB_COMMIT
cabal v2-update && cabal v2-build
# Copy the built binary to the Dockerfile directory
PGRST_BIN=$(cabal exec which postgrest | tail -1)
cp $PGRST_BIN ~/$DOCKER_BUILD_DIR
# Move and compress the built binary
mkdir -p ~/$SCRIPT_DIR/result
mv $PGRST_BIN ~/$SCRIPT_DIR/result
cd ~/$SCRIPT_DIR
tar -cJf result.tar.xz result
-16
View File
@@ -1,16 +0,0 @@
# PostgREST docker hub image
FROM ubuntu:focal AS postgrest
RUN apt-get update -y \
&& apt install -y --no-install-recommends libpq-dev zlib1g-dev jq gcc libnuma-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY postgrest /usr/bin/postgrest
EXPOSE 3000
USER 1000
CMD postgrest
-50
View File
@@ -1,50 +0,0 @@
#!/bin/bash
# This script publishes the Docker ARM images to Docker Hub.
[ -z "$1" ] && { echo "Missing 1st argument: PostgREST github commit SHA"; exit 1; }
[ -z "$2" ] && { echo "Missing 2nd argument: Docker repo"; exit 1; }
[ -z "$3" ] && { echo "Missing 3rd argument: Docker username"; exit 1; }
[ -z "$4" ] && { echo "Missing 4th argument: Docker password"; exit 1; }
[ -z "$5" ] && { echo "Missing 5th argument: Build environment directory name"; exit 1; }
[ -z "$6" ] && { echo "Missing 6th argument: PostgREST version"; exit 1; }
PGRST_GITHUB_COMMIT="$1"
DOCKER_REPO="$2"
DOCKER_USER="$3"
DOCKER_PASS="$4"
SCRIPT_DIR="$5"
PGRST_VERSION="v$6"
IS_PRERELEASE="$7"
DOCKER_BUILD_DIR="$SCRIPT_DIR/docker-env"
clean_env()
{
sudo docker logout
}
# Login to Docker
sudo docker logout
{ echo $DOCKER_PASS | sudo docker login -u $DOCKER_USER --password-stdin; } || { echo "Couldn't login to docker"; exit 1; }
trap clean_env sigint sigterm exit
# Move to the docker build environment
cd ~/$DOCKER_BUILD_DIR
# Push final images to Docker hub
# NOTE: This command publishes a separate ARM image because the builds cannot
# be added to the manifest if they are not in the registry beforehand.
# This image must be manually deleted from Docker Hub at the end of the process.
sudo docker buildx build --build-arg PGRST_GITHUB_COMMIT=$PGRST_GITHUB_COMMIT \
-t $DOCKER_REPO/postgrest:$PGRST_VERSION-arm \
--push .
# Add the arm images to the manifest
# NOTE: This assumes that there already is a `postgrest:<version>` image
# for the amd64 architecture pushed to Docker Hub
sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:$PGRST_VERSION $DOCKER_REPO/postgrest:$PGRST_VERSION-arm
[ -z $IS_PRERELEASE ] && sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:latest $DOCKER_REPO/postgrest:$PGRST_VERSION-arm
sudo docker logout
-78
View File
@@ -1,78 +0,0 @@
name: Cachix
# This workflow serves to
# - keep cachix up to date with the main branch
# - incrementally update cachix for large dependency
# updates, e.g. after running postgrest-nixpkgs-upgrade,
# which can cause the main CI workflow to time out
on:
workflow_dispatch:
push:
branches:
- main
- rel-*
tags:
- v*
jobs:
Seed-Cachix:
strategy:
fail-fast: false
matrix:
include:
- os: Linux
runs-on: ubuntu-latest
- os: MacOS
runs-on: macos-latest
name: Seed ${{ matrix.os }}
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Install cachix tooling
run: |
nix-env -f default.nix -iA devTools.pushCachix.bin
postgrest-push-cachix
- name: Seed dynamic postgrest build
run: |
nix-build -A postgrestPackage
postgrest-push-cachix
- name: Seed style tools
run: |
nix-build -A style
postgrest-push-cachix
- name: Seed test tools
run: |
nix-build -A tests
postgrest-push-cachix
- name: Seed static toolchain
if: matrix.os == 'Linux'
run: |
nix-build -A packagesStatic.haskellPackages.hello
postgrest-push-cachix
- name: Seed static postgresql build (for libpq)
if: matrix.os == 'Linux'
run: |
nix-build -A packagesStatic.pkgs.postgresql
postgrest-push-cachix
- name: Seed static postgrest build
if: matrix.os == 'Linux'
run: |
nix-build -A postgrestStatic
postgrest-push-cachix
- name: Build and push everything to Cachix
run: |
nix-build
postgrest-push-cachix
-530
View File
@@ -1,530 +0,0 @@
name: CI
on:
push:
branches:
- main
- rel-*
tags:
- v*
pull_request:
branches:
- main
- rel-*
jobs:
Lint-Style:
name: Lint & check code style
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: style
- name: Run linter (check locally with `nix-shell --run postgrest-lint`)
run: postgrest-lint
- name: Run style check (auto-format with `nix-shell --run postgrest-style`)
run: postgrest-style-check
Test-Nix:
name: Test (Nix)
runs-on: ubuntu-latest
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: tests
- name: Run coverage (IO tests and Spec tests against PostgreSQL 15)
run: postgrest-coverage
- name: Upload coverage to codecov
uses: codecov/codecov-action@v3.1.4
with:
files: ./coverage/codecov.json
- name: Run doctests
if: always()
run: nix-shell --run postgrest-test-doctests
- name: Check the spec tests for idempotence
if: always()
run: postgrest-test-spec-idempotence
Test-Pg-Nix:
strategy:
fail-fast: false
matrix:
pgVersion: [9.6, 10, 11, 12, 13, 14, 15]
name: Test PG ${{ matrix.pgVersion }} (Nix)
runs-on: ubuntu-latest
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: tests withTools
- name: Run spec tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} postgrest-test-spec
- name: Run IO tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} -f test/io/fixtures.sql postgrest-test-io -vv
Test-Memory-Nix:
name: Test memory (Nix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: memory
- name: Run memory tests
run: postgrest-test-memory
Build-Static-Nix:
name: Build Linux static (Nix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: tests
- name: Build static executable
run: nix-build -A postgrestStatic
- name: Check static executable
run: postgrest-check-static result/bin/postgrest
- name: Save built executable as artifact
uses: actions/upload-artifact@v3
with:
name: postgrest-linux-static-x64
path: result/bin/postgrest
if-no-files-found: error
- name: Build Docker image
run: nix-build -A docker.image --out-link postgrest-docker.tar.gz
- name: Save built Docker image as artifact
uses: actions/upload-artifact@v3
with:
name: postgrest-docker-x64
path: postgrest-docker.tar.gz
if-no-files-found: error
Build-Macos-Nix:
name: Build MacOS (Nix)
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
- name: Build everything
run: |
nix-build
Build-Stack:
strategy:
fail-fast: false
matrix:
include:
- name: Linux
runs-on: ubuntu-latest
cache: |
~/.stack
.stack-work
artifact: postgrest-ubuntu-x64
- name: MacOS
runs-on: macos-latest
cache: |
~/.stack
.stack-work
artifact: postgrest-macos-x64
- name: Windows
runs-on: windows-latest
cache: |
~\AppData\Roaming\stack
~\AppData\Local\Programs\stack
.stack-work
deps: Add-Content $env:GITHUB_PATH $env:PGBIN
artifact: postgrest-windows-x64
name: Build ${{ matrix.name }} (Stack)
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v3
- name: Stack working files cache
uses: actions/cache@v3
with:
path: ${{ matrix.cache }}
key: ${{ runner.os }}-${{ hashFiles('stack.yaml.lock') }}
- name: Install dependencies
if: ${{ matrix.deps }}
run: ${{ matrix.deps }}
- name: Build with Stack
run: stack build --local-bin-path result --copy-bins
- name: Save built executable as artifact
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.artifact }}
path: |
result/postgrest
result/postgrest.exe
if-no-files-found: error
Get-FreeBSD-CirrusCI:
name: Get FreeBSD build from CirrusCI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get FreeBSD executable from CirrusCI
env:
# GITHUB_SHA does weird things for pull request, so we roll our own:
GITHUB_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: .github/get_cirrusci_freebsd
- name: Save executable as artifact
uses: actions/upload-artifact@v3
with:
name: postgrest-freebsd-x64
path: postgrest
if-no-files-found: error
Build-Cabal:
strategy:
matrix:
ghc: ['9.2.4']
fail-fast: false
name: Build Linux (Cabal, GHC ${{ matrix.ghc }})
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Workaround runner image issue
# https://github.com/actions/runner-images/issues/7061
run: sudo chown -R "$USER" /usr/local/.ghcup
- name: ghcup
run: |
ghcup install ghc ${{ matrix.ghc }}
ghcup set ghc ${{ matrix.ghc }}
- name: Copy cabal.project
run: |
cp cabal.project.non-nix cabal.project
- name: Cache
uses: actions/cache@v3
with:
path: ~/.cabal
key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
restore-keys: |
${{ runner.os }}-${{ matrix.ghc }}-
- name: Install dependencies
run: |
cabal update
cabal build --only-dependencies --enable-tests --enable-benchmarks
- name: Build
run: cabal build --enable-tests --enable-benchmarks all
Build-Cabal-Arm:
name: Build aarch64 (Cabal)
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/rel-') }}
runs-on: ubuntu-latest
outputs:
remotepath: ${{ steps.Remote-Dir.outputs.remotepath }}
env:
GITHUB_COMMIT: ${{ github.sha }}
steps:
- uses: actions/checkout@v3
- id: Remote-Dir
name: Unique directory name for the remote build
run: echo "remotepath=postgrest-build-$(uuidgen)" >> "$GITHUB_OUTPUT"
- name: Copy script files to the remote server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
source: ".github/scripts/arm/*"
target: ${{ steps.Remote-Dir.outputs.remotepath }}
strip_components: 3
- name: Build ARM
uses: appleboy/ssh-action@master
env:
REMOTE_DIR: ${{ steps.Remote-Dir.outputs.remotepath }}
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
command_timeout: 120m
script_stop: true
envs: GITHUB_COMMIT,REMOTE_DIR
script: bash ~/$REMOTE_DIR/build.sh "$GITHUB_COMMIT" "$REMOTE_DIR"
- name: Download binaries from remote server
uses: nicklasfrahm/scp-action@main
with:
direction: download
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
source: "${{ steps.Remote-Dir.outputs.remotepath }}/result.tar.xz"
target: "result.tar.xz"
- name: Extract downloaded binaries
run: tar -xvf result.tar.xz && rm result.tar.xz
- name: Save aarch64 executable as artifact
uses: actions/upload-artifact@v3
with:
name: postgrest-ubuntu-aarch64
path: result/postgrest
if-no-files-found: error
Prepare-Release:
name: Prepare release
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
needs:
- Lint-Style
- Test-Nix
- Test-Pg-Nix
- Test-Memory-Nix
- Build-Static-Nix
- Build-Stack
#- Get-FreeBSD-CirrusCI
- Build-Cabal-Arm
outputs:
version: ${{ steps.Identify-Version.outputs.version }}
isprerelease: ${{ steps.Identify-Version.outputs.isprerelease }}
steps:
- uses: actions/checkout@v3
- id: Identify-Version
name: Identify the version to be released
run: |
tag_version="${GITHUB_REF##*/}"
cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
if [ "$tag_version" != "v$cabal_version" ]; then
echo "Tagged version ($tag_version) does not match the one in postgrest.cabal (v$cabal_version). Aborting release..."
exit 1
else
echo "Version to be released is $cabal_version"
echo "version=$cabal_version" >> "$GITHUB_OUTPUT"
fi
if [[ "$cabal_version" != *.*.*.* ]]; then
echo "Version is for a full release (version does not have four components)"
else
echo "Version is for a pre-release (version has four components, e.g., 1.1.1.1)"
echo "isprerelease=1" >> "$GITHUB_OUTPUT"
fi
- name: Identify changes from CHANGELOG.md
run: |
version="${{ steps.Identify-Version.outputs.version }}"
isprerelease="${{ steps.Identify-Version.outputs.isprerelease }}"
if [ -n "$isprerelease" ]; then
echo "Getting unreleased changes..."
sed -n "1,/## Unreleased/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
else
echo "Full release (no '-' in version), getting changes for version $version ..."
sed -n "1,/## \[$version\]/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
fi
echo "Relevant extract from CHANGELOG.md:"
cat CHANGES.md
- name: Save CHANGES.md as artifact
uses: actions/upload-artifact@v3
with:
name: release-changes
path: CHANGES.md
if-no-files-found: error
Release-GitHub:
name: Release on GitHub
permissions:
contents: write
runs-on: ubuntu-latest
needs: Prepare-Release
env:
VERSION: ${{ needs.Prepare-Release.outputs.version }}
steps:
- uses: actions/checkout@v3
- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Create release bundle with archives for all builds
run: |
find artifacts -type f -iname postgrest -exec chmod +x {} \;
mkdir -p release-bundle
tar cJvf "release-bundle/postgrest-v$VERSION-linux-static-x64.tar.xz" \
-C artifacts/postgrest-linux-static-x64 postgrest
# No need to release Ubuntu, as the static Linux binary built with Nix
# covers all Linux use-cases
#tar cfJv "release-bundle/postgrest-v$VERSION-ubuntu-x64.tar.xz" \
# -C artifacts/postgrest-ubuntu-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-macos-x64.tar.xz" \
-C artifacts/postgrest-macos-x64 postgrest
# TODO: Fix timeouts for FreeBSD builds in Cirrus
#tar cJvf "release-bundle/postgrest-v$VERSION-freebsd-x64.tar.xz" \
# -C artifacts/postgrest-freebsd-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-ubuntu-aarch64.tar.xz" \
-C artifacts/postgrest-ubuntu-aarch64 postgrest
zip "release-bundle/postgrest-v$VERSION-windows-x64.zip" \
artifacts/postgrest-windows-x64/postgrest.exe
- name: Save release bundle
uses: actions/upload-artifact@v3
with:
name: release-bundle
path: release-bundle
if-no-files-found: error
- name: Publish release on GitHub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
isprerelease="${{ needs.Prepare-Release.outputs.isprerelease }}"
echo "Releasing version v$VERSION on GitHub (isprerelease=$isprerelease)..."
gh release delete "v$VERSION" || true
gh release create "v$VERSION" \
-F artifacts/release-changes/CHANGES.md \
${isprerelease:+"--prerelease"} \
release-bundle/*
Release-Docker:
name: Release on Docker Hub
runs-on: ubuntu-latest
needs:
- Prepare-Release
env:
GITHUB_COMMIT: ${{ github.sha }}
DOCKER_REPO: postgrest
DOCKER_USER: stevechavez
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
VERSION: ${{ needs.Prepare-Release.outputs.version }}
ISPRERELEASE: ${{ needs.Prepare-Release.outputs.isprerelease }}
steps:
- uses: actions/checkout@v3
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: release
- name: Download Docker image
uses: actions/download-artifact@v3
with:
name: postgrest-docker-x64
- name: Publish images on Docker Hub
run: |
docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
docker load -i postgrest-docker.tar.gz
docker tag postgrest:latest "$DOCKER_REPO/postgrest:v$VERSION"
docker push "$DOCKER_REPO/postgrest:v$VERSION"
# Only tag 'latest' for full releases
if [[ -z "$ISPRERELEASE" ]]; then
echo "Pushing to 'latest' tag for full release of v$VERSION ..."
docker tag postgrest:latest "$DOCKER_REPO"/postgrest:latest
docker push "$DOCKER_REPO"/postgrest:latest
else
echo "Skipping pushing to 'latest' tag for v$VERSION pre-release..."
fi
# TODO: Enable dockerhub description update again, once a solution for the permission problem is found:
# https://github.com/docker/hub-feedback/issues/1927
# - name: Update descriptions on Docker Hub
# env:
# DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
# run: |
# if [[ -z "$ISPRERELEASE" ]]; then
# echo "Updating description on Docker Hub..."
# postgrest-release-dockerhub-description
# else
# echo "Skipping updating description for pre-release..."
# fi
Release-Docker-Arm:
name: Release Arm Builds on Docker Hub
runs-on: ubuntu-latest
needs:
- Build-Cabal-Arm
- Prepare-Release
- Release-Docker
env:
GITHUB_COMMIT: ${{ github.sha }}
DOCKER_REPO: postgrest
DOCKER_USER: stevechavez
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
VERSION: ${{ needs.Prepare-Release.outputs.version }}
ISPRERELEASE: ${{ needs.Prepare-Release.outputs.isprerelease }}
steps:
- uses: actions/checkout@v3
- name: Publish images for ARM builds on Docker Hub
uses: appleboy/ssh-action@master
env:
REMOTE_DIR: ${{ needs.Build-Cabal-Arm.outputs.remotepath }}
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
script_stop: true
envs: GITHUB_COMMIT,DOCKER_REPO,DOCKER_USER,DOCKER_PASS,REMOTE_DIR,VERSION,ISPRERELEASE
script: bash ~/$REMOTE_DIR/docker-publish.sh "$GITHUB_COMMIT" "$DOCKER_REPO" "$DOCKER_USER" "$DOCKER_PASS" "$REMOTE_DIR" "$VERSION" "$ISPRERELEASE"
Clean-Arm-Server:
name: Remove copied files from server
needs:
- Build-Cabal-Arm
- Release-Docker-Arm
if: success() ||
needs.Build-Cabal-Arm.result == 'failure' ||
needs.Build-Cabal-Arm.result == 'cancelled' ||
(needs.Build-Cabal-Arm.result == 'success' && !startsWith(github.ref, 'refs/tags/v'))
runs-on: ubuntu-latest
env:
REMOTE_DIR: ${{ needs.Build-Cabal-Arm.outputs.remotepath }}
steps:
- uses: actions/checkout@v3
- name: Remove uploaded files from server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
envs: REMOTE_DIR
script: rm -rf $REMOTE_DIR
+50
View File
@@ -0,0 +1,50 @@
name: Docs
on:
push:
branches:
- main
- v[0-9]+
pull_request:
branches:
- main
- v[0-9]+
jobs:
build:
name: Build docs
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31
- run: nix-env -f docs/default.nix -iA build
- run: postgrest-docs-build
spellcheck:
name: Run spellcheck
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31
- run: nix-env -f docs/default.nix -iA spellcheck
- run: postgrest-docs-spellcheck
dictcheck:
name: Run dictcheck
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31
- run: nix-env -f docs/default.nix -iA dictcheck
- run: postgrest-docs-dictcheck
linkcheck:
name: Run linkcheck
if: github.base_ref == 'main'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31
- run: nix-env -f docs/default.nix -iA linkcheck
- run: postgrest-docs-linkcheck
-34
View File
@@ -1,34 +0,0 @@
name: Loadtest
on:
push:
branches:
- main
tags:
- v*
pull_request:
branches:
- main
jobs:
Loadtest-Nix:
name: Loadtest (Nix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: loadtest
- name: Run loadtest
run: |
postgrest-loadtest-against main
postgrest-loadtest-report > loadtest/loadtest.md
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: loadtest.md
path: loadtest/loadtest.md
if-no-files-found: error
-33
View File
@@ -1,33 +0,0 @@
name: Upload Reports
on:
workflow_run:
workflows: ["Loadtest"]
types:
- completed
jobs:
upload:
name: Loadtest
permissions:
checks: write
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Download from Artifacts
uses: dawidd6/action-download-artifact@v2
with:
workflow: ${{ github.event.workflow.name }}
run_id: ${{github.event.workflow_run.id }}
name: loadtest.md
path: artifacts
- name: Upload to GitHub Checks
uses: LouisBrunner/checks-action@v1.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
sha: ${{ github.event.workflow_run.head_sha }}
name: Loadtest Results
conclusion: neutral
output: |
{"summary":""}
output_text_description_file: artifacts/loadtest.md
+1
View File
@@ -23,3 +23,4 @@ coverage
.hpc
loadtest
.history
.docs-build
+10
View File
@@ -0,0 +1,10 @@
version: 2
sphinx:
configuration: docs/conf.py
python:
install:
- requirements: docs/requirements.txt
build:
os: ubuntu-22.04
tools:
python: "3.11"
+6 -4
View File
@@ -55,6 +55,12 @@ It builds the OpenAPI response using the schema cache.
This module provides functions to deal with JWT authorization.
### Workers.hs
This spawns threads which are used to execute concurrent jobs.
Jobs include connection recovery, a listener for the PostgreSQL LISTEN command, and an admin server.
### SchemaCache.hs
This queries the PostgreSQL system catalogs and caches the metadata into a SchemaCache type,
@@ -62,7 +68,3 @@ This queries the PostgreSQL system catalogs and caches the metadata into a Schem
### AppState.hs
The state of the App which is kept across requests.
This spawns threads which are used to execute concurrent jobs.
Jobs include connection recover and a listener for the PostgreSQL LISTEN command.
-2
View File
@@ -46,14 +46,12 @@ PostgREST ongoing development is only possible thanks to our Sponsors and Backer
## Lead Backers
- [Roboflow](https://github.com/roboflow)
- Evans Fernandes
- [Jan Sommer](https://github.com/nerfpops)
- [Franz Gusenbauer](https://www.igutech.at/)
## Backers
- Zac Miller
- Tsingson Qin
- Michel Pelletier
- Jay Hannah
-85
View File
@@ -3,90 +3,6 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
## [11.1.0] - 2023-06-07
### Added
- #2786, Limit idle postgresql connection lifetime - @robx
+ New option `db-pool-max-idletime` (default 30s).
+ This is equivalent to the old option `db-pool-timeout` of PostgREST 10.0.0.
+ A config alias for `db-pool-timeout` is included.
- #2703, Add pre-config function - @steve-chavez
+ New config option `db-pre-config`(empty by default)
+ Allows using the in-database configuration without SUPERUSER
- #2781, When `db-channel-enabled` is false, start automatic connection recovery on a new request when pool connections are closed with `pg_terminate_backend` - @steve-chavez
+ Mitigates the lack of LISTEN/NOTIFY for schema cache reloading on read replicas.
### Fixed
- #2791, Fix dropping schema cache reload notifications - @steve-chavez
- #2801, Stop retrying connection when "no password supplied" - @steve-chavez
## [11.0.1] - 2023-04-27
### Fixed
- #2762, Fixes "permission denied for schema" error during schema cache load - @steve-chavez
- #2756, Fix bad error message on generated columns when using `Prefer: missing=default` - @steve-chavez
- #1139, Allow a 30 second skew for JWT validation - @steve-chavez
+ It used to be 1 second, which was too strict
## [11.0.0] - 2023-04-16
### Added
- #1414, Add related orders - @steve-chavez
+ On a many-to-one or one-to-one relationship, you can order a parent by a child column `/projects?select=*,clients(*)&order=clients(name).desc.nullsfirst`
- #1233, #1907, #2566, Allow spreading embedded resources - @steve-chavez
+ On a many-to-one or one-to-one relationship, you can unnest a json object with `/projects?select=*,...clients(client_name:name)`
+ Allows including the join table columns when resource embedding
+ Allows disambiguating a recursive m2m embed
+ Allows disambiguating an embed that has a many-to-many relationship using two foreign keys on a junction
- #2340, Allow embedding without selecting any column - @steve-chavez
- #2563, Allow `is.null` or `not.is.null` on an embedded resource - @steve-chavez
+ Offers a more flexible replacement for `!inner`, e.g. `/projects?select=*,clients(*)&clients=not.is.null`
+ Allows doing an anti join, e.g. `/projects?select=*,clients(*)&clients=is.null`
+ Allows using or across related tables conditions
- #1100, Customizable OpenAPI title - @AnthonyFisi
- #2506, Add `server-trace-header` for tracing HTTP requests. - @steve-chavez
+ When the client sends the request header specified in the config it will be included in the response headers.
- #2694, Make `db-root-spec` stable. - @steve-chavez
+ This can be used to override the OpenAPI spec with a custom database function
- #1567, On bulk inserts, missing values can get the column DEFAULT by using the `Prefer: missing=default` header - @steve-chavez
- #2501, Allow filtering by`IS DISTINCT FROM` using the `isdistinct` operator, e.g. `/people?alias=isdistinct.foo`
- #1569, Allow `any/all` modifiers on the `eq,like,ilike,gt,gte,lt,lte,match,imatch` operators, e.g. `/tbl?id=eq(any).{1,2,3}` - @steve-chavez
- This converts the input into an array type
- #2561, Configurable role settings - @steve-chavez
- Database roles that are members of the connection role get their settings applied, e.g. doing
`ALTER ROLE anon SET statement_timeout TO '5s'` will result in that `statement_timeout` getting applied for that role.
- Works when switching roles when a JWT is sent
- Settings can be reloaded with `NOTIFY pgrst, 'reload config'`.
- #2468, Configurable transaction isolation level with `default_transaction_isolation` - @steve-chavez
- Can be set per function `create function .. set default_transaction_isolation = 'repeatable read'`
- Or per role `alter role .. set default_transaction_isolation = 'serializable'`
### Fixed
- #2651, Add the missing `get` path item for RPCs to the OpenAPI output - @laurenceisla
- #2648, Fix inaccurate error codes with new ones - @laurenceisla
+ `PGRST204`: Column is not found
+ `PGRST003`: Timed out when acquiring connection to db
- #1652, Fix function call with arguments not inlining - @steve-chavez
- #2705, Fix bug when using the `Range` header on `PATCH/DELETE` - @laurenceisla
+ Fix the`"message": "syntax error at or near \"RETURNING\""` error
+ Fix doing a limited update/delete when an `order` query parameter was present
- #2742, Fix db settings and pg version queries not getting prepared - @steve-chavez
- #2618, Fix `PATCH` requests not recognizing embedded filters and using the top-level resource instead - @steve-chavez
### Changed
- #2705, The `Range` header is now only considered on `GET` requests and is ignored for any other method - @laurenceisla
+ Other methods should use the `limit/offset` query parameters for sub-ranges
+ `PUT` requests no longer return an error when this header is present (using `limit/offset` still triggers the error)
- #2733, Remove bulk RPC call with the `Prefer: params=multiple-objects` header. A function with a JSON array or object parameter should be used instead.
## [10.2.0] - 2023-04-12
### Added
@@ -120,7 +36,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #2548, Fix regression when embedding views with partial references to multi column FKs - @wolfgangwalther
- #2558, Fix regression when requesting limit=0 and `db-max-row` is set - @laurenceisla
- #2542, Return a clear error without hitting the database when trying to update or insert an unknown column with `?columns` - @aljungberg
## [10.1.0] - 2022-10-28
+3
View File
@@ -0,0 +1,3 @@
This repository follows the same contribution guidelines as the main PostgREST repository contribution guidelines:
https://github.com/PostgREST/postgrest/blob/main/.github/CONTRIBUTING.md
+1 -7
View File
@@ -1,8 +1,6 @@
![Logo](static/bigger-logo.png "Logo")
[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/postgrest)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/postgrest)
[![Join the chat at https://gitter.im/begriffs/postgrest](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/begriffs/postgrest)
[![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](http://postgrest.org)
[![Docker Stars](https://img.shields.io/docker/pulls/postgrest/postgrest.svg)](https://hub.docker.com/r/postgrest/postgrest/)
[![Build Status](https://github.com/postgrest/postgrest/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/PostgREST/postgrest/actions?query=branch%3Amain)
@@ -145,11 +143,7 @@ and the [API guide](http://postgrest.org/en/stable/api.html).
## Supporting development
You can help PostgREST ongoing maintenance and development by:
- Making a regular donation through Patreon https://www.patreon.com/postgrest
- Alternatively, you can make a one-time donation via Paypal https://www.paypal.me/postgrest
You can help PostgREST ongoing maintenance and development by making a regular donation through Patreon https://www.patreon.com/postgrest
Every donation will be spent on making PostgREST better for the whole community.
+11 -18
View File
@@ -41,7 +41,6 @@ let
allOverlays.postgresql-legacy
allOverlays.postgresql-future
(allOverlays.haskell-packages { inherit compiler; })
allOverlays.slocat
];
# Evaluated expression of the Nixpkgs repository.
@@ -66,17 +65,11 @@ let
postgrest =
pkgs.haskell.packages."${compiler}".callCabal2nix name src { };
# Functionality that derives a fully static Haskell package based on
# Function that derives a fully static Haskell package based on
# nh2/static-haskell-nix
staticHaskellPackage =
import nix/static-haskell-package.nix { inherit nixpkgs system compiler patches allOverlays; };
# Static executable.
postgrestStatic =
lib.justStaticExecutables (lib.dontCheck (staticHaskellPackage name src).package);
packagesStatic = (staticHaskellPackage name src).survey;
# Options passed to cabal in dev tools and tests
devCabalOptions =
"-f dev --test-show-detail=direct";
@@ -101,6 +94,10 @@ rec {
postgrestPackage =
lib.dontCheck postgrest;
# Static executable.
postgrestStatic =
lib.justStaticExecutables (lib.dontCheck (staticHaskellPackage name src));
# Profiled dynamic executable.
postgrestProfiled =
lib.enableExecutableProfiling (
@@ -122,13 +119,14 @@ rec {
cabalTools =
pkgs.callPackage nix/tools/cabalTools.nix { inherit devCabalOptions postgrest; };
withTools =
pkgs.callPackage nix/tools/withTools.nix { inherit cabalTools devCabalOptions postgresqlVersions postgrest; };
# Development tools.
devTools =
pkgs.callPackage nix/tools/devTools.nix { inherit tests style devCabalOptions hsie withTools; };
# Docker images and loading script.
docker =
pkgs.callPackage nix/tools/docker { postgrest = postgrestStatic; };
# Load testing tools.
loadtest =
pkgs.callPackage nix/tools/loadtest.nix { inherit withTools; };
@@ -157,12 +155,7 @@ rec {
inherit (pkgs.haskell.packages."${compiler}") hpc-codecov;
inherit (pkgs.haskell.packages."${compiler}") weeder;
};
} // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux rec {
# Static executable.
inherit postgrestStatic;
inherit packagesStatic;
# Docker images and loading script.
docker =
pkgs.callPackage nix/tools/docker { postgrest = postgrestStatic; };
withTools =
pkgs.callPackage nix/tools/withTools.nix { inherit devCabalOptions postgresqlVersions postgrest; };
}
+8
View File
@@ -0,0 +1,8 @@
_build
Pipfile.lock
*.aux
*.log
_diagrams/db.pdf
misspellings
unuseddict
*.mo
+20
View File
@@ -0,0 +1,20 @@
# PostgREST documentation https://postgrest.org/
PostgREST docs use the reStructuredText format, check this [cheatsheet](https://github.com/ralsina/rst-cheatsheet/blob/master/rst-cheatsheet.rst) to get acquainted with it.
To build the docs locally, use [nix](https://nixos.org/nix/):
```bash
nix-shell
```
Once in the nix-shell you have the following commands available:
- `postgrest-docs-build`: Build the docs.
- `postgrest-docs-serve`: Build the docs and start a livereload server on `http://localhost:5500`.
- `postgrest-docs-spellcheck`: Run aspell.
## Documentation structure
This documentation is structured according to tutorials-howtos-topics-references. For more details on the rationale of this structure,
see https://www.divio.com/blog/documentation.
+40
View File
@@ -0,0 +1,40 @@
## ERD
The ER diagrams were created with https://github.com/BurntSushi/erd/.
You can go download erd from https://github.com/BurntSushi/erd/releases and then do:
```bash
./erd_static-x86-64 -i film.er -o ../_static/film.png
```
## LaTeX
The schema structure diagram is done with LaTeX. You can use a GUI like https://www.mathcha.io/editor to create the .tex file.
Then use this command to generate the png file.
```bash
pdflatex --shell-escape -halt-on-error db.tex
## and move it to the static folder(it's not easy to do it in one go with the pdflatex)
mv db.png ../_static/
```
LaTeX is used because it's a tweakable plain text format.
You can install the full latex suite with `nix`:
```
nix-env -iA texlive.combined.scheme-full
```
To tweak the file with a live reload environment use:
```bash
# open the pdf(zathura used as an example)
zathura db.pdf &
# live reload with entr
echo db.tex | entr pdflatex --shell-escape -halt-on-error db.tex
```
+71
View File
@@ -0,0 +1,71 @@
\documentclass[convert]{standalone}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{mathdots}
\usepackage{yhmath}
\usepackage{cancel}
\usepackage{color}
\usepackage{siunitx}
\usepackage{array}
\usepackage{multirow}
\usepackage{amssymb}
\usepackage{gensymb}
\usepackage{tabularx}
\usepackage{booktabs}
\usetikzlibrary{fadings}
\usetikzlibrary{patterns}
\usetikzlibrary{shadows.blur}
\usetikzlibrary{shapes}
\begin{document}
\newcommand\customScale{0.35}
\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1, scale=\customScale, every node/.style={scale=\customScale}]
%Shape: Can [id:dp7234864758664346]
\draw [fill={rgb, 255:red, 47; green, 97; blue, 144 } ,fill opacity=1 ] (497.5,51.5) -- (497.5,255.5) .. controls (497.5,275.66) and (423.18,292) .. (331.5,292) .. controls (239.82,292) and (165.5,275.66) .. (165.5,255.5) -- (165.5,51.5) .. controls (165.5,31.34) and (239.82,15) .. (331.5,15) .. controls (423.18,15) and (497.5,31.34) .. (497.5,51.5) .. controls (497.5,71.66) and (423.18,88) .. (331.5,88) .. controls (239.82,88) and (165.5,71.66) .. (165.5,51.5) ;
%Shape: Rectangle [id:dp7384065579958246]
\draw [fill={rgb, 255:red, 236; green, 227; blue, 227 } ,fill opacity=1 ] (189,115) -- (252.5,115) -- (252.5,155) -- (189,155) -- cycle ;
%Shape: Rectangle [id:dp24763906430298177]
\draw [fill={rgb, 255:red, 236; green, 227; blue, 227 } ,fill opacity=1 ] (292,118) -- (362,118) -- (362,158) -- (292,158) -- cycle ;
%Shape: Rectangle [id:dp3775601612537265]
\draw [fill={rgb, 255:red, 236; green, 227; blue, 227 } ,fill opacity=1 ] (397,114) -- (467,114) -- (467,154) -- (397,154) -- cycle ;
%Shape: Rectangle [id:dp7071457022893852]
\draw [fill={rgb, 255:red, 248; green, 231; blue, 28 } ,fill opacity=1 ] (269,199) -- (397.5,199) -- (397.5,273) -- (269,273) -- cycle ;
%Straight Lines [id:da8846759047437789]
\draw (268,234) -- (226.44,155.77) ;
\draw [shift={(225.5,154)}, rotate = 422.02] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Straight Lines [id:da6908444738113828]
\draw (309.5,198) -- (307.6,161) ;
\draw [shift={(307.5,159)}, rotate = 447.06] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Straight Lines [id:da7168757864413169]
\draw (398.5,233) -- (431.72,154.84) ;
\draw [shift={(432.5,153)}, rotate = 473.03] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Up Down Arrow [id:dp14059754167108496]
\draw [fill={rgb, 255:red, 126; green, 211; blue, 33 } ,fill opacity=1 ] (312.5,288.5) -- (330,273) -- (347.5,288.5) -- (338.75,288.5) -- (338.75,319.5) -- (347.5,319.5) -- (330,335) -- (312.5,319.5) -- (321.25,319.5) -- (321.25,288.5) -- cycle ;
% Text Node
\draw (201,129) node [anchor=north west][inner sep=0.75pt] [align=left] {tables};
% Text Node
\draw (307,130) node [anchor=north west][inner sep=0.75pt] [align=left ] {tables};
% Text Node
\draw (414,127) node [anchor=north west][inner sep=0.75pt] [align=left] {tables};
% Text Node
\draw (272,203) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 0; green, 0; blue, 0 } ,opacity=1 ] [align=center] { \\ views \\ + \\ \ \ stored procedures};
% Text Node
\draw (322,178) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{api}};
% Text Node
\draw (190,97) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{internal}};
% Text Node
\draw (300,99) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{private}};
% Text Node
\draw (417,101) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{core}};
% Text Node
\draw (358,306) node [anchor=north west][inner sep=0.75pt] [align=left] {REST};
\end{tikzpicture}
\end{document}
+40
View File
@@ -0,0 +1,40 @@
[Films]
*id
+director_id
title
year
rating
language
[Directors]
*id
first_name
last_name
[Actors]
*id
first_name
last_name
[Roles]
*+film_id
*+actor_id
character
[Competitions]
*id
name
year
[Nominations]
*+competition_id
*+film_id
rank
Roles *--1 Actors
Roles *--1 Films
Nominations *--1 Competitions
Nominations *--1 Films
Films *--1 Directors
+15
View File
@@ -0,0 +1,15 @@
[Addresses]
*id
name
city
state
postal_code
[Orders]
*id
name
+billing_address_id
+shipping_address_id
Orders *--1 Addresses
Orders *--1 Addresses
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

+67
View File
@@ -0,0 +1,67 @@
.wy-nav-content {
max-width: initial;
}
#postgrest-documentation > h1 {
display: none;
}
div.wy-menu.rst-pro {
display: none !important;
}
div.highlight {
background: #fff !important;
}
div.line-block {
margin-bottom: 0px !important;
}
#sponsors {
text-align: center;
}
#sponsors h2 {
text-align: left;
}
#sponsors img{
margin: 10px;
}
#thanks{
text-align: center;
}
#thanks img{
margin: 10px;
}
#thanks h2{
text-align: left;
}
#thanks p{
text-align: left;
}
#thanks ul{
text-align: left;
}
.image-container {
max-width: 800px;
display: block;
margin-left: auto;
margin-right: auto;
margin-bottom: 24px;
}
.wy-table-responsive table td {
white-space: normal !important;
}
.wy-table-responsive {
overflow: visible !important;
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+385
View File
@@ -0,0 +1,385 @@
.. _admin:
Hardening PostgREST
===================
PostgREST is a fast way to construct a RESTful API. Its default behavior is great for scaffolding in development. When it's time to go to production it works great too, as long as you take precautions. PostgREST is a small sharp tool that focuses on performing the API-to-database mapping. We rely on a reverse proxy like Nginx for additional safeguards.
The first step is to create an Nginx configuration file that proxies requests to an underlying PostgREST server.
.. code-block:: nginx
http {
# ...
# upstream configuration
upstream postgrest {
server localhost:3000;
}
# ...
server {
# ...
# expose to the outside world
location /api/ {
default_type application/json;
proxy_hide_header Content-Location;
add_header Content-Location /api/$upstream_http_content_location;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://postgrest/;
}
# ...
}
}
.. note::
For ubuntu, if you already installed nginx through :code:`apt` you can add this to the config file in
:code:`/etc/nginx/sites-enabled/default`.
.. _block_fulltable:
Block Full-Table Operations
---------------------------
Each table in the admin-selected schema gets exposed as a top level route. Client requests are executed by certain database roles depending on their authentication. All HTTP verbs are supported that correspond to actions permitted to the role. For instance if the active role can drop rows of the table then the DELETE verb is allowed for clients. Here's an API request to delete old rows from a hypothetical logs table:
.. tabs::
.. code-tab:: http
DELETE /logs?time=lt.1991-08-06 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/logs?time=lt.1991-08-06" -X DELETE
However it's very easy to delete the **entire table** by omitting the query parameter!
.. tabs::
.. code-tab:: http
DELETE /logs HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/logs" -X DELETE
This can happen accidentally such as by switching a request from a GET to a DELETE. To protect against accidental operations use the `pg-safeupdate <https://github.com/eradman/pg-safeupdate>`_ PostgreSQL extension. It raises an error if UPDATE or DELETE are executed without specifying conditions. To install it you can use the `PGXN <https://pgxn.org/>`_ network:
.. code-block:: bash
sudo -E pgxn install safeupdate
# then add this to postgresql.conf:
# shared_preload_libraries='safeupdate';
This does not protect against malicious actions, since someone can add a url parameter that does not affect the result set. To prevent this you must turn to database permissions, forbidding the wrong people from deleting rows, and using `row-level security <https://www.postgresql.org/docs/current/ddl-rowsecurity.html>`_ if finer access control is required.
Count-Header DoS
----------------
For convenience to client-side pagination controls PostgREST supports counting and reporting total table size in its response. As described in :ref:`limits`, responses ordinarily include a range but leave the total unspecified like
.. code-block:: http
HTTP/1.1 200 OK
Range-Unit: items
Content-Range: 0-14/*
However including the request header :code:`Prefer: count=exact` calculates and includes the full count:
.. code-block:: http
HTTP/1.1 206 Partial Content
Range-Unit: items
Content-Range: 0-14/3573458
This is fine in small tables, but count performance degrades in big tables due to the MVCC architecture of PostgreSQL. For very large tables it can take a very long time to retrieve the results which allows a denial of service attack. The solution is to strip this header from all requests:
.. code-block:: postgres
-- Pending nginx config: Remove any prefer header which contains the word count
.. _https:
HTTPS
-----
PostgREST aims to do one thing well: add an HTTP interface to a PostgreSQL database. To keep the code small and focused we do not implement HTTPS. Use a reverse proxy such as NGINX to add this, `here's how <https://nginx.org/en/docs/http/configuring_https_servers.html>`_. Note that some Platforms as a Service like Heroku also add SSL automatically in their load balancer.
Rate Limiting
-------------
Nginx supports "leaky bucket" rate limiting (see `official docs <https://nginx.org/en/docs/http/ngx_http_limit_req_module.html>`_). Using standard Nginx configuration, routes can be grouped into *request zones* for rate limiting. For instance we can define a zone for login attempts:
.. code-block:: nginx
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
This creates a shared memory zone called "login" to store a log of IP addresses that access the rate limited urls. The space reserved, 10 MB (:code:`10m`) will give us enough space to store a history of 160k requests. We have chosen to allow only allow one request per second (:code:`1r/s`).
Next we apply the zone to certain routes, like a hypothetical stored procedure called :code:`login`.
.. code-block:: nginx
location /rpc/login/ {
# apply rate limiting
limit_req zone=login burst=5;
}
The burst argument tells Nginx to start dropping requests if more than five queue up from a specific IP.
Nginx rate limiting is general and indiscriminate. To rate limit each authenticated request individually you will need to add logic in a :ref:`Custom Validation <custom_validation>` function.
.. _external_connection_poolers:
Using External Connection Poolers
---------------------------------
PostgREST manages its :ref:`own pool of connections <db-pool>` and uses prepared statements by default in order to increase performance. However, this setting is incompatible with external connection poolers such as PgBouncer working in transaction pooling mode. In this case, you need to set the :ref:`db-prepared-statements` config option to ``false``. On the other hand, session pooling is fully compatible with PostgREST, while statement pooling is not compatible at all.
.. note::
If prepared statements are enabled, PostgREST will quit after detecting that transaction or statement pooling is being used.
You should also set the :ref:`db-channel-enabled` config option to ``false``, due to the ``LISTEN`` command not being compatible with transaction pooling, although it should not give any errors if it's left enabled by default.
Debugging
=========
Server Version
--------------
When debugging a problem it's important to verify the PostgREST version. At any time you can make a request to the running server and determine exactly which version is deployed. Look for the :code:`Server` HTTP response header, which contains the version number.
Errors
------
See the :doc:`Errors <errors>` reference page for detailed information on the errors that PostgREST returns.
.. _pgrst_logging:
Logging
-------
PostgREST logs basic request information to ``stdout``, including the authenticated user if available, the requesting IP address and user agent, the URL requested, and HTTP response status.
.. code::
127.0.0.1 - user [26/Jul/2021:01:56:38 -0500] "GET /clients HTTP/1.1" 200 - "" "curl/7.64.0"
127.0.0.1 - anonymous [26/Jul/2021:01:56:48 -0500] "GET /unexistent HTTP/1.1" 404 - "" "curl/7.64.0"
For diagnostic information about the server itself, PostgREST logs to ``stderr``.
.. code::
12/Jun/2021:17:47:39 -0500: Attempting to connect to the database...
12/Jun/2021:17:47:39 -0500: Listening on port 3000
12/Jun/2021:17:47:39 -0500: Connection successful
12/Jun/2021:17:47:39 -0500: Config re-loaded
12/Jun/2021:17:47:40 -0500: Schema cache loaded
.. note::
When running it in an SSH session you must detach it from stdout or it will be terminated when the session closes. The easiest technique is redirecting the output to a log file or to the syslog:
.. code-block:: bash
ssh foo@example.com \
'postgrest foo.conf </dev/null >/var/log/postgrest.log 2>&1 &'
# another option is to pipe the output into "logger -t postgrest"
PostgREST logging provides limited information for debugging server errors. It's helpful to get full information about both client requests and the corresponding SQL commands executed against the underlying database.
HTTP Requests
-------------
A great way to inspect incoming HTTP requests including headers and query parameters is to sniff the network traffic on the port where PostgREST is running. For instance on a development server bound to port 3000 on localhost, run this:
.. code:: bash
# sudo access is necessary for watching the network
sudo ngrep -d lo0 port 3000
The options to ngrep vary depending on the address and host on which you've bound the server. The binding is described in the :ref:`configuration` section. The ngrep output isn't particularly pretty, but it's legible.
.. _automatic_recovery:
Automatic Connection Recovery
-----------------------------
When PostgREST loses the connection to the database, it retries the connection using capped exponential backoff, with 32 seconds being the maximum backoff time.
This retry behavior is triggered immediately after the connection is lost if :ref:`db-channel-enabled` is set to true(the default), otherwise it will be activated once a request is made.
To notify the client when the next reconnection attempt will be, PostgREST responds with ``503 Service Unavailable`` and the ``Retry-After: x`` header, where ``x`` is the number of seconds programmed for the next retry.
Database Logs
-------------
Once you've verified that requests are as you expect, you can get more information about the server operations by watching the database logs. By default PostgreSQL does not keep these logs, so you'll need to make the configuration changes below. Find :code:`postgresql.conf` inside your PostgreSQL data directory (to find that, issue the command :code:`show data_directory;`). Either find the settings scattered throughout the file and change them to the following values, or append this block of code to the end of the configuration file.
.. code:: sql
# send logs where the collector can access them
log_destination = "stderr"
# collect stderr output to log files
logging_collector = on
# save logs in pg_log/ under the pg data directory
log_directory = "pg_log"
# (optional) new log file per day
log_filename = "postgresql-%Y-%m-%d.log"
# log every kind of SQL statement
log_statement = "all"
Restart the database and watch the log file in real-time to understand how HTTP requests are being translated into SQL commands.
.. note::
On Docker you can enable the logs by using a custom ``init.sh``:
.. code:: bash
#!/bin/sh
echo "log_statement = 'all'" >> /var/lib/postgresql/data/postgresql.conf
After that you can start the container and check the logs with ``docker logs``.
.. code:: bash
docker run -v "$(pwd)/init.sh":"/docker-entrypoint-initdb.d/init.sh" -d postgres
docker logs -f <container-id>
Schema Reloading
----------------
Changing the schema while the server is running can lead to errors due to a stale schema cache. To learn how to refresh the cache see :ref:`schema_reloading`.
.. _health_check:
Health Check
------------
You can enable a minimal health check to verify if PostgREST is available for client requests and to check the status of its internal state.
To do this, set the configuration variable :ref:`admin-server-port` to the port number of your preference. Two endpoints ``live`` and ``ready`` will then be available.
The ``live`` endpoint verifies if PostgREST is running on its configured port. A request will return ``200 OK`` if PostgREST is alive or ``503`` otherwise.
The ``ready`` endpoint also checks the state of both the Database Connection and the :ref:`schema_cache`. A request will return ``200 OK`` if it is ready or ``503`` if not.
For instance, to verify if PostgREST is running at ``localhost:3000`` while the ``admin-server-port`` is set to ``3001``:
.. tabs::
.. code-tab:: http
GET localhost:3001/live HTTP/1.1
.. code-tab:: bash Curl
curl -I "http://localhost:3001/live"
.. code-block:: http
HTTP/1.1 200 OK
If you have a machine with multiple network interfaces and multiple PostgREST instances in the same port, you need to specify a unique :ref:`hostname <server-host>` in the configuration of each PostgREST instance for the health check to work correctly. Don't use the special values(``!4``, ``*``, etc) in this case because the health check could report a false positive.
Daemonizing
===========
For Linux distributions that use **systemd** (Ubuntu, Debian, Archlinux) you can create a daemon in the following way.
First, create postgrest configuration in ``/etc/postgrest/config``
.. code-block:: ini
db-uri = "postgres://<your_user>:<your_password>@localhost:5432/<your_db>"
db-schemas = "<your_exposed_schema>"
db-anon-role = "<your_anon_role>"
jwt-secret = "<your_secret>"
Then create the systemd service file in ``/etc/systemd/system/postgrest.service``
.. code-block:: ini
[Unit]
Description=REST API for any PostgreSQL database
After=postgresql.service
[Service]
ExecStart=/bin/postgrest /etc/postgrest/config
ExecReload=/bin/kill -SIGUSR1 $MAINPID
[Install]
WantedBy=multi-user.target
After that, you can enable the service at boot time and start it with:
.. code-block:: bash
systemctl enable postgrest
systemctl start postgrest
## For reloading the service
## systemctl restart postgrest
.. _file_descriptors:
File Descriptors
----------------
File descriptors are kernel resources that are used by HTTP connections (among others). File descriptors are limited per process. The kernel default limit is 1024, which is increased in some Linux distributions.
When under heavy traffic, PostgREST can reach this limit and start showing ``No file descriptors available`` errors. To clear these errors, you can increase the process' file descriptor limit.
.. code-block:: ini
[Service]
LimitNOFILE=10000
Alternate URL Structure
=======================
As discussed in :ref:`singular_plural`, there are no special URL forms for singular resources in PostgREST, only operators for filtering. Thus there are no URLs like :code:`/people/1`. It would be specified instead as
.. tabs::
.. code-tab:: http
GET /people?id=eq.1 HTTP/1.1
Accept: application/vnd.pgrst.object+json
.. code-tab:: bash Curl
curl "http://localhost:3000/people?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
This allows compound primary keys and makes the intent for singular response independent of a URL convention.
Nginx rewrite rules allow you to simulate the familiar URL convention. The following example adds a rewrite rule for all table endpoints, but you'll want to restrict it to those tables that have a numeric simple primary key named "id."
.. code-block:: nginx
# support /endpoint/:id url style
location ~ ^/([a-z_]+)/([0-9]+) {
# make the response singular
proxy_set_header Accept 'application/vnd.pgrst.object+json';
# assuming an upstream named "postgrest"
proxy_pass http://postgrest/$1?id=eq.$2;
}
.. TODO
.. Administration
.. API Versioning
.. HTTP Caching
.. Upgrading
+3113
View File
File diff suppressed because it is too large Load Diff
+496
View File
@@ -0,0 +1,496 @@
.. _roles:
Overview of Role System
=======================
PostgREST is designed to keep the database at the center of API security. All authorization happens through database roles and permissions. It is PostgREST's job to **authenticate** requests -- i.e. verify that a client is who they say they are -- and then let the database **authorize** client actions.
Authentication Sequence
-----------------------
There are three types of roles used by PostgREST, the **authenticator**, **anonymous** and **user** roles. The database administrator creates these roles and configures PostgREST to use them.
.. image:: _static/security-roles.png
The authenticator should be created :code:`NOINHERIT` and configured in the database to have very limited access. It is a chameleon whose job is to "become" other users to service authenticated HTTP requests. The picture below shows how the server handles authentication. If auth succeeds, it switches into the user role specified by the request, otherwise it switches into the anonymous role (if it's set in :ref:`db-anon-role`).
.. image:: _static/security-anon-choice.png
Here are the technical details. We use `JSON Web Tokens <https://jwt.io/>`_ to authenticate API requests. As you'll recall a JWT contains a list of cryptographically signed claims. All claims are allowed but PostgREST cares specifically about a claim called role.
.. code:: json
{
"role": "user123"
}
When a request contains a valid JWT with a role claim PostgREST will switch to the database role with that name for the duration of the HTTP request.
.. code:: sql
SET LOCAL ROLE user123;
Note that the database administrator must allow the authenticator role to switch into this user by previously executing
.. code:: sql
GRANT user123 TO authenticator;
If the client included no JWT (or one without a role claim) then PostgREST switches into the anonymous role whose actual database-specific name, like that of with the authenticator role, is specified in the PostgREST server configuration file. The database administrator must set anonymous role permissions correctly to prevent anonymous users from seeing or changing things they shouldn't.
Users and Groups
----------------
PostgreSQL manages database access permissions using the concept of roles. A role can be thought of as either a database user, or a group of database users, depending on how the role is set up.
Roles for Each Web User
~~~~~~~~~~~~~~~~~~~~~~~
PostgREST can accommodate either viewpoint. If you treat a role as a single user then the JWT-based role switching described above does most of what you need. When an authenticated user makes a request PostgREST will switch into the role for that user, which in addition to restricting queries, is available to SQL through the :code:`current_user` variable.
You can use row-level security to flexibly restrict visibility and access for the current user. Here is an `example <https://www.2ndquadrant.com/en/blog/application-users-vs-row-level-security/>`_ from Tomas Vondra, a chat table storing messages sent between users. Users can insert rows into it to send messages to other users, and query it to see messages sent to them by other users.
.. code-block:: postgres
CREATE TABLE chat (
message_uuid UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
message_time TIMESTAMP NOT NULL DEFAULT now(),
message_from NAME NOT NULL DEFAULT current_user,
message_to NAME NOT NULL,
message_subject VARCHAR(64) NOT NULL,
message_body TEXT
);
ALTER TABLE chat ENABLE ROW LEVEL SECURITY;
We want to enforce a policy that ensures a user can see only those messages sent by them or intended for them. Also we want to prevent a user from forging the message_from column with another person's name.
PostgreSQL allows us to set this policy with row-level security:
.. code-block:: postgres
CREATE POLICY chat_policy ON chat
USING ((message_to = current_user) OR (message_from = current_user))
WITH CHECK (message_from = current_user)
Anyone accessing the generated API endpoint for the chat table will see exactly the rows they should, without our needing custom imperative server-side coding.
.. warning::
Roles are namespaced per-cluster rather than per-database so they may be prone to collision.
Web Users Sharing Role
~~~~~~~~~~~~~~~~~~~~~~
Alternately database roles can represent groups instead of (or in addition to) individual users. You may choose that all signed-in users for a web app share the role webuser. You can distinguish individual users by including extra claims in the JWT such as email.
.. code:: json
{
"role": "webuser",
"email": "john@doe.com"
}
SQL code can access claims through GUC variables set by PostgREST per request. For instance to get the email claim, call this function:
For PostgreSQL server version >= 14
.. code:: sql
current_setting('request.jwt.claims', true)::json->>'email';
For PostgreSQL server version < 14
.. code:: sql
current_setting('request.jwt.claim.email', true);
This allows JWT generation services to include extra information and your database code to react to it. For instance the RLS example could be modified to use this current_setting rather than current_user. The second 'true' argument tells current_setting to return NULL if the setting is missing from the current configuration.
Hybrid User-Group Roles
~~~~~~~~~~~~~~~~~~~~~~~
You can mix the group and individual role policies. For instance we could still have a webuser role and individual users which inherit from it:
.. code-block:: postgres
CREATE ROLE webuser NOLOGIN;
-- grant this role access to certain tables etc
CREATE ROLE user000 NOLOGIN;
GRANT webuser TO user000;
-- now user000 can do whatever webuser can
GRANT user000 TO authenticator;
-- allow authenticator to switch into user000 role
-- (the role itself has nologin)
.. _custom_validation:
Custom Validation
-----------------
PostgREST honors the :code:`exp` claim for token expiration, rejecting expired tokens. However it does not enforce any extra constraints. An example of an extra constraint would be to immediately revoke access for a certain user. The configuration file parameter :code:`db-pre-request` specifies a stored procedure to call immediately after the authenticator switches into a new role and before the main query itself runs.
Here's an example. In the config file specify a stored procedure:
.. code:: ini
db-pre-request = "public.check_user"
In the function you can run arbitrary code to check the request and raise an exception to block it if desired.
.. code-block:: postgres
CREATE OR REPLACE FUNCTION check_user() RETURNS void AS $$
BEGIN
IF current_user = 'evil_user' THEN
RAISE EXCEPTION 'No, you are evil'
USING HINT = 'Stop being so evil and maybe you can log in';
END IF;
END
$$ LANGUAGE plpgsql;
.. _client_auth:
Client Auth
===========
To make an authenticated request the client must include an :code:`Authorization` HTTP header with the value :code:`Bearer <jwt>`. For instance:
.. tabs::
.. code-tab:: http
GET /foo HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4
.. code-tab:: bash Curl
curl "http://localhost:3000/foo" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiamRvZSIsImV4cCI6MTQ3NTUxNjI1MH0.GYDZV3yM0gqvuEtJmfpplLBXSGYnke_Pvnl0tbKAjB4"
The ``Bearer`` header value can be used with or without capitalization(``bearer``).
JWT Generation
--------------
You can create a valid JWT either from inside your database or via an external service. Each token is cryptographically signed with a secret key. In the case of symmetric cryptography the signer and verifier share the same secret passphrase. In asymmetric cryptography the signer uses the private key and the verifier the public key. PostgREST supports both symmetric and asymmetric cryptography.
JWT from SQL
~~~~~~~~~~~~
You can create JWT tokens in SQL using the `pgjwt extension <https://github.com/michelp/pgjwt>`_. It's simple and requires only pgcrypto. If you're on an environment like Amazon RDS which doesn't support installing new extensions, you can still manually run the `SQL inside pgjwt <https://github.com/michelp/pgjwt/blob/master/pgjwt--0.1.1.sql>`_ (you'll need to replace ``@extschema@`` with another schema or just delete it) which creates the functions you will need.
Next write a stored procedure that returns the token. The one below returns a token with a hard-coded role, which expires five minutes after it was issued. Note this function has a hard-coded secret as well.
.. code-block:: postgres
CREATE TYPE jwt_token AS (
token text
);
CREATE FUNCTION jwt_test() RETURNS public.jwt_token AS $$
SELECT public.sign(
row_to_json(r), 'reallyreallyreallyreallyverysafe'
) AS token
FROM (
SELECT
'my_role'::text as role,
extract(epoch from now())::integer + 300 AS exp
) r;
$$ LANGUAGE sql;
PostgREST exposes this function to clients via a POST request to ``/rpc/jwt_test``.
.. note::
To avoid hard-coding the secret in stored procedures, save it as a property of the database.
.. code-block:: postgres
-- run this once
ALTER DATABASE mydb SET "app.jwt_secret" TO 'reallyreallyreallyreallyverysafe';
-- then all functions can refer to app.jwt_secret
SELECT sign(
row_to_json(r), current_setting('app.jwt_secret')
) AS token
FROM ...
JWT from Auth0
~~~~~~~~~~~~~~
An external service like `Auth0 <https://auth0.com/>`_ can do the hard work transforming OAuth from Github, Twitter, Google etc into a JWT suitable for PostgREST. Auth0 can also handle email signup and password reset flows.
To use Auth0, create `an application <https://auth0.com/docs/get-started/applications>`_ for your app and `an API <https://auth0.com/docs/get-started/apis>`_ for your PostgREST server. Auth0 supports both HS256 and RS256 scheme for the issued tokens for APIs. For simplicity, you may first try HS256 scheme while creating your API on Auth0. Your application should use your PostgREST API's `API identifier <https://auth0.com/docs/get-started/apis/api-settings>`_ by setting it with the `audience parameter <https://auth0.com/docs/secure/tokens/access-tokens/get-access-tokens#control-access-token-audience>`_ during the authorization request. This will ensure that Auth0 will issue an access token for your PostgREST API. For PostgREST to verify the access token, you will need to set ``jwt-secret`` on PostgREST config file with your API's signing secret.
.. note::
Our code requires a database role in the JWT. To add it you need to save the database role in Auth0 `app metadata <https://auth0.com/docs/manage-users/user-accounts/metadata/manage-metadata-rules>`_. Then, you will need to write `a rule <https://auth0.com/docs/customize/rules>`_ that will extract the role from the user's app_metadata and set it as a `custom claim <https://auth0.com/docs/get-started/apis/scopes/sample-use-cases-scopes-and-claims#add-custom-claims-to-a-token>`_ in the access token. Note that, you may use Auth0's `core authorization feature <https://auth0.com/docs/manage-users/access-control/rbac>`_ for more complex use cases. Metadata solution is mentioned here for simplicity.
.. code:: javascript
function (user, context, callback) {
// Follow the documentations at
// https://postgrest.org/en/latest/configuration.html#db-role-claim-key
// to set a custom role claim on PostgREST
// and use it as custom claim attribute in this rule
const myRoleClaim = 'https://myapp.com/role';
user.app_metadata = user.app_metadata || {};
context.accessToken[myRoleClaim] = user.app_metadata.role;
callback(null, user, context);
}
.. _asym_keys:
Asymmetric Keys
~~~~~~~~~~~~~~~
As described in the :ref:`configuration` section, PostgREST accepts a ``jwt-secret`` config file parameter. If it is set to a simple string value like "reallyreallyreallyreallyverysafe" then PostgREST interprets it as an HMAC-SHA256 passphrase. However you can also specify a literal JSON Web Key (JWK) or set. For example, you can use an RSA-256 public key encoded as a JWK:
.. code-block:: json
{
"alg":"RS256",
"e":"AQAB",
"key_ops":["verify"],
"kty":"RSA",
"n":"9zKNYTaYGfGm1tBMpRT6FxOYrM720GhXdettc02uyakYSEHU2IJz90G_MLlEl4-WWWYoS_QKFupw3s7aPYlaAjamG22rAnvWu-rRkP5sSSkKvud_IgKL4iE6Y2WJx2Bkl1XUFkdZ8wlEUR6O1ft3TS4uA-qKifSZ43CahzAJyUezOH9shI--tirC028lNg767ldEki3WnVr3zokSujC9YJ_9XXjw2hFBfmJUrNb0-wldvxQbFU8RPXip-GQ_JPTrCTZhrzGFeWPvhA6Rqmc3b1PhM9jY7Dur1sjYWYVyXlFNCK3c-6feo5WlRfe1aCWmwZQh6O18eTmLeT4nWYkDzQ"
}
.. note::
This could also be a JSON Web Key Set (JWKS) if it was contained within an array assigned to a `keys` member, e.g. ``{ keys: [jwk1, jwk2] }``.
Just pass it in as a single line string, escaping the quotes:
.. code-block:: ini
jwt-secret = "{ \"alg\":\"RS256\", … }"
To generate such a public/private key pair use a utility like `latchset/jose <https://github.com/latchset/jose>`_.
.. code-block:: bash
jose jwk gen -i '{"alg": "RS256"}' -o rsa.jwk
jose jwk pub -i rsa.jwk -o rsa.jwk.pub
# now rsa.jwk.pub contains the desired JSON object
You can specify the literal value as we saw earlier, or reference a filename to load the JWK from a file:
.. code-block:: ini
jwt-secret = "@rsa.jwk.pub"
JWT security
~~~~~~~~~~~~
There are at least three types of common critiques against using JWT: 1) against the standard itself, 2) against using libraries with known security vulnerabilities, and 3) against using JWT for web sessions. We'll briefly explain each critique, how PostgREST deals with it, and give recommendations for appropriate user action.
The critique against the `JWT standard <https://datatracker.ietf.org/doc/html/rfc7519>`_ is voiced in detail `elsewhere on the web <https://web.archive.org/web/20230123041631/https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid>`_. The most relevant part for PostgREST is the so-called :code:`alg=none` issue. Some servers implementing JWT allow clients to choose the algorithm used to sign the JWT. In this case, an attacker could set the algorithm to :code:`none`, remove the need for any signature at all and gain unauthorized access. The current implementation of PostgREST, however, does not allow clients to set the signature algorithm in the HTTP request, making this attack irrelevant. The critique against the standard is that it requires the implementation of the :code:`alg=none` at all.
Critiques against JWT libraries are only relevant to PostgREST via the library it uses. As mentioned above, not allowing clients to choose the signature algorithm in HTTP requests removes the greatest risk. Another more subtle attack is possible where servers use asymmetric algorithms like RSA for signatures. Once again this is not relevant to PostgREST since it is not supported. Curious readers can find more information in `this article <https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/>`_. Recommendations about high quality libraries for usage in API clients can be found on `jwt.io <https://jwt.io/>`_.
The last type of critique focuses on the misuse of JWT for maintaining web sessions. The basic recommendation is to `stop using JWT for sessions <http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/>`_ because most, if not all, solutions to the problems that arise when you do, `do not work <http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/>`_. The linked articles discuss the problems in depth but the essence of the problem is that JWT is not designed to be secure and stateful units for client-side storage and therefore not suited to session management.
PostgREST uses JWT mainly for authentication and authorization purposes and encourages users to do the same. For web sessions, using cookies over HTTPS is good enough and well catered for by standard web frameworks.
Schema Isolation
================
You can isolate your api schema from internal implementation details, as explained in :ref:`schema_isolation`. For an example of wrapping a private table with a public view see the :ref:`public_ui` section below.
.. _sql_user_management:
SQL User Management
===================
Storing Users and Passwords
---------------------------
As mentioned, an external service can provide user management and coordinate with the PostgREST server using JWT. It's also possible to support logins entirely through SQL. It's a fair bit of work, so get ready.
The following table, functions, and triggers will live in a :code:`basic_auth` schema that you shouldn't expose publicly in the API. The public views and functions will live in a different schema which internally references this internal information.
First we'll need a table to keep track of our users:
.. code:: sql
-- We put things inside the basic_auth schema to hide
-- them from public view. Certain public procs/views will
-- refer to helpers and tables inside.
create schema if not exists basic_auth;
create table if not exists
basic_auth.users (
email text primary key check ( email ~* '^.+@.+\..+$' ),
pass text not null check (length(pass) < 512),
role name not null check (length(role) < 512)
);
We would like the role to be a foreign key to actual database roles, however PostgreSQL does not support these constraints against the :code:`pg_roles` table. We'll use a trigger to manually enforce it.
.. code-block:: plpgsql
create or replace function
basic_auth.check_role_exists() returns trigger as $$
begin
if not exists (select 1 from pg_roles as r where r.rolname = new.role) then
raise foreign_key_violation using message =
'unknown database role: ' || new.role;
return null;
end if;
return new;
end
$$ language plpgsql;
drop trigger if exists ensure_user_role_exists on basic_auth.users;
create constraint trigger ensure_user_role_exists
after insert or update on basic_auth.users
for each row
execute procedure basic_auth.check_role_exists();
Next we'll use the pgcrypto extension and a trigger to keep passwords safe in the :code:`users` table.
.. code-block:: plpgsql
create extension if not exists pgcrypto;
create or replace function
basic_auth.encrypt_pass() returns trigger as $$
begin
if tg_op = 'INSERT' or new.pass <> old.pass then
new.pass = crypt(new.pass, gen_salt('bf'));
end if;
return new;
end
$$ language plpgsql;
drop trigger if exists encrypt_pass on basic_auth.users;
create trigger encrypt_pass
before insert or update on basic_auth.users
for each row
execute procedure basic_auth.encrypt_pass();
With the table in place we can make a helper to check a password against the encrypted column. It returns the database role for a user if the email and password are correct.
.. code-block:: plpgsql
create or replace function
basic_auth.user_role(email text, pass text) returns name
language plpgsql
as $$
begin
return (
select role from basic_auth.users
where users.email = user_role.email
and users.pass = crypt(user_role.pass, users.pass)
);
end;
$$;
.. _public_ui:
Public User Interface
---------------------
In the previous section we created an internal table to store user information. Here we create a login function which takes an email address and password and returns JWT if the credentials match a user in the internal table.
Permissions
~~~~~~~~~~~
Your database roles need access to the schema, tables, views and functions in order to service HTTP requests.
Recall from the `Overview of Role System`_ that PostgREST uses special roles to process requests, namely the authenticator and
anonymous roles. Below is an example of permissions that allow anonymous users to create accounts and attempt to log in.
.. code-block:: postgres
-- the names "anon" and "authenticator" are configurable and not
-- sacred, we simply choose them for clarity
create role anon noinherit;
create role authenticator noinherit;
grant anon to authenticator;
Then, add ``db-anon-role`` to the configuration file to allow anonymous requests.
.. code:: ini
db-anon-role = "anon"
Logins
~~~~~~
As described in `JWT from SQL`_, we'll create a JWT inside our login function. Note that you'll need to adjust the secret key which is hard-coded in this example to a secure (at least thirty-two character) secret of your choosing.
.. code-block:: postgres
-- add type
CREATE TYPE basic_auth.jwt_token AS (
token text
);
-- login should be on your exposed schema
create or replace function
login(email text, pass text) returns basic_auth.jwt_token as $$
declare
_role name;
result basic_auth.jwt_token;
begin
-- check email and password
select basic_auth.user_role(email, pass) into _role;
if _role is null then
raise invalid_password using message = 'invalid user or password';
end if;
select sign(
row_to_json(r), 'reallyreallyreallyreallyverysafe'
) as token
from (
select _role as role, login.email as email,
extract(epoch from now())::integer + 60*60 as exp
) r
into result;
return result;
end;
$$ language plpgsql security definer;
grant execute on function login(text,text) to anon;
Since the above :code:`login` function is defined as `security definer <https://www.postgresql.org/docs/current/sql-createfunction.html#id-1.9.3.67.10.2>`_,
the anonymous user :code:`anon` doesn't need permission to read the :code:`basic_auth.users` table. It doesn't even need permission to access the :code:`basic_auth` schema.
:code:`grant execute on function` is included for clarity but it might not be needed, see :ref:`func_privs` for more details.
An API request to call this function would look like:
.. tabs::
.. code-tab:: http
POST /rpc/login HTTP/1.1
{ "email": "foo@bar.com", "pass": "foobar" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "email": "foo@bar.com", "pass": "foobar" }'
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`reallyreallyreallyreallyverysafe` as specified in the SQL code above. You'll want to change this secret in your app!)
.. code:: json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImZvb0BiYXIuY29tIiwicGFzcyI6ImZvb2JhciJ9.37066TTRlh-1hXhnA9oO9Pj6lgL6zFuJU0iCHhuCFno"
}
Alternatives
~~~~~~~~~~~~
See the how-to :ref:`sql-user-management-using-postgres-users-and-passwords` for a similar way that completely avoids the table :code:`basic_auth.users`.
+293
View File
@@ -0,0 +1,293 @@
# -*- coding: utf-8 -*-
#
# PostgREST documentation build configuration file, created by
# sphinx-quickstart on Sun Oct 9 16:53:00 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ["sphinx_tabs.tabs", "sphinx_copybutton"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = "index"
# This is overriden by readthedocs with the version tag anyway
version = "10.2"
# To avoid repetition in <title> we set this to an empty string.
release = ""
# General information about the project.
project = "PostgREST " + version
author = "Joe Nelson, Steve Chavez"
copyright = "2017, " + author
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {"display_version": False}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
# html_title = u'PostgREST v0.4.0.0'
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = "_static/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = "PostgRESTdoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, "PostgREST.tex", "PostgREST Documentation", author, "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "postgrest", "PostgREST Documentation", [author], 1)]
# If true, show URL addresses after external links.
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
master_doc,
"PostgREST",
"PostgREST Documentation",
author,
"PostgREST",
"REST API for any PostgreSQL database",
"Web",
),
]
# Documents to append as an appendix to all manuals.
# texinfo_appendices = []
# If false, no module index is generated.
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False
# -- Custom setup ---------------------------------------------------------
def setup(app):
app.add_css_file("css/custom.css")
user_agent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0"
# sphinx-tabs configuration
sphinx_tabs_disable_tab_closing = True
+728
View File
@@ -0,0 +1,728 @@
.. _configuration:
Configuration
=============
Without configuration, PostgREST won't be able to serve requests. At the minimum it needs either :ref:`a role to serve anonymous requests with <db-anon-role>` - or :ref:`a secret to use for JWT authentication <jwt-secret>`. Config parameters can be provided via :ref:`file_config`, via :ref:`env_variables_config` or through :ref:`in_db_config`.
To connect to a database it uses a `libpq connection string <https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING>`_. The connection string can be set in the configuration file or via environment variable or can be read from an external file. See :ref:`db-uri` for details. Any parameter that is not set in the connection string is read from `libpq environment variables <https://www.postgresql.org/docs/current/libpq-envars.html>`_. The default connection string is ``postgresql://``, which reads **all** parameters from the environment.
The user with whom PostgREST connects to the database is also known as the authenticator role. For more information about the anonymous vs authenticator roles see :ref:`roles`.
Config parameters are read in the following order:
1. From the config file.
2. From environment variables, overriding values from the config file.
3. From the database, overriding values from both the config file and environment variables.
.. _file_config:
Config File
-----------
PostgREST can read a config file. There is no predefined location for this file, you must specify the file path as the one and only argument to the server:
.. code:: bash
./postgrest /path/to/postgrest.conf
.. note::
Configuration can be reloaded without restarting the server. See :ref:`config_reloading`.
The configuration file must contain a set of key value pairs:
.. code::
# postgrest.conf
# The standard connection URI format, documented at
# https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
db-uri = "postgres://user:pass@host:5432/dbname"
# The database role to use when no client authentication is provided.
# Should differ from authenticator
db-anon-role = "anon"
# The secret to verify the JWT for authenticated requests with.
# Needs to be 32 characters minimum.
jwt-secret = "reallyreallyreallyreallyverysafe"
jwt-secret-is-base64 = False
# Port the postgrest process is listening on for http requests
server-port = 80
You can run ``postgrest --example`` to display all possible configuration parameters and how to use them in a configuration file.
.. _env_variables_config:
Environment Variables
---------------------
You can also set these :ref:`configuration parameters <config_full_list>` using environment variables. They are capitalized, have a ``PGRST_`` prefix, and use underscores. For example: ``PGRST_DB_URI`` corresponds to ``db-uri`` and ``PGRST_APP_SETTINGS_*`` to ``app.settings.*``.
.. _in_db_config:
In-Database Configuration
-------------------------
By adding settings to the **authenticator** role (see :ref:`roles`), you can make the database the single source of truth for PostgREST's configuration.
This is enabled by :ref:`db-config`.
For example, you can configure :ref:`db-schemas` and :ref:`jwt-secret` like this:
.. code:: postgresql
ALTER ROLE authenticator SET pgrst.db_schemas = "tenant1, tenant2, tenant3"
ALTER ROLE authenticator IN DATABASE <your_database_name> SET pgrst.jwt_secret = "REALLYREALLYREALLYREALLYVERYSAFE"
You can use both database-specific settings with `IN DATABASE` and cluster-wide settings without it. Database-specific settings will override cluster-wide settings if both are used for the same parameter.
Note that underscores(``_``) need to be used instead of dashes(``-``) for the in-database config parameters.
.. important::
For altering a role in this way, you need a SUPERUSER. You might not be able to use this configuration mode on cloud-hosted databases.
When using both the configuration file and the in-database configuration, the latter takes precedence.
.. danger::
If direct connections to the database are allowed, then it's not safe to use the in-db configuration for storing the :ref:`jwt-secret`.
The settings of every role are PUBLIC - they can be viewed by any user that queries the ``pg_catalog.pg_db_role_setting`` table.
In this case you should keep the :ref:`jwt-secret` in the configuration file or as environment variables.
.. _config_reloading:
Configuration Reloading
=======================
It's possible to reload PostgREST's configuration without restarting the server. You can do this :ref:`via signal <config_reloading_signal>` or :ref:`via notification <config_reloading_notify>`.
It's not possible to change :ref:`env_variables_config` for a running process and reloading a Docker container configuration will not work. In these cases, you need to restart the PostgREST server or use :ref:`in_db_config` as an alternative.
.. important::
The following settings will not be reloaded. You will need to restart PostgREST to change those.
* :ref:`admin-server-port`
* :ref:`db-uri`
* :ref:`db-pool`
* :ref:`db-pool-acquisition-timeout`
* :ref:`db-pool-max-lifetime`
* :ref:`server-host`
* :ref:`server-port`
* :ref:`server-unix-socket`
* :ref:`server-unix-socket-mode`
.. _config_reloading_signal:
Reload with signal
------------------
To reload the configuration via signal, send a SIGUSR2 signal to the server process.
.. code:: bash
killall -SIGUSR2 postgrest
.. _config_reloading_notify:
Reload with NOTIFY
------------------
To reload the configuration from within the database, you can use a NOTIFY command.
.. code:: postgresql
NOTIFY pgrst, 'reload config'
The ``"pgrst"`` notification channel is enabled by default. For configuring the channel, see :ref:`db-channel` and :ref:`db-channel-enabled`.
.. _config_full_list:
List of parameters
==================
=========================== ======= ================= ==========
Name Type Default Reloadable
=========================== ======= ================= ==========
admin-server-port Int
app.settings.* String Y
db-anon-role String Y
db-channel String pgrst Y
db-channel-enabled Boolean True Y
db-config Boolean True Y
db-extra-search-path String public Y
db-max-rows Int ∞ Y
db-plan-enabled Boolean False Y
db-pool Int 10
db-pool-acquisition-timeout Int 10
db-pool-max-lifetime Int 1800
db-pre-request String Y
db-prepared-statements Boolean True Y
db-schemas String public Y
db-tx-end String commit
db-uri String postgresql://
db-use-legacy-gucs Boolean True Y
jwt-aud String Y
jwt-role-claim-key String .role Y
jwt-secret String Y
jwt-secret-is-base64 Boolean False Y
log-level String error Y
openapi-mode String follow-privileges Y
openapi-security-active Boolean False Y
openapi-server-proxy-uri String Y
raw-media-types String Y
server-host String !4
server-port Int 3000
server-unix-socket String
server-unix-socket-mode String 660
=========================== ======= ================= ==========
.. _admin-server-port:
admin-server-port
-----------------
=============== =======================
**Environment** PGRST_ADMIN_SERVER_PORT
**In-Database** `n/a`
=============== =======================
Specifies the port for the :ref:`health_check` endpoints.
.. _app.settings.*:
app.settings.*
--------------
=============== ====================
**Environment** PGRST_APP_SETTINGS_*
**In-Database** pgrst.app_settings_*
=============== ====================
Arbitrary settings that can be used to pass in secret keys directly as strings, or via OS environment variables. For instance: :code:`app.settings.jwt_secret = "$(MYAPP_JWT_SECRET)"` will take :code:`MYAPP_JWT_SECRET` from the environment and make it available to postgresql functions as :code:`current_setting('app.settings.jwt_secret')`.
.. _db-anon-role:
db-anon-role
------------
=============== ==================
**Environment** PGRST_DB_ANON_ROLE
**In-Database** `n/a`
=============== ==================
The database role to use when executing commands on behalf of unauthenticated clients. For more information, see :ref:`roles`.
When unset anonymous access will be blocked.
.. _db-channel:
db-channel
----------
=============== ================
**Environment** PGRST_DB_CHANNEL
**In-Database** `n/a`
=============== ================
The name of the notification channel that PostgREST uses for :ref:`schema_reloading` and configuration reloading.
.. _db-channel-enabled:
db-channel-enabled
------------------
=============== ========================
**Environment** PGRST_DB_CHANNEL_ENABLED
**In-Database** `n/a`
=============== ========================
When this is set to :code:`true`, the notification channel specified in :ref:`db-channel` is enabled.
You should set this to ``false`` when using PostgresSQL behind an external connection pooler such as PgBouncer working in transaction pooling mode. See :ref:`this section <external_connection_poolers>` for more information.
.. _db-config:
db-config
---------
=============== ===============
**Environment** PGRST_DB_CONFIG
**In-Database** `n/a`
=============== ===============
Enables the in-database configuration.
.. _db-extra-search-path:
db-extra-search-path
--------------------
=============== ==========================
**Environment** PGRST_DB_EXTRA_SEARCH_PATH
**In-Database** pgrst.db_extra_search_path
=============== ==========================
Extra schemas to add to the `search_path <https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH>`_ of every request. These schemas tables, views and stored procedures **don't get API endpoints**, they can only be referred from the database objects inside your :ref:`db-schemas`.
This parameter was meant to make it easier to use **PostgreSQL extensions** (like PostGIS) that are outside of the :ref:`db-schemas`.
Multiple schemas can be added in a comma-separated string, e.g. ``public, extensions``.
.. _db-max-rows:
db-max-rows
-----------
*For backwards compatibility, this config parameter is also available without prefix as "max-rows".*
=============== =================
**Environment** PGRST_DB_MAX_ROWS
**In-Database** pgrst.db_max_rows
=============== =================
A hard limit to the number of rows PostgREST will fetch from a view, table, or stored procedure. Limits payload size for accidental or malicious requests.
.. _db-plan-enabled:
db-plan-enabled
---------------
=============== =====================
**Environment** PGRST_DB_PLAN_ENABLED
**In-Database** pgrst.db_plan_enabled
=============== =====================
When this is set to :code:`true`, the execution plan of a request can be retrieved by using the :code:`Accept: application/vnd.pgrst.plan` header. See :ref:`explain_plan`.
It's recommended to use this in testing environments only since it reveals internal database details.
However, if you choose to use it in production you can add a :ref:`db-pre-request` to filter the requests that can use this feature.
For example, to only allow requests from an IP address to get the execution plans:
.. code-block:: postgresql
-- Assuming a proxy(Nginx, Cloudflare, etc) passes an "X-Forwarded-For" header(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)
create or replace function filter_plan_requests()
returns void as $$
declare
headers json := current_setting('request.headers', true)::json;
client_ip text := coalesce(headers->>'x-forwarded-for', '');
accept text := coalesce(headers->>'accept', '');
begin
if accept like 'application/vnd.pgrst.plan%' and client_ip != '144.96.121.73' then
raise insufficient_privilege using
message = 'Not allowed to use application/vnd.pgrst.plan';
end if;
end; $$ language plpgsql;
-- set this function on your postgrest.conf
-- db-pre-request = filter_plan_requests
.. _db-pool:
db-pool
-------
=============== =================
**Environment** PGRST_DB_POOL
**In-Database** `n/a`
=============== =================
Number of connections to keep open in PostgREST's database pool. Having enough here for the maximum expected simultaneous client connections can improve performance. Note it's pointless to set this higher than the :code:`max_connections` GUC in your database.
.. _db-pool-acquisition-timeout:
db-pool-acquisition-timeout
---------------------------
=============== =================
**Environment** PGRST_DB_POOL_ACQUISITION_TIMEOUT
**In-Database** `n/a`
=============== =================
Specifies the maximum time in seconds that the request will wait for the pool to free up a connection slot to the database. If it times out without acquiring a connection, then the request is aborted and a ``504`` error is returned.
.. _db-pool-max-lifetime:
db-pool-max-lifetime
--------------------
=============== =================
**Environment** PGRST_DB_POOL_MAX_LIFETIME
**In-Database** `n/a`
=============== =================
Specifies the maximum time in seconds of an existing connection in the pool. When this lifetime is reached, then the connection will be closed and returned to the pool.
.. _db-pre-request:
db-pre-request
--------------
*For backwards compatibility, this config parameter is also available without prefix as "pre-request".*
=============== =================
**Environment** PGRST_DB_PRE_REQUEST
**In-Database** pgrst.db_pre_request
=============== =================
A schema-qualified stored procedure name to call right after switching roles for a client request. This provides an opportunity to modify SQL variables or raise an exception to prevent the request from completing.
.. _db-prepared-statements:
db-prepared-statements
----------------------
=============== =================
**Environment** PGRST_DB_PREPARED_STATEMENTS
**In-Database** pgrst.db_prepared_statements
=============== =================
Enables or disables prepared statements.
When disabled, the generated queries will be parameterized (invulnerable to SQL injection) but they will not be prepared (cached in the database session). Not using prepared statements will noticeably decrease performance, so it's recommended to always have this setting enabled.
You should only set this to ``false`` when using PostgresSQL behind an external connection pooler such as PgBouncer working in transaction pooling mode. See :ref:`this section <external_connection_poolers>` for more information.
.. _db-schemas:
db-schemas
----------
*For backwards compatibility, this config parameter is also available in singular as "db-schema".*
=============== =================
**Environment** PGRST_DB_SCHEMAS
**In-Database** pgrst.db_schemas
=============== =================
The database schema to expose to REST clients. Tables, views and stored procedures in this schema will get API endpoints.
.. code:: bash
db-schemas = "api"
This schema gets added to the `search_path <https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH>`_ of every request.
List of schemas
~~~~~~~~~~~~~~~
You can also specify a list of schemas that can be used for **schema-based multitenancy** and **api versioning** by :ref:`multiple-schemas`. Example:
.. code:: bash
db-schemas = "tenant1, tenant2"
If you don't :ref:`Switch Schemas <multiple-schemas>`, the first schema in the list(``tenant1`` in this case) is chosen as the default schema.
*Only the chosen schema* gets added to the `search_path <https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH>`_ of every request.
.. warning::
Never expose private schemas in this way. See :ref:`schema_isolation`.
.. _db-tx-end:
db-tx-end
---------
=============== =================
**Environment** PGRST_DB_TX_END
**In-Database** pgrst.db_tx_end
=============== =================
Specifies how to terminate the database transactions.
.. code:: bash
# The transaction is always committed
db-tx-end = "commit"
# The transaction is committed unless a "Prefer: tx=rollback" header is sent
db-tx-end = "commit-allow-override"
# The transaction is always rolled back
db-tx-end = "rollback"
# The transaction is rolled back unless a "Prefer: tx=commit" header is sent
db-tx-end = "rollback-allow-override"
.. _db-uri:
db-uri
------
=============== =================
**Environment** PGRST_DB_URI
**In-Database** `n/a`
=============== =================
The standard connection PostgreSQL `URI format <https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING>`_. Symbols and unusual characters in the password or other fields should be percent encoded to avoid a parse error. If enforcing an SSL connection to the database is required you can use `sslmode <https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS>`_ in the URI, for example ``postgres://user:pass@host:5432/dbname?sslmode=require``.
When running PostgREST on the same machine as PostgreSQL, it is also possible to connect to the database using a `Unix socket <https://en.wikipedia.org/wiki/Unix_domain_socket>`_ and the `Peer Authentication method <https://www.postgresql.org/docs/current/auth-peer.html>`_ as an alternative to TCP/IP communication and authentication with a password, this also grants higher performance. To do this you can omit the host and the password, e.g. ``postgres://user@/dbname``, see the `libpq connection string <https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING>`_ documentation for more details.
Choosing a value for this parameter beginning with the at sign such as ``@filename`` (e.g. ``@./configs/my-config``) loads the connection string out of an external file.
.. _db-use-legacy-gucs:
db-use-legacy-gucs
------------------
=============== =================
**Environment** PGRST_DB_USE_LEGACY_GUCS
**In-Database** pgrst.db_use_legacy_gucs
=============== =================
Determine if GUC request settings for headers, cookies and jwt claims use the :ref:`legacy names <guc_legacy_names>` (string with dashes, invalid starting from PostgreSQL v14) with text values instead of the :ref:`new names <guc_req_headers_cookies_claims>` (string without dashes, valid on all PostgreSQL versions) with json values.
On PostgreSQL versions 14 and above, this parameter is ignored.
.. _jwt-aud:
jwt-aud
-------
=============== =================
**Environment** PGRST_JWT_AUD
**In-Database** pgrst.jwt_aud
=============== =================
Specifies the `JWT audience claim <https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3>`_. If this claim is present in the client provided JWT then you must set this to the same value as in the JWT, otherwise verifying the JWT will fail.
.. _jwt-role-claim-key:
jwt-role-claim-key
------------------
*For backwards compatibility, this config parameter is also available without prefix as "role-claim-key".*
=============== =================
**Environment** PGRST_JWT_ROLE_CLAIM_KEY
**In-Database** pgrst.jwt_role_claim_key
=============== =================
A JSPath DSL that specifies the location of the :code:`role` key in the JWT claims. This can be used to consume a JWT provided by a third party service like Auth0, Okta or Keycloak. Usage examples:
.. code:: bash
# {"postgrest":{"roles": ["other", "author"]}}
# the DSL accepts characters that are alphanumerical or one of "_$@" as keys
jwt-role-claim-key = ".postgrest.roles[1]"
# {"https://www.example.com/role": { "key": "author }}
# non-alphanumerical characters can go inside quotes(escaped in the config value)
jwt-role-claim-key = ".\"https://www.example.com/role\".key"
.. _jwt-secret:
jwt-secret
----------
=============== =================
**Environment** PGRST_JWT_SECRET
**In-Database** pgrst.jwt_secret
=============== =================
The secret or `JSON Web Key (JWK) (or set) <https://datatracker.ietf.org/doc/html/rfc7517>`_ used to decode JWT tokens clients provide for authentication. For security the key must be **at least 32 characters long**. If this parameter is not specified then PostgREST refuses authentication requests. Choosing a value for this parameter beginning with the at sign such as :code:`@filename` loads the secret out of an external file. This is useful for automating deployments. Note that any binary secrets must be base64 encoded. Both symmetric and asymmetric cryptography are supported. For more info see :ref:`asym_keys`.
Choosing a value for this parameter beginning with the at sign such as ``@filename`` (e.g. ``@./configs/my-config``) loads the secret out of an external file.
.. warning::
Only when using the :ref:`file_config`, if the ``jwt-secret`` contains a ``$`` character by itself it will give errors. In this case, use ``$$`` and PostgREST will interpret it as a single ``$`` character.
.. _jwt-secret-is-base64:
jwt-secret-is-base64
--------------------
=============== =================
**Environment** PGRST_JWT_SECRET_IS_BASE64
**In-Database** pgrst.jwt_secret_is_base64
=============== =================
When this is set to :code:`true`, the value derived from :code:`jwt-secret` will be treated as a base64 encoded secret.
.. _log-level:
log-level
---------
=============== =================
**Environment** PGRST_LOG_LEVEL
**In-Database** `n/a`
=============== =================
Specifies the level of information to be logged while running PostgREST.
.. code:: bash
# Only startup and db connection recovery messages are logged
log-level = "crit"
# All the "crit" level events plus server errors (status 5xx) are logged
log-level = "error"
# All the "error" level events plus request errors (status 4xx) are logged
log-level = "warn"
# All the "warn" level events plus all requests (every status code) are logged
log-level = "info"
Because currently there's no buffering for logging, the levels with minimal logging(``crit/error``) will increase throughput.
.. _openapi-mode:
openapi-mode
------------
=============== =================
**Environment** PGRST_OPENAPI_MODE
**In-Database** pgrst.openapi_mode
=============== =================
Specifies how the OpenAPI output should be displayed.
.. code:: bash
# Follows the privileges of the JWT role claim (or from db-anon-role if the JWT is not sent)
# Shows information depending on the permissions that the role making the request has
openapi-mode = "follow-privileges"
# Ignores the privileges of the JWT role claim (or from db-anon-role if the JWT is not sent)
# Shows all the exposed information, regardless of the permissions that the role making the request has
openapi-mode = "ignore-privileges"
# Disables the OpenApi output altogether.
# Throws a `404 Not Found` error when accessing the API root path
openapi-mode = "disabled"
.. _openapi-security-active:
openapi-security-active
-----------------------
=============== =============================
**Environment** PGRST_OPENAPI_SECURITY_ACTIVE
**In-Database** pgrst.openapi_security_active
=============== =============================
When this is set to :code:`true`, security options are included in the :ref:`OpenAPI output <open-api>`.
.. _openapi-server-proxy-uri:
openapi-server-proxy-uri
------------------------
=============== =================
**Environment** PGRST_OPENAPI_SERVER_PROXY_URI
**In-Database** pgrst.openapi_server_proxy_uri
=============== =================
Overrides the base URL used within the OpenAPI self-documentation hosted at the API root path. Use a complete URI syntax :code:`scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]`. Ex. :code:`https://postgrest.com`
.. code:: json
{
"swagger": "2.0",
"info": {
"version": "0.4.3.0",
"title": "PostgREST API",
"description": "This is a dynamic API generated by PostgREST"
},
"host": "postgrest.com:443",
"basePath": "/",
"schemes": [
"https"
]
}
.. _raw-media-types:
raw-media-types
---------------
=============== =================
**Environment** PGRST_RAW_MEDIA_TYPES
**In-Database** pgrst.raw_media_types
=============== =================
This serves to extend the `Media Types <https://en.wikipedia.org/wiki/Media_type>`_ that PostgREST currently accepts through an ``Accept`` header.
These media types can be requested by following the same rules as the ones defined in :ref:`scalar_return_formats`.
As an example, the below config would allow you to request an **image** and a **XML** file by doing a request with ``Accept: image/png``
or ``Accept: font/woff2``, respectively.
.. code:: bash
raw-media-types="image/png, font/woff2"
.. _server-host:
server-host
-----------
=============== =================
**Environment** PGRST_SERVER_HOST
**In-Database** `n/a`
=============== =================
Where to bind the PostgREST web server. In addition to the usual address options, PostgREST interprets these reserved addresses with special meanings:
* :code:`*` - any IPv4 or IPv6 hostname
* :code:`*4` - any IPv4 or IPv6 hostname, IPv4 preferred
* :code:`!4` - any IPv4 hostname
* :code:`*6` - any IPv4 or IPv6 hostname, IPv6 preferred
* :code:`!6` - any IPv6 hostname
.. _server-port:
server-port
-----------
=============== =================
**Environment** PGRST_SERVER_PORT
**In-Database** `n/a`
=============== =================
The TCP port to bind the web server.
.. _server-unix-socket:
server-unix-socket
------------------
=============== =================
**Environment** PGRST_SERVER_UNIX_SOCKET
**In-Database** `n/a`
=============== =================
`Unix domain socket <https://en.wikipedia.org/wiki/Unix_domain_socket>`_ where to bind the PostgREST web server.
If specified, this takes precedence over :ref:`server-port`. Example:
.. code:: bash
server-unix-socket = "/tmp/pgrst.sock"
.. _server-unix-socket-mode:
server-unix-socket-mode
-----------------------
=============== =================
**Environment** PGRST_SERVER_UNIX_SOCKET_MODE
**In-Database** `n/a`
=============== =================
`Unix file mode <https://en.wikipedia.org/wiki/File_system_permissions>`_ to be set for the socket specified in :ref:`server-unix-socket`
Needs to be a valid octal between 600 and 777.
.. code:: bash
server-unix-socket-mode = "660"
+91
View File
@@ -0,0 +1,91 @@
let
# Commit of the Nixpkgs repository that we want to use.
nixpkgsVersion = {
date = "2021-06-02";
rev = "84aa23742f6c72501f9cc209f29c438766f5352d";
tarballHash = "0h7xl6q0yjrbl9vm3h6lkxw692nm8bg3wy65gm95a2mivhrdjpxp";
};
# Nix files that describe the Nixpkgs repository. We evaluate the expression
# using `import` below.
pkgs = import
(fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/${nixpkgsVersion.rev}.tar.gz";
sha256 = nixpkgsVersion.tarballHash;
})
{ };
sphinxTabsPkg = ps: ps.callPackage ./extensions/sphinx-tabs.nix { };
sphinxCopybuttonPkg = ps: ps.callPackage ./extensions/sphinx-copybutton.nix { };
python = pkgs.python3.withPackages (ps: [ ps.sphinx ps.sphinx_rtd_theme ps.livereload (sphinxTabsPkg ps) (sphinxCopybuttonPkg ps) ]);
in
{
inherit pkgs;
build =
pkgs.writeShellScriptBin "postgrest-docs-build"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
# clean previous build, otherwise some errors might be supressed
rm -rf _build
${python}/bin/sphinx-build --color -W -b html -a -n . _build
'';
serve =
pkgs.writeShellScriptBin "postgrest-docs-serve"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
# livereload_docs.py needs to find "sphinx-build"
PATH=${python}/bin:$PATH
${python}/bin/python livereload_docs.py
'';
spellcheck =
pkgs.writeShellScriptBin "postgrest-docs-spellcheck"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
FILES=$(find . -type f -iname '*.rst' | tr '\n' ' ')
cat $FILES \
| grep -v '^\(\.\.\| \)' \
| sed 's/`.*`//g' \
| ${pkgs.aspell}/bin/aspell -d ${pkgs.aspellDicts.en}/lib/aspell/en_US -p ./postgrest.dict list \
| sort -f \
| tee misspellings
test ! -s misspellings
'';
# dictcheck detects obsolete entries in postgrest.dict, that are not used anymore
dictcheck =
pkgs.writeShellScriptBin "postgrest-docs-dictcheck"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
FILES=$(find . -type f -iname '*.rst' | tr '\n' ' ')
cat postgrest.dict \
| tail -n+2 \
| tr '\n' '\0' \
| xargs -0 -n 1 -i \
sh -c "grep \"{}\" $FILES > /dev/null || echo \"{}\""
'';
linkcheck =
pkgs.writeShellScriptBin "postgrest-docs-linkcheck"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
${python}/bin/sphinx-build --color -b linkcheck . _build
'';
}
+128
View File
@@ -0,0 +1,128 @@
.. _community_tutorials:
Community Tutorials
-------------------
* `Building a Contacts List with PostgREST and Vue.js <https://www.youtube.com/watch?v=iHtsALtD5-U>`_ -
In this video series, DigitalOcean shows how to build and deploy an Nginx + PostgREST(using a managed PostgreSQL database) + Vue.js webapp in an Ubuntu server droplet.
* `PostgREST + Auth0: Create REST API in minutes, and add social login using Auth0 <https://samkhawase.com/blog/postgrest-1-introduction/>`_ - A step-by-step tutorial to show how to dockerize and integrate Auth0 to PostgREST service.
* `PostgREST + PostGIS API tutorial in 5 minutes <https://gis-ops.com/postgrest-postgis-api-tutorial-geospatial-api-in-5-minutes/>`_ -
In this tutorial, GIS • OPS shows how to perform PostGIS calculations through PostgREST :ref:`s_procs` interface.
* `"CodeLess" backend using postgres, postgrest and oauth2 authentication with keycloak <https://www.mathieupassenaud.fr/codeless_backend/>`_ -
A step-by-step tutorial for using PostgREST with KeyCloak(hosted on a managed service).
* `How PostgreSQL triggers work when called with a PostgREST PATCH HTTP request <https://blog.fgribreau.com/2020/11/how-postgresql-triggers-works-when.html>`_ - A tutorial to see how the old and new values are set or not when doing a PATCH request to PostgREST.
.. _templates:
Templates
---------
* `compose-postgrest <https://github.com/mattddowney/compose-postgrest>`_ - docker-compose setup with Nginx and HTML example
* `svelte-postgrest-template <https://github.com/guyromm/svelte-postgrest-template>`_ - Svelte/SvelteKit, PostgREST, EveryLayout and social auth
.. _eco_example_apps:
Example Apps
------------
* `chronicle <https://github.com/srid/chronicle>`_ - tracking a tree of personal memories
* `code-du-travail-backoffice <https://github.com/SocialGouv/code-du-travail-backoffice>`_ - data administration portal for the official French Labor Code and Agreements
* `delibrium-postgrest <https://gitlab.com/delibrium/delibrium-postgrest/>`_ - example school API and front-end in Vue.js
* `elm-workshop <https://github.com/diogob/elm-workshop>`_ - building a simple database query UI
* `ember-postgrest-dynamic-ui <https://github.com/benoror/ember-postgrest-dynamic-ui>`_ - generating Ember forms to edit data
* `ETH-transactions-storage <https://github.com/Adamant-im/ETH-transactions-storage>`_ - indexer for Ethereum to get transaction list by ETH address
* `ext-postgrest-crud <https://github.com/timwis/ext-postgrest-crud>`_ - browser-based spreadsheet
* `general <https://github.com/PierreRochard/general>`_ - example auth back-end
* `goodfilm <https://github.com/tyrchen/goodfilm>`_ - example film API
* `guild-operators <https://github.com/cardano-community/koios-artifacts/tree/main/files/grest>`_ - example queries and functions that the Cardano Community uses for their Guild Operators' Repository
* `handsontable-postgrest <https://github.com/timwis/handsontable-postgrest>`_ - an excel-like database table editor
* `heritage-near-me <https://github.com/CodeforAustralia/heritage-near-me>`_ - Elm and PostgREST with PostGIS
* `ng-admin-postgrest <https://github.com/marmelab/ng-admin-postgrest>`_ - automatic database admin panel
* `pgrst-dev-setup <https://github.com/Qu4tro/pgrst-dev-setup>`_ - docker-compose and tmuxp setup for experimentation.
* `postgres-postgrest-cloudflared-example <https://github.com/cloudflare/postgres-postgrest-cloudflared-example>`_ - docker-compose setup exposing PostgREST using cloudfared
* `postgrest-demo <https://github.com/SMRxT/postgrest-demo>`_ - multi-tenant logging system
* `postgrest-example <https://github.com/begriffs/postgrest-example>`_ - sqitch versioning for API
* `postgrest-sessions-example <https://github.com/monacoremo/postgrest-sessions-example>`_ - example for cookie-based sessions
* `postgrest-translation-proxy <https://github.com/NikolayS/postgrest-translation-proxy>`_ - calling to external translation service
* `postgrest-ui <https://github.com/tatut/postgrest-ui>`_ - ClojureScript UI components for PostgREST
* `postgrest-vercel <https://github.com/seveibar/postgrest-vercel>`_ - run PostgREST on Vercel (Serverless/AWS Lambda)
* `PostgrestSkeleton <https://github.com/Recmo/PostgrestSkeleton>`_ - Docker Compose, PostgREST, Nginx and Auth0
* `PostGUI <https://github.com/priyank-purohit/PostGUI>`_ - React Material UI admin panel
* `prospector <https://github.com/sfcta/prospector>`_ - data warehouse and visualization platform
.. _devops:
DevOps
------
* `cloudgov-demo-postgrest <https://github.com/GSA/cloudgov-demo-postgrest>`_ - demo for a federally-compliant REST API on cloud.gov
* `cloudstark/helm-charts <https://github.com/cloudstark/helm-charts/tree/master/postgrest>`_ - helm chart to deploy PostgREST to a Kubernetes cluster via a Deployment and Service
* `jbkarle/postgrest <https://github.com/jbkarle/postgrest>`_ - helm chart with a demo database for development and test purposes
* `Limezest/postgrest-cloud-run <https://github.com/Limezest/postgrest-cloud-run>`_ - expose a PostgreSQL database on Cloud SQL using Cloud Run
.. _eco_external_notification:
External Notification
---------------------
These are PostgreSQL bridges that propagate LISTEN/NOTIFY to external queues for further processing. This allows stored procedures to initiate actions outside the database such as sending emails.
* `pg-bridge <https://github.com/matthewmueller/pg-bridge>`_ - Amazon SNS
* `pg-kinesis-bridge <https://github.com/daurnimator/pg-kinesis-bridge>`_ - Amazon Kinesis
* `pg-notify-webhook <https://github.com/vbalasu/pg-notify-webhook>`_ - trigger webhooks from PostgreSQL's LISTEN/NOTIFY
* `pgsql-listen-exchange <https://github.com/gmr/pgsql-listen-exchange>`_ - RabbitMQ
* `postgres-websockets <https://github.com/diogob/postgres-websockets>`_ - expose web sockets for PostgreSQL's LISTEN/NOTIFY
* `postgresql-to-amqp <https://github.com/FGRibreau/postgresql-to-amqp>`_ - AMQP
* `postgresql2websocket <https://github.com/frafra/postgresql2websocket>`_ - Websockets
* `skeeter <https://github.com/SpiderOak/skeeter>`_ - ZeroMQ
.. _eco_extensions:
Extensions
----------
* `aiodata <https://github.com/Exahilosys/aiodata>`_ - Python, event-based proxy and caching client.
* `pg-safeupdate <https://github.com/eradman/pg-safeupdate>`_ - prevent full-table updates or deletes
* `postgrest-auth (criles25) <https://github.com/criles25/postgrest-auth>`_ - email based auth/signup
* `postgrest-node <https://github.com/seveibar/postgrest-node>`_ - Run a PostgREST server in Node.js via npm module
* `postgrest-oauth <https://github.com/nblumoe/postgrest-oauth>`_ - OAuth2 WAI middleware
* `postgrest-oauth/api <https://github.com/postgrest-oauth/api>`_ - OAuth2 server
* `PostgREST-writeAPI <https://github.com/ppKrauss/PostgREST-writeAPI>`_ - generate Nginx rewrite rules to fit an OpenAPI spec
* `spas <https://github.com/srid/spas>`_ - allow file uploads and basic auth
.. _clientside_libraries:
Client-Side Libraries
---------------------
* `aor-postgrest-client <https://github.com/tomberek/aor-postgrest-client>`_ - JS, admin-on-rest
* `elm-postgrest <https://github.com/john-kelly/elm-postgrest>`_ - Elm
* `general-angular <https://github.com/PierreRochard/general-angular>`_ - TypeScript, generate UI from API description
* `jarvus-postgrest-apikit <https://github.com/JarvusInnovations/jarvus-postgrest-apikit>`_ - JS, Sencha framework
* `mithril-postgrest <https://github.com/catarse/mithril-postgrest>`_ - JS, Mithril
* `ng-postgrest <https://github.com/team142/ng-postgrest>`_ - Angular app for browsing, editing data exposed over PostgREST.
* `postgrest-client <https://github.com/calebmer/postgrest-client>`_ - JS
* `postgrest-csharp <https://github.com/supabase-community/postgrest-csharp>`_ - C#
* `postgrest-dart <https://github.com/supabase-community/postgrest-dart>`_ - Dart
* `postgrest-ex <https://github.com/J0/postgrest-ex>`_ - Elixir
* `postgrest-go <https://github.com/supabase-community/postgrest-go>`_ - Go
* `postgrest-js <https://github.com/supabase/postgrest-js>`_ - TypeScript/JavaScript
* `postgrest-kt <https://github.com/supabase-community/postgrest-kt>`_ - Kotlin
* `postgrest-py <https://github.com/supabase/postgrest-py>`_ - Python
* `postgrest-request <https://github.com/lewisjared/postgrest-request>`_ - JS, SuperAgent
* `postgrest-rs <https://github.com/supabase-community/postgrest-rs>`_ - Rust
* `postgrest-sharp-client <https://github.com/thejettdurham/postgrest-sharp-client>`_ (needs maintainer) - C#, RestSharp
* `postgrest-swift <https://github.com/supabase-community/postgrest-swift>`_ - Swift
* `postgrest-url <https://github.com/hugomrdias/postgrest-url>`_ - JS, just for generating query URLs
* `postgrest_python_requests_client <https://github.com/davidthewatson/postgrest_python_requests_client>`_ - Python
* `postgrester <https://github.com/ivangabriele/postgrester>`_ - JS + Typescript
* `postgrestR <https://github.com/clesiemo3/postgrestR>`_ - R
* `py-postgrest <https://github.com/Kong/py-postgrest>`_ - Python
* `redux-postgrest <https://github.com/andytango/redux-postgrest>`_ - TypeScript/JS, client integrated with (React) Redux.
* `vue-postgrest <https://github.com/technowledgy/vue-postgrest>`_ - Vue.js
+298
View File
@@ -0,0 +1,298 @@
.. _error_source:
Error Source
============
For the most part, error messages will come directly from the database with the same `structure that PostgreSQL uses <https://www.postgresql.org/docs/current/error-style-guide.html>`_. PostgREST will convert the ``MESSAGE``, ``DETAIL``, ``HINT`` and ``ERRCODE`` from the PostgreSQL error to JSON format and add an HTTP status code to the response (see :ref:`status_codes`). For instance, this is the error you will get when querying a nonexistent table:
.. code-block:: http
GET /nonexistent_table?id=eq.1 HTTP/1.1
.. code-block:: http
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
.. code-block:: json
{
"hint": null,
"details": null,
"code": "42P01",
"message": "relation \"api.nonexistent_table\" does not exist"
}
However, some errors do come from PostgREST itself (such as those related to the :ref:`schema_cache`). These have the same structure as the PostgreSQL errors but are differentiated by the ``PGRST`` prefix in the ``code`` field (see :ref:`pgrst_errors`). For instance, when querying a function that does not exist, the error will be:
.. code-block:: http
POST /rpc/nonexistent_function HTTP/1.1
.. code-block:: http
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
.. code-block:: json
{
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
"details": null
"code": "PGRST202",
"message": "Could not find the api.nonexistent_function() function in the schema cache"
}
.. _status_codes:
HTTP Status Codes
=================
PostgREST translates `PostgreSQL error codes <https://www.postgresql.org/docs/current/errcodes-appendix.html>`_ into HTTP status as follows:
+--------------------------+-------------------------+---------------------------------+
| PostgreSQL error code(s) | HTTP status | Error description |
+==========================+=========================+=================================+
| 08* | 503 | pg connection err |
+--------------------------+-------------------------+---------------------------------+
| 09* | 500 | triggered action exception |
+--------------------------+-------------------------+---------------------------------+
| 0L* | 403 | invalid grantor |
+--------------------------+-------------------------+---------------------------------+
| 0P* | 403 | invalid role specification |
+--------------------------+-------------------------+---------------------------------+
| 23503 | 409 | foreign key violation |
+--------------------------+-------------------------+---------------------------------+
| 23505 | 409 | uniqueness violation |
+--------------------------+-------------------------+---------------------------------+
| 25006 | 405 | read only sql transaction |
+--------------------------+-------------------------+---------------------------------+
| 25* | 500 | invalid transaction state |
+--------------------------+-------------------------+---------------------------------+
| 28* | 403 | invalid auth specification |
+--------------------------+-------------------------+---------------------------------+
| 2D* | 500 | invalid transaction termination |
+--------------------------+-------------------------+---------------------------------+
| 38* | 500 | external routine exception |
+--------------------------+-------------------------+---------------------------------+
| 39* | 500 | external routine invocation |
+--------------------------+-------------------------+---------------------------------+
| 3B* | 500 | savepoint exception |
+--------------------------+-------------------------+---------------------------------+
| 40* | 500 | transaction rollback |
+--------------------------+-------------------------+---------------------------------+
| 53* | 503 | insufficient resources |
+--------------------------+-------------------------+---------------------------------+
| 54* | 413 | too complex |
+--------------------------+-------------------------+---------------------------------+
| 55* | 500 | obj not in prerequisite state |
+--------------------------+-------------------------+---------------------------------+
| 57* | 500 | operator intervention |
+--------------------------+-------------------------+---------------------------------+
| 58* | 500 | system error |
+--------------------------+-------------------------+---------------------------------+
| F0* | 500 | config file error |
+--------------------------+-------------------------+---------------------------------+
| HV* | 500 | foreign data wrapper error |
+--------------------------+-------------------------+---------------------------------+
| P0001 | 400 | default code for "raise" |
+--------------------------+-------------------------+---------------------------------+
| P0* | 500 | PL/pgSQL error |
+--------------------------+-------------------------+---------------------------------+
| XX* | 500 | internal error |
+--------------------------+-------------------------+---------------------------------+
| 42883 | 404 | undefined function |
+--------------------------+-------------------------+---------------------------------+
| 42P01 | 404 | undefined table |
+--------------------------+-------------------------+---------------------------------+
| 42501 | | if authenticated 403, | insufficient privileges |
| | | else 401 | |
+--------------------------+-------------------------+---------------------------------+
| other | 400 | |
+--------------------------+-------------------------+---------------------------------+
.. _pgrst_errors:
PostgREST Error Codes
=====================
PostgREST error codes have the form ``PGRSTgxx``, where ``PGRST`` is the prefix that differentiates the error from a PostgreSQL error, ``g`` is the group where the error belongs and ``xx`` is the number that identifies the error in the group.
.. _pgrst0**:
Group 0 - Connection
--------------------
Related to the connection with the database.
+---------------+-------------+-------------------------------------------------------------+
| Code | HTTP status | Description |
+===============+=============+=============================================================+
| .. _pgrst000: | 503 | Could not connect with the database due to an incorrect |
| | | :ref:`db-uri` or due to the PostgreSQL service not running. |
| PGRST000 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst001: | 503 | Could not connect with the database due to an internal |
| | | error. |
| PGRST001 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst002: | 503 | Could not connect with the database when building the |
| | | :ref:`schema_cache` due to the PostgreSQL service not |
| PGRST002 | | running. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst003: | 504 | The request timed out waiting for a pool connection |
| | | to be available. See :ref:`db-pool-acquisition-timeout`. |
| PGRST003 | | |
+---------------+-------------+-------------------------------------------------------------+
.. _pgrst1**:
Group 1 - Api Request
---------------------
Related to the HTTP request elements.
+---------------+-------------+-------------------------------------------------------------+
| Code | HTTP status | Description |
+===============+=============+=============================================================+
| .. _pgrst100: | 400 | Parsing error in the query string parameter. |
| | | See :ref:`h_filter`, :ref:`operators` and :ref:`ordering`. |
| PGRST100 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst101: | 405 | For :ref:`functions <s_procs>`, only ``GET`` and ``POST`` |
| | | verbs are allowed. Any other verb will throw this error. |
| PGRST101 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst102: | 400 | An invalid request body was sent(e.g. an empty body or |
| | | malformed JSON). |
| PGRST102 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst103: | 416 | An invalid range was specified for :ref:`limits`. |
| | | |
| PGRST103 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst105: | 405 | An invalid :ref:`PUT <upsert_put>` request was done |
| | | |
| PGRST105 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst106: | 406 | The schema specified when |
| | | :ref:`switching schemas <multiple-schemas>` is not present |
| PGRST106 | | in the :ref:`db-schemas` configuration variable. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst107: | 415 | The ``Content-Type`` sent in the request is invalid. |
| | | |
| PGRST107 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst108: | 400 | The filter is applied to a embedded resource that is not |
| | | specified in the ``select`` part of the query string. |
| PGRST108 | | See :ref:`embed_filters`. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst109: | 400 | Restricting a Deletion or an Update using limits must |
| | | include the ordering of a unique column. |
| PGRST109 | | See :ref:`limited_update_delete`. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst110: | 400 | When restricting a Deletion or an Update using limits |
| | | modifies more rows than the maximum specified in the limit. |
| PGRST110 | | See :ref:`limited_update_delete`. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst111: | 500 | An invalid ``response.headers`` was set. |
| | | See :ref:`guc_resp_hdrs`. |
| PGRST111 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst112: | 500 | The status code must be a positive integer. |
| | | See :ref:`guc_resp_status`. |
| PGRST112 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst113: | 406 | More than one column was returned for a scalar result. |
| | | See :ref:`scalar_return_formats`. |
| PGRST113 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst114: | 400 | For an :ref:`UPSERT using PUT <upsert_put>`, when |
| | | :ref:`limits and offsets <limits>` are used. |
| PGRST114 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst115: | 400 | For an :ref:`UPSERT using PUT <upsert_put>`, when the |
| | | primary key in the query string and the body are different. |
| PGRST115 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst116: | 406 | More than 1 or no items where returned when requesting |
| | | a singular response. See :ref:`singular_plural`. |
| PGRST116 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst117: | 405 | The HTTP verb used in the request in not supported. |
| | | |
| PGRST117 | | |
+---------------+-------------+-------------------------------------------------------------+
.. _pgrst2**:
Group 2 - Schema Cache
----------------------
Related to a :ref:`stale schema cache <stale_schema>`. Most of the time, these errors are solved by :ref:`reloading the schema cache <schema_reloading>`.
+---------------+-------------+-------------------------------------------------------------+
| Code | HTTP status | Description |
+===============+=============+=============================================================+
| .. _pgrst200: | 400 | Caused by :ref:`stale_fk_relationships`, otherwise any of |
| | | the embedding resources or the relationship itself may not |
| PGRST200 | | exist in the database. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst201: | 300 | An ambiguous embedding request was made. |
| | | See :ref:`embed_disamb`. |
| PGRST201 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst202: | 404 | Caused by a :ref:`stale_function_signature`, otherwise |
| | | the function may not exist in the database. |
| PGRST202 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst203: | 300 | Caused by requesting overloaded functions with the same |
| | | argument names but different types, or by using a ``POST`` |
| PGRST203 | | verb to request overloaded functions with a ``JSON`` or |
| | | ``JSONB`` type unnamed parameter. The solution is to rename |
| | | the function or add/modify the names of the arguments. |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst204: | 400 | Caused when the :ref:`column specified <specify_columns>` |
| | | in the ``columns`` query parameter is not found. |
| PGRST204 | | |
+---------------+-------------+-------------------------------------------------------------+
.. _pgrst3**:
Group 3 - JWT
-------------
Related to the authentication process using JWT. You can follow the :ref:`tut1` for an example on how to implement authentication and the :doc:`Authentication page <auth>` for more information on this process.
+---------------+-------------+-------------------------------------------------------------+
| Code | HTTP status | Description |
+===============+=============+=============================================================+
| .. _pgrst300: | 500 | A :ref:`JWT secret <jwt-secret>` is missing from the |
| | | configuration. |
| PGRST300 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst301: | 401 | Any error related to the verification of the JWT, |
| | | which means that the JWT provided is invalid in some way. |
| PGRST301 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst302: | 401 | Attempted to do a request without |
| | | :ref:`authentication <client_auth>` when the anonymous role |
| PGRST302 | | is disabled by not setting it in :ref:`db-anon-role`. |
+---------------+-------------+-------------------------------------------------------------+
.. The Internal Errors Group X** is always at the end
.. _pgrst_X**:
Group X - Internal
------------------
Internal errors. If you encounter any of these, you may have stumbled on a PostgREST bug, please `open an issue <https://github.com/PostgREST/postgrest/issues>`_ and we'll be glad to fix it.
+---------------+-------------+-------------------------------------------------------------+
| Code | HTTP status | Description |
+===============+=============+=============================================================+
| .. _pgrstX00: | 500 | Internal errors related to the library used for connecting |
| | | to the database. |
| PGRSTX00 | | |
+---------------+-------------+-------------------------------------------------------------+
+33
View File
@@ -0,0 +1,33 @@
{ lib
, buildPythonPackage
, fetchFromGitHub
, sphinx
}:
buildPythonPackage rec {
pname = "sphinx-copybutton";
version = "0.4.0";
src = fetchFromGitHub {
owner = "executablebooks";
repo = "sphinx-copybutton";
rev = "v${version}";
sha256 = "sha256-vrEIvQeP7AMXSme1PBp0ox5k8Q1rz+1cbHIO+o17Jqc=";
fetchSubmodules = true;
};
propagatedBuildInputs = [
sphinx
];
doCheck = false; # no tests
pythonImportsCheck = [ "sphinx_copybutton" ];
meta = with lib; {
description = "A small sphinx extension to add a \"copy\" button to code blocks";
homepage = "https://github.com/executablebooks/sphinx-copybutton";
license = licenses.mit;
maintainers = with maintainers; [ Luflosi ];
};
}
+29
View File
@@ -0,0 +1,29 @@
{ lib
, buildPythonPackage
, fetchPypi
, sphinx
}:
buildPythonPackage rec {
pname = "sphinx-tabs";
version = "3.2.0";
src = fetchPypi {
inherit pname version;
sha256 = "sha256:1970aahi6sa7c37cpz8nwgdb2xzf21rk6ykdd1m6w9wvxla7j4rk";
};
propagatedBuildInputs = [
sphinx
];
doCheck = false;
pythonImportsCheck = [ "sphinx_tabs" ];
meta = with lib; {
description = "Create tabbed content in Sphinx documentation when building HTML";
homepage = "https://sphinx-tabs.readthedocs.io";
license = licenses.mit;
};
}
+222
View File
@@ -0,0 +1,222 @@
.. _create_soap_endpoint:
Create a SOAP endpoint
======================
:author: `fjf2002 <https://github.com/fjf2002>`_
PostgREST now has XML support. With a bit of work, SOAP endpoints become possible.
Please note that PostgREST supports just ``text/xml`` MIME type in request/response headers ``Content-Type`` and ``Accept``.
If you have to use other MIME types such as ``application/soap+xml``, you could manipulate the headers in your reverse proxy.
Minimal Example
---------------
This example will simply return the request body, inside a tag ``therequestbodywas``.
Add the following function to your PostgreSQL database:
.. code-block:: postgres
CREATE OR REPLACE FUNCTION my_soap_endpoint(xml) RETURNS xml AS $$
DECLARE
nsarray CONSTANT text[][] := ARRAY[
ARRAY['soapenv', 'http://schemas.xmlsoap.org/soap/envelope/']
];
BEGIN
RETURN xmlelement(
NAME "soapenv:Envelope",
XMLATTRIBUTES('http://schemas.xmlsoap.org/soap/envelope/' AS "xmlns:soapenv"),
xmlelement(NAME "soapenv:Header"),
xmlelement(
NAME "soapenv:Body",
xmlelement(
NAME theRequestBodyWas,
(xpath('/soapenv:Envelope/soapenv:Body', $1, nsarray))[1]
)
)
);
END;
$$ LANGUAGE plpgsql;
Do not forget to refresh the :ref:`PostgREST schema cache <schema_reloading>`.
Use ``curl`` for a first test:
.. code-block:: bash
curl http://localhost:3000/rpc/my_soap_endpoint \
--header 'Content-Type: text/xml' \
--header 'Accept: text/xml' \
--data-binary @- <<XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<mySOAPContent>
My SOAP Content
</mySOAPContent>
</soapenv:Body>
</soapenv:Envelope>
XML
The output should contain the original request body within the ``therequestbodywas`` entity,
and should roughly look like:
.. code-block:: xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<therequestbodywas>
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<mySOAPContent>
My SOAP Content
</mySOAPContent>
</soapenv:Body>
</therequestbodywas>
</soapenv:Body>
</soapenv:Envelope>
Unfortunately the ``Accept: text/xml`` header is currently mandatory concerning PostgREST, otherwise it will respond
with a ``Content-Type: application/json`` header and enclose the response with quotes.
(You can check the returned headers by adding ``-v`` to the curl call.)
If your SOAP clients do not send the ``Accept: text/xml`` header, you can fix that in your nginx reverse proxy
by adding something like ...
.. code-block:: nginx
set $accept $http_accept;
if ($contentType ~ "^text/xml($|;)") {
set $accept "text/xml";
}
proxy_set_header Accept $accept;
to your ``location`` nginx configuration.
(The given example sets the ``Accept`` header for each request of Content-Type ``text/xml``.)
A more elaborate example
------------------------
Here we have a SOAP service that converts a fraction to a decimal value,
with pass-through of PostgreSQL errors to the SOAP response.
Please note that in production you probably should not pass through plain database errors
potentially disclosing internals to the client, but instead handle the errors directly.
.. code-block:: postgres
-- helper function
CREATE OR REPLACE FUNCTION _soap_envelope(body xml)
RETURNS xml
LANGUAGE sql
AS $function$
SELECT xmlelement(
NAME "soapenv:Envelope",
XMLATTRIBUTES('http://schemas.xmlsoap.org/soap/envelope/' AS "xmlns:soapenv"),
xmlelement(NAME "soapenv:Header"),
xmlelement(NAME "soapenv:Body", body)
);
$function$;
-- helper function
CREATE OR REPLACE FUNCTION _soap_exception(
faultcode text,
faultstring text
)
RETURNS xml
LANGUAGE sql
AS $function$
SELECT _soap_envelope(
xmlelement(NAME "soapenv:Fault",
xmlelement(NAME "faultcode", faultcode),
xmlelement(NAME "faultstring", faultstring)
)
);
$function$;
CREATE OR REPLACE FUNCTION fraction_to_decimal(xml)
RETURNS xml
LANGUAGE plpgsql
AS $function$
DECLARE
nsarray CONSTANT text[][] := ARRAY[
ARRAY['soapenv', 'http://schemas.xmlsoap.org/soap/envelope/']
];
exc_msg text;
exc_detail text;
exc_hint text;
exc_sqlstate text;
BEGIN
-- simulating a statement that results in an exception:
RETURN _soap_envelope(xmlelement(
NAME "decimalValue",
(
(xpath('/soapenv:Envelope/soapenv:Body/fraction/numerator/text()', $1, nsarray))[1]::text::int
/
(xpath('/soapenv:Envelope/soapenv:Body/fraction/denominator/text()', $1, nsarray))[1]::text::int
)::text::xml
));
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS
exc_msg := MESSAGE_TEXT,
exc_detail := PG_EXCEPTION_DETAIL,
exc_hint := PG_EXCEPTION_HINT,
exc_sqlstate := RETURNED_SQLSTATE;
RAISE WARNING USING
MESSAGE = exc_msg,
DETAIL = exc_detail,
HINT = exc_hint;
RETURN _soap_exception(faultcode => exc_sqlstate, faultstring => concat(exc_msg, ', DETAIL: ', exc_detail, ', HINT: ', exc_hint));
END
$function$;
Let's test the ``fraction_to_decimal`` service with illegal values:
.. code-block:: bash
curl http://localhost:3000/rpc/fraction_to_decimal \
--header 'Content-Type: text/xml' \
--header 'Accept: text/xml' \
--data-binary @- <<XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<fraction>
<numerator>42</numerator>
<denominator>0</denominator>
</fraction>
</soapenv:Body>
</soapenv:Envelope>
XML
The output should roughly look like:
.. code-block:: xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<soapenv:Fault>
<faultcode>22012</faultcode>
<faultstring>division by zero, DETAIL: , HINT: </faultstring>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
References
----------
For more information concerning PostgREST, cf.
- :ref:`s_proc_single_unnamed`
- :ref:`scalar_return_formats`
- :ref:`Nginx reverse proxy <admin>`
For SOAP reference, visit
- the specification at https://www.w3.org/TR/soap/
- shorter more practical advice is available at https://www.w3schools.com/xml/xml_soap.asp
+96
View File
@@ -0,0 +1,96 @@
.. _providing_img:
Providing images for ``<img>``
==============================
:author: `pkel <https://github.com/pkel>`_
In this how-to, you will learn how to create an endpoint for providing images to HTML :code:`<img>` tags without client side JavaScript. In fact, the presented technique is suitable for providing not only images, but arbitrary files.
We will start with a minimal example that highlights the general concept.
Afterwards we present a more detailed solution that fixes a few shortcomings of the first approach.
.. warning::
Be careful when saving binaries in the database, having a separate storage service for these is preferable in most cases. See `Storing Binary files in the Database <https://wiki.postgresql.org/wiki/BinaryFilesInDB>`_.
Minimal Example
---------------
First, we need a public table for storing the files.
.. code-block:: postgres
create table files(
id int primary key
, blob bytea
);
Let's assume this table contains an image of two cute kittens with id 42.
We can retrieve this image in binary format from our PostgREST API by requesting :code:`/files?select=blob&id=eq.42` with the :code:`Accept: application/octet-stream` header.
Unfortunately, putting the URL into the :code:`src` of an :code:`<img>` tag will not work.
That's because browsers do not send the required :code:`Accept: application/octet-stream` header.
Luckily we can specify the accepted media types in the :ref:`raw-media-types` configuration variable.
In this case, the :code:`Accept: image/webp` header is sent by many web browsers by default, so let's add it to the configuration variable, like this: :code:`raw-media-types="image/webp"`.
Now, the image will be displayed in the HTML page:
.. code-block:: html
<img src="http://localhost:3000/files?select=blob&id=eq.42" alt="Cute Kittens"/>
Improved Version
----------------
The basic solution has some shortcomings:
1. The response :code:`Content-Type` header is set to :code:`image/webp`.
This might be a problem if you want to specify a different format for the file.
2. Download requests (e.g. Right Click -> Save Image As) to :code:`/files?select=blob&id=eq.42` will propose :code:`files` as filename.
This might confuse users.
3. Requests to the binary endpoint are not cached.
This will cause unnecessary load on the database.
The following improved version addresses these problems.
First, in addition to the minimal example, we need to store the media types and names of our files in the database.
.. code-block:: postgres
alter table files
add column type text,
add column name text;
Next, we set up an RPC endpoint that sets the content type and filename.
We use this opportunity to configure some basic, client-side caching.
For production, you probably want to configure additional caches, e.g. on the :ref:`reverse proxy <admin>`.
.. code-block:: postgres
create function file(id int) returns bytea as
$$
declare headers text;
declare blob bytea;
begin
select format(
'[{"Content-Type": "%s"},'
'{"Content-Disposition": "inline; filename=\"%s\""},'
'{"Cache-Control": "max-age=259200"}]'
, files.type, files.name)
from files where files.id = file.id into headers;
perform set_config('response.headers', headers, true);
select files.blob from files where files.id = file.id into blob;
if found
then return(blob);
else raise sqlstate 'PT404' using
message = 'NOT FOUND',
detail = 'File not found',
hint = format('%s seems to be an invalid file id', file.id);
end if;
end
$$ language plpgsql;
With this, we can obtain the cat image from :code:`/rpc/file?id=42`. Thus, the resulting HTML will be:
.. code-block:: html
<img src="http://localhost:3000/rpc/file?id=42" alt="Cute Kittens"/>
@@ -0,0 +1,341 @@
.. _sql-user-management-using-postgres-users-and-passwords:
SQL User Management using postgres' users and passwords
=======================================================
:author: `fjf2002 <https://github.com/fjf2002>`_
This is an alternative to chapter :ref:`sql_user_management`, solely using the PostgreSQL built-in table `pg_catalog.pg_authid <https://www.postgresql.org/docs/current/catalog-pg-authid.html>`_ for user management. This means
- no dedicated user table (aside from :code:`pg_authid`) is required
- PostgreSQL's users and passwords (i. e. the stuff in :code:`pg_authid`) are also used at the PostgREST level.
.. note::
Only PostgreSQL users with SCRAM-SHA-256 password hashes (the default since PostgreSQL v14) are supported.
.. warning::
This is experimental. We can't give you any guarantees, especially concerning security. Use at your own risk.
Working with pg_authid and SCRAM-SHA-256 hashes
-----------------------------------------------
As in :ref:`sql_user_management`, we create a :code:`basic_auth` schema:
.. code-block:: postgres
-- We put things inside the basic_auth schema to hide
-- them from public view. Certain public procs/views will
-- refer to helpers and tables inside.
CREATE SCHEMA IF NOT EXISTS basic_auth;
As in :ref:`sql_user_management`, we create the :code:`pgcrypto` and :code:`pgjwt` extensions. Here we prefer to put the extensions in its own schemas:
.. code-block:: postgres
CREATE SCHEMA ext_pgcrypto;
ALTER SCHEMA ext_pgcrypto OWNER TO postgres;
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA ext_pgcrypto;
Concerning the `pgjwt extension <https://github.com/michelp/pgjwt>`_, please cf. to :ref:`client_auth`.
.. code-block:: postgres
CREATE SCHEMA ext_pgjwt;
ALTER SCHEMA ext_pgjwt OWNER TO postgres;
CREATE EXTENSION IF NOT EXISTS pgjwt WITH SCHEMA ext_pgjwt;
In order to be able to work with postgres' SCRAM-SHA-256 password hashes, we also need the PBKDF2 key derivation function. Luckily there is `a PL/pgSQL implementation on stackoverflow <https://stackoverflow.com/q/47162200/2337147>`_:
.. code-block:: plpgsql
CREATE FUNCTION basic_auth.pbkdf2(salt bytea, pw text, count integer, desired_length integer, algorithm text) RETURNS bytea
LANGUAGE plpgsql IMMUTABLE
AS $$
DECLARE
hash_length integer;
block_count integer;
output bytea;
the_last bytea;
xorsum bytea;
i_as_int32 bytea;
i integer;
j integer;
k integer;
BEGIN
algorithm := lower(algorithm);
CASE algorithm
WHEN 'md5' then
hash_length := 16;
WHEN 'sha1' then
hash_length = 20;
WHEN 'sha256' then
hash_length = 32;
WHEN 'sha512' then
hash_length = 64;
ELSE
RAISE EXCEPTION 'Unknown algorithm "%"', algorithm;
END CASE;
--
block_count := ceil(desired_length::real / hash_length::real);
--
FOR i in 1 .. block_count LOOP
i_as_int32 := E'\\000\\000\\000'::bytea || chr(i)::bytea;
i_as_int32 := substring(i_as_int32, length(i_as_int32) - 3);
--
the_last := salt::bytea || i_as_int32;
--
xorsum := ext_pgcrypto.HMAC(the_last, pw::bytea, algorithm);
the_last := xorsum;
--
FOR j IN 2 .. count LOOP
the_last := ext_pgcrypto.HMAC(the_last, pw::bytea, algorithm);
-- xor the two
FOR k IN 1 .. length(xorsum) LOOP
xorsum := set_byte(xorsum, k - 1, get_byte(xorsum, k - 1) # get_byte(the_last, k - 1));
END LOOP;
END LOOP;
--
IF output IS NULL THEN
output := xorsum;
ELSE
output := output || xorsum;
END IF;
END LOOP;
--
RETURN substring(output FROM 1 FOR desired_length);
END $$;
ALTER FUNCTION basic_auth.pbkdf2(salt bytea, pw text, count integer, desired_length integer, algorithm text) OWNER TO postgres;
Analogous to :ref:`sql_user_management` creates the function :code:`basic_auth.user_role`, we create a helper function to check the user's password, here with another name and signature (since we want the username, not an email address).
But contrary to :ref:`sql_user_management`, this function does not use a dedicated :code:`users` table with passwords, but instead utilizes the built-in table `pg_catalog.pg_authid <https://www.postgresql.org/docs/current/catalog-pg-authid.html>`_:
.. code-block:: plpgsql
CREATE FUNCTION basic_auth.check_user_pass(username text, password text) RETURNS name
LANGUAGE sql
AS
$$
SELECT rolname AS username
FROM pg_authid
-- regexp-split scram hash:
CROSS JOIN LATERAL regexp_match(rolpassword, '^SCRAM-SHA-256\$(.*):(.*)\$(.*):(.*)$') AS rm
-- identify regexp groups with sane names:
CROSS JOIN LATERAL (SELECT rm[1]::integer AS iteration_count, decode(rm[2], 'base64') as salt, decode(rm[3], 'base64') AS stored_key, decode(rm[4], 'base64') AS server_key, 32 AS digest_length) AS stored_password_part
-- calculate pbkdf2-digest:
CROSS JOIN LATERAL (SELECT basic_auth.pbkdf2(salt, check_user_pass.password, iteration_count, digest_length, 'sha256')) AS digest_key(digest_key)
-- based on that, calculate hashed passwort part:
CROSS JOIN LATERAL (SELECT ext_pgcrypto.digest(ext_pgcrypto.hmac('Client Key', digest_key, 'sha256'), 'sha256') AS stored_key, ext_pgcrypto.hmac('Server Key', digest_key, 'sha256') AS server_key) AS check_password_part
WHERE rolpassword IS NOT NULL
AND pg_authid.rolname = check_user_pass.username
-- verify password:
AND check_password_part.stored_key = stored_password_part.stored_key
AND check_password_part.server_key = stored_password_part.server_key;
$$;
ALTER FUNCTION basic_auth.check_user_pass(username text, password text) OWNER TO postgres;
Public User Interface
---------------------
Analogous to :ref:`sql_user_management`, we create a login function which takes a username and password and returns a JWT if the credentials match a user in the internal table.
Here we use the username instead of the email address to identify a user.
Logins
~~~~~~
As described in :ref:`client_auth`, we'll create a JWT token inside our login function. Note that you'll need to adjust the secret key which is hard-coded in this example to a secure (at least thirty-two character) secret of your choosing.
.. code-block:: plpgsql
CREATE TYPE basic_auth.jwt_token AS (
token text
);
-- if you are not using psql, you need to replace :DBNAME with the current database's name.
ALTER DATABASE :DBNAME SET "app.jwt_secret" to 'reallyreallyreallyreallyverysafe';
CREATE FUNCTION public.login(username text, password text) RETURNS basic_auth.jwt_token
LANGUAGE plpgsql security definer
AS $$
DECLARE
_role name;
result basic_auth.jwt_token;
BEGIN
-- check email and password
SELECT basic_auth.check_user_pass(username, password) INTO _role;
IF _role IS NULL THEN
RAISE invalid_password USING message = 'invalid user or password';
END IF;
--
SELECT ext_pgjwt.sign(
row_to_json(r), current_setting('app.jwt_secret')
) AS token
FROM (
SELECT login.username as role,
extract(epoch FROM now())::integer + 60*60 AS exp
) r
INTO result;
RETURN result;
END;
$$;
ALTER FUNCTION public.login(username text, password text) OWNER TO postgres;
Permissions
~~~~~~~~~~~
Analogous to :ref:`sql_user_management`:
Your database roles need access to the schema, tables, views and functions in order to service HTTP requests.
Recall from the :ref:`roles` that PostgREST uses special roles to process requests, namely the authenticator and
anonymous roles. Below is an example of permissions that allow anonymous users to attempt to log in.
.. code-block:: postgres
-- the names "anon" and "authenticator" are configurable and not
-- sacred, we simply choose them for clarity
CREATE ROLE anon NOINHERIT;
CREATE role authenticator NOINHERIT LOGIN PASSWORD 'secret';
GRANT anon TO authenticator;
GRANT EXECUTE ON FUNCTION public.login(username text, password text) TO anon;
Since the above :code:`login` function is defined as `security definer <https://www.postgresql.org/docs/current/sql-createfunction.html#id-1.9.3.67.10.2>`_,
the anonymous user :code:`anon` doesn't need permission to access the table :code:`pg_catalog.pg_authid` .
:code:`grant execute on function` is included for clarity but it might not be needed, see :ref:`func_privs` for more details.
Choose a secure password for role :code:`authenticator`.
Do not forget to configure PostgREST to use the :code:`authenticator` user to connect, and to use the :code:`anon` user as anonymous user.
Testing
-------
Let us create a sample user:
.. code-block:: postgres
CREATE ROLE foo PASSWORD 'bar';
Test at the SQL level
~~~~~~~~~~~~~~~~~~~~~
Execute:
.. code-block:: postgres
SELECT * FROM public.login('foo', 'bar');
This should return a single scalar field like:
::
token
-----------------------------------------------------------------------------------------------------------------------------
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTg4ODQ3fQ.idBBHuDiQuN_S7JJ2v3pBOr9QypCliYQtCgwYOzAqEk
(1 row)
Test at the REST level
~~~~~~~~~~~~~~~~~~~~~~
An API request to call this function would look like:
.. tabs::
.. code-tab:: http
POST /rpc/login HTTP/1.1
{ "username": "foo", "password": "bar" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "username": "foo", "password": "bar" }'
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`reallyreallyreallyreallyverysafe` as specified in the SQL code above. You'll want to change this secret in your app!)
.. code:: json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VwcCIsImV4cCI6MTY2ODE4ODQzN30.WSytcouNMQe44ZzOQit2AQsqTKFD5mIvT3z2uHwdoYY"
}
A more sophisticated test at the REST level
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let's add a table, intended for the :code:`foo` user:
.. code-block:: postgres
CREATE TABLE public.foobar(foo int, bar text, baz float);
ALTER TABLE public.foobar owner TO postgres;
Now try to get the table's contents with:
.. tabs::
.. code-tab:: http
GET /foobar HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/foobar"
This should fail --- of course, we haven't specified the user, thus PostgREST falls back to the :code:`anon` user and denies access.
Add an :code:`Authorization` header. Please use the token value from the login function call above instead of the one provided below.
.. tabs::
.. code-tab:: http
GET /foobar HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY
.. code-tab:: bash Curl
curl "http://localhost:3000/foobar" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY"
This will fail again --- we get :code:`Permission denied to set role`. We forgot to allow the authenticator role to switch into this user by executing:
.. code-block:: postgres
GRANT foo TO authenticator;
Re-execute the last REST request. We fail again --- we also forgot to grant permissions for :code:`foo` on the table. Execute:
.. code-block:: postgres
GRANT SELECT ON TABLE public.foobar TO foo;
Now the REST request should succeed. An empty JSON array :code:`[]` is returned.
@@ -0,0 +1,763 @@
.. _working_with_types:
Working with PostgreSQL data types
==================================
:author: `Laurence Isla <https://github.com/laurenceisla>`_
PostgREST makes use of PostgreSQL string representations to work with data types. Thanks to this, you can use special values, such as ``now`` for timestamps, ``yes`` for booleans or time values including the time zones. This page describes how you can take advantage of these string representations to perform operations on different PostgreSQL data types.
.. contents::
:local:
:depth: 1
Timestamps
----------
You can use the **time zone** to filter or send data if needed.
.. code-block:: postgres
create table reports (
id int primary key
, due_date timestamptz
);
Suppose you are located in Sydney and want create a report with the date in the local time zone. Your request should look like this:
.. tabs::
.. code-tab:: http
POST /reports HTTP/1.1
Content-Type: application/json
[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },
{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]
.. code-tab:: bash Curl
curl "http://localhost:3000/reports" \
-X POST -H "Content-Type: application/json" \
-d '[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]'
Someone located in Cairo can retrieve the data using their local time, too:
.. tabs::
.. code-tab:: http
GET /reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo"
.. code-block:: json
[
{
"id": 1,
"due_date": "2022-02-23T19:10:15-05:00"
}
]
The response has the date in the time zone configured by the server: ``UTC -05:00``.
You can use other comparative filters and also all the `PostgreSQL special date/time input values <https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-SPECIAL-TABLE>`_ as illustrated in this example:
.. tabs::
.. code-tab:: http
GET /reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch)) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch))"
.. code-block:: json
[
{
"id": 2,
"due_date": "2022-02-27T06:00:00-05:00"
}
]
JSON
----
To work with a ``json`` type column, you can handle the value as a JSON object.
.. code-block:: postgres
create table products (
id int primary key,
name text unique,
extra_info json
);
You can insert a new product using a JSON object for the ``extra_info`` column:
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{
"id": 1,
"name": "Canned fish",
"extra_info": {
"expiry_date": "2025-12-31",
"exportable": true
}
}
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "Canned fish",
"extra_info": {
"expiry_date": "2025-12-31",
"exportable": true
}
}
EOF
To query and filter the data see :ref:`json_columns` for a complete reference.
Arrays
------
To handle `array types <https://www.postgresql.org/docs/current/arrays.html>`_ you can use string representation or JSON array format.
.. code-block:: postgres
create table movies (
id int primary key,
title text not null,
tags text[],
performance_times time[]
);
You can insert a new value using string representation.
.. tabs::
.. code-tab:: http
POST /movies HTTP/1.1
Content-Type: application/json
{
"id": 1,
"title": "Paddington",
"tags": "{family,comedy,not streamable}",
"performance_times": "{12:40,15:00,20:00}"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": "{family,comedy,not streamable}",
"performance_times": "{12:40,15:00,20:00}"
}
EOF
Or you could send the same data using JSON array format:
.. tabs::
.. code-tab:: http
POST /movies HTTP/1.1
Content-Type: application/json
{
"id": 1,
"title": "Paddington",
"tags": ["family", "comedy", "not streamable"],
"performance_times": ["12:40", "15:00", "20:00"]
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": ["family", "comedy", "not streamable"],
"performance_times": ["12:40", "15:00", "20:00"]
}
EOF
To query the data you can use arrow operators. See :ref:`composite_array_columns`.
Multidimensional Arrays
~~~~~~~~~~~~~~~~~~~~~~~
Similarly to one-dimensional arrays, both the string representation and JSON array format are allowed.
.. code-block:: postgres
-- This new column stores the cinema, floor and auditorium numbers in that order
alter table movies
add column cinema_floor_auditorium int[][][];
You can now update the item using JSON array format:
.. tabs::
.. code-tab:: http
PATCH /movies?id=eq.1 HTTP/1.1
Content-Type: application/json
{
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies?id=eq.1" \
-X PATCH -H "Content-Type: application/json" \
-d @- << EOF
{
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
}
EOF
Then, for example, to query the auditoriums that are located in the first cinema (position 0 in the array) and on the second floor (position 1 in the next inner array), we can use the arrow operators this way:
.. tabs::
.. code-tab:: http
GET /movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1"
.. code-block:: json
[
{
"title": "Paddington",
"auditorium": [6,7]
}
]
Composite Types
---------------
With PostgREST, you have two options to handle `composite type columns <https://www.postgresql.org/docs/current/rowtypes.html>`_.
.. code-block:: postgres
create type dimension as (
length decimal(6,2),
width decimal (6,2),
height decimal (6,2),
unit text
);
create table products (
id int primary key,
size dimension
);
insert into products (id, size)
values (1, '(5.0,5.0,10.0,"cm")');
On one hand you can insert values using string representation.
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
EOF
Or you could insert the same data in JSON format.
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
}
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
}
EOF
You can also query the data using arrow operators. See :ref:`composite_array_columns`.
Ranges
------
PostgREST allows you to handle `ranges <https://www.postgresql.org/docs/current/rangetypes.html>`_.
.. code-block:: postgres
create table events (
id int primary key,
name text unique,
duration tsrange
);
To insert a new event, specify the ``duration`` value as a string representation of the ``tsrange`` type:
.. tabs::
.. code-tab:: http
POST /events HTTP/1.1
Content-Type: application/json
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/events" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
EOF
You can use range :ref:`operators <operators>` to filter the data. But, in this case, requesting a filter like ``events?duration=cs.2023-01-01`` will return an error, because PostgreSQL needs an explicit cast from string to timestamp. A workaround is to use a range starting and ending in the same date:
.. tabs::
.. code-tab:: http
GET /events?duration=cs.[2023-01-01,2023-01-01] HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/events?duration=cs.\[2023-01-01,2023-01-01\]"
.. code-block:: json
[
{
"id": 1,
"name": "New Year's Party",
"duration": "[\"2022-12-31 11:00:00\",\"2023-01-01 06:00:00\"]"
}
]
.. _casting_range_to_json:
Casting a Range to a JSON Object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As you may have noticed, the ``tsrange`` value is returned as a string literal. To return it as a JSON value, first you need to create a function that will do the conversion from a ``tsrange`` type:
.. code-block:: postgres
create or replace function tsrange_to_json(tsrange) returns json as $$
select json_build_object(
'lower', lower($1)
, 'upper', upper($1)
, 'lower_inc', lower_inc($1)
, 'upper_inc', upper_inc($1)
);
$$ language sql;
Then, create the cast using this function:
.. code-block:: postgres
create cast (tsrange as json) with function tsrange_to_json(tsrange) as assignment;
Finally, do the request :ref:`casting the range column <casting_columns>`:
.. tabs::
.. code-tab:: http
GET /events?select=id,name,duration::json HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/events?select=id,name,duration::json"
.. code-block:: json
[
{
"id": 1,
"name": "New Year's Party",
"duration": {
"lower": "2022-12-31T11:00:00",
"upper": "2023-01-01T06:00:00",
"lower_inc": true,
"upper_inc": true
}
}
]
.. note::
If you don't want to modify casts for built-in types, an option would be to `create a custom type <https://www.postgresql.org/docs/current/sql-createtype.html>`_
for your own ``tsrange`` and add its own cast.
.. code-block:: postgres
create type mytsrange as range (subtype = timestamp, subtype_diff = tsrange_subdiff);
-- define column types and casting function analogously to the above example
-- ...
create cast (mytsrange as json) with function mytsrange_to_json(mytsrange) as assignment;
Bytea
-----
To send raw binary to PostgREST you need a function with a single unnamed parameter of `bytea type <https://www.postgresql.org/docs/current/datatype-binary.html>`_.
.. code-block:: postgres
create table files (
id int primary key generated always as identity,
file bytea
);
create function upload_binary(bytea) returns void as $$
insert into files (file) values ($1);
$$ language sql;
Let's download the PostgREST logo for our test.
.. code-block:: bash
curl "https://postgrest.org/en/latest/_images/logo.png" -o postgrest-logo.png
Now, to send the file ``postgrest-logo.png`` we need to set the ``Content-Type: application/octet-stream`` header in the request:
.. tabs::
.. code-tab:: http
POST /rpc/upload_binary HTTP/1.1
Content-Type: application/octet-stream
postgrest-logo.png
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@postgrest-logo.png"
To get the image from the database, set the ``Accept: application/octet-stream`` header and select only the
``bytea`` type column.
.. tabs::
.. code-tab:: http
GET /files?select=file&id=eq.1 HTTP/1.1
Accept: application/octet-stream
.. code-tab:: bash Curl
curl "http://localhost:3000/files?select=file&id=eq.1" \
-H "Accept: application/octet-stream"
Use more accurate headers according to the type of the files by using the :ref:`raw-media-types` configuration. For example, adding the ``raw-media-types="image/png"`` setting to the configuration file will allow you to use the ``Accept: image/png`` header:
.. tabs::
.. code-tab:: http
GET /files?select=file&id=eq.1 HTTP/1.1
Accept: image/png
.. code-tab:: bash Curl
curl "http://localhost:3000/files?select=file&id=eq.1" \
-H "Accept: image/png"
See :ref:`providing_img` for a step-by-step example on how to handle images in HTML.
.. warning::
Be careful when saving binaries in the database, having a separate storage service for these is preferable in most cases. See `Storing Binary files in the Database <https://wiki.postgresql.org/wiki/BinaryFilesInDB>`_.
hstore
------
You can work with data types belonging to additional supplied modules such as `hstore <https://www.postgresql.org/docs/current/hstore.html>`_.
.. code-block:: postgres
-- Activate the hstore module in the current database
create extension if not exists hstore;
create table countries (
id int primary key,
name hstore unique
);
The ``name`` column will have the name of the country in different formats. You can insert values using the string representation for that data type:
.. tabs::
.. code-tab:: http
POST /countries HTTP/1.1
Content-Type: application/json
[
{ "id": 1, "name": "common => Egypt, official => \"Arab Republic of Egypt\", native => مصر" },
{ "id": 2, "name": "common => Germany, official => \"Federal Republic of Germany\", native => Deutschland" }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/countries" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "common => Egypt, official => \"Arab Republic of Egypt\", native => مصر" },
{ "id": 2, "name": "common => Germany, official => \"Federal Republic of Germany\", native => Deutschland" }
]
EOF
Notice that the use of ``"`` in the value of the ``name`` column needs to be escaped using a backslash ``\``.
You can also query and filter the value of a ``hstore`` column using the arrow operators, as you would do for a :ref:`JSON column<json_columns>`. For example, if you want to get the native name of Egypt:
.. tabs::
.. code-tab:: http
GET /countries?select=name->>native&name->>common=like.Egypt HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/countries?select=name->>native&name->>common=like.Egypt"
.. code-block:: json
[{ "native": "مصر" }]
.. _ww_postgis:
PostGIS
-------
You can use the string representation for `PostGIS <https://postgis.net/>`_ data types such as ``geometry`` or ``geography`` (you need to `install PostGIS <https://postgis.net/install/>`_ first).
.. code-block:: postgres
-- Activate the postgis module in the current database
create extension if not exists postgis;
create table coverage (
id int primary key,
name text unique,
area geometry
);
To add areas in polygon format, you can use string representation:
.. tabs::
.. code-tab:: http
POST /coverage HTTP/1.1
Content-Type: application/json
[
{ "id": 1, "name": "small", "area": "SRID=4326;POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))" },
{ "id": 2, "name": "big", "area": "SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))" }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/coverage" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "small", "area": "SRID=4326;POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))" },
{ "id": 2, "name": "big", "area": "SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))" }
]
EOF
Now, when you request the information, PostgREST will automatically cast the ``area`` column into a ``Polygon`` geometry type. Although this is useful, you may need the whole output to be in `GeoJSON <https://geojson.org/>`_ format out of the box, which can be done by including the ``Accept: application/geo+json`` in the request. This will work for PostGIS versions 3.0.0 and up and will return the output as a `FeatureCollection Object <https://www.rfc-editor.org/rfc/rfc7946#section-3.3>`_:
.. tabs::
.. code-tab:: http
GET /coverage HTTP/1.1
Accept: application/geo+json
.. code-tab:: bash Curl
curl "http://localhost:3000/coverage" \
-H "Accept: application/geo+json"
.. code-block:: json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[[0,0],[1,0],[1,1],[0,1],[0,0]]
]
},
"properties": {
"id": 1,
"name": "small"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[[0,0],[10,0],[10,10],[0,10],[0,0]]
]
},
"properties": {
"id": 2,
"name": "big"
}
}
]
}
If you need to add an extra property, like the area in square units by using ``st_area(area)``, you could add a generated column to the table and it will appear in the ``properties`` key of each ``Feature``.
.. code-block:: postgres
alter table coverage
add square_units double precision generated always as ( st_area(area) ) stored;
In the case that you are using older PostGIS versions, then creating a function is your best option:
.. code-block:: postgres
create or replace function coverage_geo_collection() returns json as $$
select
json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', st_AsGeoJSON(c.area)::json,
'properties', json_build_object('id', c.id, 'name', c.name)
)
)
)
from coverage c;
$$ language sql;
Now this query will return the same results:
.. tabs::
.. code-tab:: http
GET /rpc/coverage_geo_collection HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/coverage_geo_collection"
.. code-block:: json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[[0,0],[1,0],[1,1],[0,1],[0,0]]
]
},
"properties": {
"id": 1,
"name": "small"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[[0,0],[10,0],[10,10],[0,10],[0,0]]
]
},
"properties": {
"id": 2,
"name": "big"
}
}
]
}
+298
View File
@@ -0,0 +1,298 @@
.. title:: PostgREST Documentation
PostgREST Documentation
=======================
.. container:: image-container
.. figure:: _static/logo.png
.. image:: https://img.shields.io/github/stars/postgrest/postgrest.svg?style=social
:target: https://github.com/PostgREST/postgrest
.. image:: https://img.shields.io/github/v/release/PostgREST/postgrest.svg
:target: https://github.com/PostgREST/postgrest/releases
.. image:: https://img.shields.io/docker/pulls/postgrest/postgrest.svg
:target: https://hub.docker.com/r/postgrest/postgrest/
.. image:: https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854
:target: https://www.patreon.com/postgrest
|
PostgREST is a standalone web server that turns your PostgreSQL database directly into a RESTful API. The structural constraints and permissions in the database determine the API endpoints and operations.
Sponsors
--------
.. container:: image-container
.. image:: _static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. image:: _static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: _static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: _static/gnuhost.png
:target: https://euronodes.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: _static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: _static/oblivious.jpg
:target: https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. The static/empty.png(created with `convert -size 320x95 xc:#fcfcfc empty.png`) is an ugly workaround
to create space and center the logos. It's not easy to layout with restructuredText.
.. .. image:: _static/empty.png
:target: #sponsors
:width: 13em
|
Motivation
----------
Using PostgREST is an alternative to manual CRUD programming. Custom API servers suffer problems. Writing business logic often duplicates, ignores or hobbles database structure. Object-relational mapping is a leaky abstraction leading to slow imperative code. The PostgREST philosophy establishes a single declarative source of truth: the data itself.
Declarative Programming
-----------------------
It's easier to ask PostgreSQL to join data for you and let its query planner figure out the details than to loop through rows yourself. It's easier to assign permissions to db objects than to add guards in controllers. (This is especially true for cascading permissions in data dependencies.) It's easier to set constraints than to litter code with sanity checks.
Leak-proof Abstraction
----------------------
There is no ORM involved. Creating new views happens in SQL with known performance implications. A database administrator can now create an API from scratch with no custom programming.
One Thing Well
--------------
PostgREST has a focused scope. It works well with other tools like Nginx. This forces you to cleanly separate the data-centric CRUD operations from other concerns. Use a collection of sharp tools rather than building a big ball of mud.
Getting Support
----------------
The project has a friendly and growing community. For discussions, use the Github `discussions page <https://github.com/PostgREST/postgrest/discussions>`_. You can also report or search for bugs/features on the Github `issues <https://github.com/PostgREST/postgrest/issues>`_ page.
.. toctree::
:glob:
:caption: Release Notes
:titlesonly:
:hidden:
v10.2.0 <releases/v10.2.0>
v10.0.0 <releases/v10.0.0>
v9.0.1 <releases/v9.0.1>
v9.0.0 <releases/v9.0.0>
releases/v8.0.0
releases/v7.0.1
releases/v7.0.0
releases/v6.0.2
releases/v5.2.0
Tutorials
---------
Are you new to PostgREST? This is the place to start!
.. toctree::
:glob:
:caption: Tutorials
:hidden:
tutorials/*
- :doc:`tutorials/tut0`
- :doc:`tutorials/tut1`
Also have a look at :doc:`Installation <install>` and :ref:`community_tutorials`.
Reference guides
----------------
Technical references for PostgREST's functionality.
.. toctree::
:caption: API
:hidden:
api.rst
.. toctree::
:caption: Configuration
:hidden:
configuration.rst
.. toctree::
:caption: Schema Cache
:hidden:
schema_cache.rst
.. toctree::
:caption: Errors
:hidden:
errors.rst
- :doc:`API <api>`
- :doc:`configuration`
- :doc:`Schema Cache <schema_cache>`
- :doc:`Errors <errors>`
Topic guides
------------
Explanations of some key concepts in PostgREST.
.. toctree::
:caption: Authentication
:hidden:
auth.rst
.. toctree::
:caption: Schema Structure
:hidden:
schema_structure.rst
.. toctree::
:caption: Administration
:hidden:
admin.rst
.. toctree::
:caption: Installation
:hidden:
install.rst
- :doc:`Authentication <auth>`
- :doc:`Schema Structure <schema_structure>`
- :doc:`Administration <admin>`
- :doc:`Installation <install>`
.. _how_tos:
How-to guides
-------------
These are recipes that'll help you address specific use-cases.
.. toctree::
:glob:
:caption: How-to guides
:hidden:
how-tos/working-with-postgresql-data-types
how-tos/providing-images-for-img
how-tos/create-soap-endpoint
how-tos/sql-user-management-using-postgres-users-and-passwords
- :doc:`how-tos/providing-images-for-img`
- :doc:`how-tos/working-with-postgresql-data-types`
- :doc:`how-tos/create-soap-endpoint`
- :doc:`how-tos/sql-user-management-using-postgres-users-and-passwords`
Ecosystem
---------
PostgREST has a growing ecosystem of examples, libraries, and experiments. Here is a selection.
.. toctree::
:caption: Ecosystem
:hidden:
ecosystem.rst
* :ref:`community_tutorials`
* :ref:`templates`
* :ref:`eco_example_apps`
* :ref:`devops`
* :ref:`eco_external_notification`
* :ref:`eco_extensions`
* :ref:`clientside_libraries`
Release Notes
-------------
Changes among versions.
- :doc:`releases/v9.0.0`
- :doc:`releases/v8.0.0`
In Production
-------------
Here are some companies that use PostgREST in production.
* `Catarse <https://www.catarse.me>`_
* `Datrium <https://www.datrium.com>`_
* `Drip Depot <https://www.dripdepot.com>`_
* `Image-charts <https://www.image-charts.com>`_
* `Netwo <https://www.netwo.io>`_
* `Nimbus <https://www.nimbusforwork.com>`_
- See how Nimbus uses PostgREST in `Paul Copplestone's blog post <https://paul.copplest.one/blog/nimbus-tech-2019-04.html>`_.
* `OpenBooking <https://www.openbooking.ch>`_
* `Supabase <https://supabase.com>`_
Testimonials
------------
"It's so fast to develop, it feels like cheating!"
-- François-Guillaume Ribreau
"I just have to say that, the CPU/Memory usage compared to our
Node.js/Waterline ORM based API is ridiculous. It's hard to even push
it over 60/70 MB while our current API constantly hits 1GB running on 6
instances (dynos)."
-- Louis Brauer
"I really enjoyed the fact that all of a sudden I was writing
microservices in SQL DDL (and v8 JavaScript functions). I dodged so
much boilerplate. The next thing I knew, we pulled out a full rewrite
of a Spring+MySQL legacy app in 6 months. Literally 10x faster, and
code was super concise. The old one took 3 years and a team of 4
people to develop."
-- Simone Scarduzio
"I like the fact that PostgREST does one thing, and one thing well.
While PostgREST takes care of bridging the gap between our HTTP server
and PostgreSQL database, we can focus on the development of our API in
a single language: SQL. This puts the database in the center of our
architecture, and pushed us to improve our skills in SQL programming
and database design."
-- Eric Bréchemier, Data Engineer, eGull SAS
"PostgREST is performant, stable, and transparent. It allows us to
bootstrap projects really fast, and to focus on our data and application
instead of building out the ORM layer. In our k8s cluster, we run a few
pods per schema we want exposed, and we scale up/down depending on demand.
Couldn't be happier."
-- Anupam Garg, Datrium, Inc.
Contributing
------------
Please see the `Contributing guidelines <https://github.com/PostgREST/postgrest/blob/main/.github/CONTRIBUTING.md>`_ in the main PostgREST repository.
+381
View File
@@ -0,0 +1,381 @@
.. _install:
Installation
============
The release page has `pre-compiled binaries for Mac OS X, Windows, Linux and FreeBSD <https://github.com/PostgREST/postgrest/releases/latest>`_ .
The Linux binary is a static executable that can be run on any Linux distribution.
You can also use your OS package manager.
.. tabs::
.. group-tab:: Mac OSX
You can install PostgREST from the `Homebrew official repo <https://formulae.brew.sh/formula/postgrest>`_.
.. code:: bash
brew install postgrest
.. group-tab:: FreeBSD
You can install PostgREST from the `official ports <https://www.freshports.org/www/hs-postgrest>`_.
.. code:: bash
pkg install hs-postgrest
.. group-tab:: Linux
.. tabs::
.. tab:: Arch Linux
You can install PostgREST from the `community repo <https://archlinux.org/packages/community/x86_64/postgrest>`_.
.. code:: bash
pacman -S postgrest
.. tab:: Nix
You can install PostgREST from nixpkgs.
.. code:: bash
nix-env -i haskellPackages.postgrest
.. group-tab:: Windows
You can install PostgREST using `Chocolatey <https://community.chocolatey.org/packages/postgrest>`_ or `Scoop <https://github.com/ScoopInstaller/Scoop>`_.
.. code:: bash
choco install postgrest
scoop install postgrest
Running PostgREST
=================
If you downloaded PostgREST from the release page, first extract the compressed file to obtain the executable.
.. code-block:: bash
# For UNIX platforms
tar Jxf postgrest-[version]-[platform].tar.xz
# On Windows you should unzip the file
Now you can run PostgREST with the :code:`--help` flag to see usage instructions:
.. code-block:: bash
# Running postgrest binary
./postgrest --help
# Running postgrest installed from a package manager
postgrest --help
# You should see a usage help message
The PostgREST server reads a configuration file as its only argument:
.. code:: bash
postgrest /path/to/postgrest.conf
# You can also generate a sample config file with
# postgrest -e > postgrest.conf
# You'll need to edit this file and remove the usage parts for postgrest to read it
For a complete reference of the configuration file, see :ref:`configuration`.
.. note::
If you see a dialog box like this on Windows, it may be that the :code:`pg_config` program is not in your system path.
.. image:: _static/win-err-dialog.png
It usually lives in :code:`C:\Program Files\PostgreSQL\<version>\bin`. See this `article <https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/>`_ about how to modify the system path.
To test that the system path is set correctly, run ``pg_config`` from the command line. You should see it output a list of paths.
.. _pg-dependency:
PostgreSQL dependency
---------------------
To use PostgREST you will need an underlying database. We require PostgreSQL 9.6 or greater. You can use something like `Amazon RDS <https://aws.amazon.com/rds/>`_ but installing your own locally is cheaper and more convenient for development. You can also run PostgreSQL in a :ref:`docker container<pg-in-docker>`.
Docker
======
You can get the `official PostgREST Docker image <https://hub.docker.com/r/postgrest/postgrest>`_ with:
.. code-block:: bash
docker pull postgrest/postgrest
To configure the container image, use :ref:`env_variables_config`.
There are two ways to run the PostgREST container: with an existing external database, or through docker-compose.
Containerized PostgREST with native PostgreSQL
----------------------------------------------
The first way to run PostgREST in Docker is to connect it to an existing native database on the host.
.. code-block:: bash
# Run the server
docker run --rm --net=host \
-e PGRST_DB_URI="postgres://app_user:password@localhost/postgres" \
postgrest/postgrest
The database connection string above is just an example. Adjust the role and password as necessary. You may need to edit PostgreSQL's :code:`pg_hba.conf` to grant the user local login access.
.. note::
Docker on Mac does not support the :code:`--net=host` flag. Instead you'll need to create an IP address alias to the host. Requests for the IP address from inside the container are unable to resolve and fall back to resolution by the host.
.. code-block:: bash
sudo ifconfig lo0 10.0.0.10 alias
You should then use 10.0.0.10 as the host in your database connection string. Also remember to include the IP address in the :code:`listen_address` within postgresql.conf. For instance:
.. code-block:: bash
listen_addresses = 'localhost,10.0.0.10'
You might also need to add a new IPv4 local connection within pg_hba.conf. For instance:
.. code-block:: bash
host all all 10.0.0.10/32 trust
The docker command will then look like this:
.. code-block:: bash
# Run the server
docker run --rm -p 3000:3000 \
-e PGRST_DB_URI="postgres://app_user:password@10.0.0.10/postgres" \
postgrest/postgrest
.. _pg-in-docker:
Containerized PostgREST *and* db with docker-compose
----------------------------------------------------
To avoid having to install the database at all, you can run both it and the server in containers and link them together with docker-compose. Use this configuration:
.. code-block:: yaml
# docker-compose.yml
version: '3'
services:
server:
image: postgrest/postgrest
ports:
- "3000:3000"
environment:
PGRST_DB_URI: postgres://app_user:password@db:5432/app_db
PGRST_OPENAPI_SERVER_PROXY_URI: http://127.0.0.1:3000
depends_on:
- db
db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_DB: app_db
POSTGRES_USER: app_user
POSTGRES_PASSWORD: password
# Uncomment this if you want to persist the data.
# volumes:
# - "./pgdata:/var/lib/postgresql/data"
Go into the directory where you saved this file and run :code:`docker-compose up`. You will see the logs of both the database and PostgREST, and be able to access the latter on port 3000.
If you want to have a visual overview of your API in your browser you can add swagger-ui to your :code:`docker-compose.yml`:
.. code-block:: yaml
swagger:
image: swaggerapi/swagger-ui
ports:
- "8080:8080"
expose:
- "8080"
environment:
API_URL: http://localhost:3000/
With this you can see the swagger-ui in your browser on port 8080.
.. _build_source:
Building from Source
====================
When a pre-built binary does not exist for your system you can build the project from source.
.. note::
We discourage building and using PostgREST on **Alpine Linux** because of a reported GHC memory leak on that platform.
You can build PostgREST from source with `Stack <https://github.com/commercialhaskell/stack>`_. It will install any necessary Haskell dependencies on your system.
* `Install Stack <https://docs.haskellstack.org/en/stable/#how-to-install-stack>`_ for your platform
* Install Library Dependencies
===================== =======================================
Operating System Dependencies
===================== =======================================
Ubuntu/Debian libpq-dev, libgmp-dev, zlib1g-dev
CentOS/Fedora/Red Hat postgresql-devel, zlib-devel, gmp-devel
BSD postgresql12-client
OS X libpq, gmp
===================== =======================================
* Build and install binary
.. code-block:: bash
git clone https://github.com/PostgREST/postgrest.git
cd postgrest
# adjust local-bin-path to taste
stack build --install-ghc --copy-bins --local-bin-path /usr/local/bin
.. note::
- If building fails and your system has less than 1GB of memory, try adding a swap file.
- `--install-ghc` flag is only needed for the first build and can be omitted in the subsequent builds.
* Check that the server is installed: :code:`postgrest --help`.
.. _deploy_heroku:
Deploying to Heroku
===================
1. Log into Heroku using the `Heroku CLI <https://devcenter.heroku.com/articles/heroku-cli>`_:
.. code-block:: bash
# If you have multiple Heroku accounts, use flag '--interactive' to switch between them
heroku login --interactive
2. Create a new Heroku app using the PostgREST buildpack:
.. code-block:: bash
mkdir ${YOUR_APP_NAME}
cd ${YOUR_APP_NAME}
git init .
heroku apps:create ${YOUR_APP_NAME} --buildpack https://github.com/PostgREST/postgrest-heroku.git
heroku git:remote -a ${YOUR_APP_NAME}
3. Create a new Heroku PostgreSQL add-on attached to the app and keep notes of the assigned add-on name (e.g. :code:`postgresql-curly-58902`) referred later as ${HEROKU_PG_DB_NAME}
.. code-block:: bash
heroku addons:create heroku-postgresql:standard-0 -a ${YOUR_APP_NAME}
# wait until the add-on is available
heroku pg:wait -a ${YOUR_APP_NAME}
4. Create the necessary user roles according to the
`PostgREST documentation <https://postgrest.org/en/stable/auth.html>`_:
.. code-block:: bash
heroku pg:credentials:create --name api_user -a ${YOUR_APP_NAME}
# use the following command to ensure the new credential state is active before attaching it
heroku pg:credentials -a ${YOUR_APP_NAME}
heroku addons:attach ${HEROKU_PG_DB_NAME} --credential api_user -a ${YOUR_APP_NAME}
5. Connect to the PostgreSQL database and create some sample data:
.. code-block:: bash
heroku psql -a ${YOUR_APP_NAME}
.. code-block:: postgres
# from the psql command prompt execute the following commands:
create schema api;
create table api.todos (
id serial primary key,
done boolean not null default false,
task text not null,
due timestamptz
);
insert into api.todos (task) values
('finish tutorial 0'), ('pat self on back');
grant usage on schema api to api_user;
grant select on api.todos to api_user;
6. Create the :code:`Procfile`:
.. code-block:: bash
web: PGRST_SERVER_HOST=0.0.0.0 PGRST_SERVER_PORT=${PORT} PGRST_DB_URI=${PGRST_DB_URI:-${DATABASE_URL}} ./postgrest-${POSTGREST_VER}
..
Set the following environment variables on Heroku:
.. code-block:: bash
heroku config:set POSTGREST_VER=10.0.0
heroku config:set PGRST_DB_SCHEMA=api
heroku config:set PGRST_DB_ANON_ROLE=api_user
..
PGRST_DB_URI can be set if an external database is used or if it's different from the default Heroku DATABASE_URL. This latter is used if nothing is provided.
POSTGREST_VER is mandatory to select and build the required PostgREST release.
See https://postgrest.org/en/stable/configuration.html#environment-variables for the full list of environment variables.
7. Build and deploy your app:
.. code-block:: bash
git add Procfile
git commit -m "PostgREST on Heroku"
git push heroku master
..
Your Heroku app should be live at :code:`${YOUR_APP_NAME}.herokuapp.com`
8. Test your app
From a terminal display the application logs:
.. code-block:: bash
heroku logs -t
..
From a different terminal retrieve with curl the records previously created:
.. code-block:: bash
curl https://${YOUR_APP_NAME}.herokuapp.com/todos
..
and test that any attempt to modify the table via a read-only user is not allowed:
.. code-block:: bash
curl https://${YOUR_APP_NAME}.herokuapp.com/todos -X POST \
-H "Content-Type: application/json" \
-d '{"task": "do bad thing"}'
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env python
from livereload import Server, shell
from subprocess import call
## Build docs at startup
call(["sphinx-build", "-b", "html", "-a", "-n", ".", "_build"])
server = Server()
server.watch("**/*.rst", shell("sphinx-build -b html -a -n . _build"))
# For custom port and host
# server.serve(root='_build/', host='192.168.1.2')
server.serve(root="_build/")
+209
View File
@@ -0,0 +1,209 @@
personal_ws-1.1 en 0 utf-8
Adossi
AMQP
api
API's
Archlinux
aud
Auth
auth
authenticator
backoff
balancer
Beles
booleans
Bouscal
buildpack
Bytea
Cardano
cd
centric
changelog
ClojureScript
cloudfared
config
CORS
CPUs
cryptographically
CSV
Daemonizing
DDL
DevOps
DiBiase
dockerize
DoS
eq
ETH
Ethereum
EveryLayout
Fenko
Fernandes
filename
FreeBSD
fts
GC
GeoJSON
GHC
Github
Google
grantor
GraphQL
gte
GUC
GUCs
gucs
Gumbs
Haskell
Heroku
HMAC
Homebrew
hstore
HTTP
HTTPS
HV
Ibarluzea
ilike
imatch
io
IP
JS
js
JSON
JWK
JWT
jwt
JWTs
Kinesis
Kofi
Kubernetes
localhost
login
Logins
logins
lon
lt
lte
middleware
misprediction
Mithril
multi
MVCC
namespace
namespaced
neq
nginx
ngrep
nixpkgs
npm
nxl
nxr
OAuth
onwards
OpenAPI
openapi
ORM
ov
passphrase
Pawel
PBKDF
Pelletier
Petr
PgBouncer
pgcrypto
pgjwt
pgrst
pgrstX
PGRSTX
pgSQL
authid
phfts
phraseto
plainto
plfts
poolers
POSIX
PostGIS
PostgreSQL
PostgreSQL's
PostgREST
postgres
postgrest
PostgREST's
pre
preflight
psql
Qin
RabbitMQ
Rafaj
RDS
reallyreallyreallyreallyverysafe
Rechkemmer
reconnection
Redux
refactor
Reloadable
Remo
requester's
RESTful
RestSharp
RLS
RPC
RSA
Saleeba
savepoint
schemas
Sencha
Serverless
Severin
SHA
signup
SIGUSR
sl
SNS
sqitch
SQL
sql
sr
SSL
stateful
stdout
Stolarz
subselect
SuperAgent
SvelteKit
SwaggerUI
syslog
systemd
Tcl
tmuxp
todo
todos
Tsingson
tsquery
tx
Tyll
TypeScript
UI
ui
unicode
unix
updatable
UPSERT
Upsert
upsert
uri
url
urls
variadic
Vercel
verifier
versioning
Vondra
Vue
WAI
webhooks
websearch
Websockets
webuser
wfts
ZeroMQ
+227
View File
@@ -0,0 +1,227 @@
PostgREST 10.0.0
================
Features
--------
XML/SOAP support for RPC
~~~~~~~~~~~~~~~~~~~~~~~~
RPC now understands the ``text/xml`` media type, allowing SQL functions to send XML output(``Accept: text/xml``) and receive XML input(``Content-Type: text/xml``). This makes SOAP endpoints possible, check the :ref:`create_soap_endpoint` how-to and the :ref:`scalar_return_formats` reference for more details.
GeoJSON support
~~~~~~~~~~~~~~~
GeoJSON is supported across the board(reads, writes, RPC) with the ``Accept: application/geo+json`` header, this depends on PostGIS from the versions 3.0.0 and up. The :ref:`working with PostGIS section <ww_postgis>` has an example to get you started.
Execution Plan
~~~~~~~~~~~~~~
The :ref:`execution plan <explain_plan>` of a request is now obtainable with the ``Accept: application/vnd.pgrst.plan`` header. The result can be in ``text`` or ``json`` formats and is compatible with EXPLAIN vizualizers like `explain.depesz.com <https://explain.depesz.com>`_ or `explain.dalibo.com <https://explain.dalibo.com>`_.
Resource Embedding
~~~~~~~~~~~~~~~~~~
- A :ref:`one-to-one relationship <one-to-one>` is now detected when a foreign key is unique.
- Using :ref:`computed_relationships`, you can add custom relationships or override automatically detected ones. This makes :ref:`resource_embedding` possible on Foreign Data Wrappers and complex SQL views.
Horizontal/Vertical Filtering
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :ref:`Accessing fields of a Composite type or elements of an Array type <composite_array_columns>` is now possible with the arrow operators(``->``, ``->>``) in the same way you would access a JSON type fields.
- :ref:`pattern_matching` operators for `POSIX regular expressions <https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP>`_ are now available: ``match`` and ``imatch``, equivalent in PostgreSQL to ``~`` and ``~*`` respectively.
Insertions/Updates
~~~~~~~~~~~~~~~~~~
- ``limit`` can now affect the number of updated/deleted rows. See :ref:`limited_update_delete`.
OpenAPI
~~~~~~~
You can now activate the "Authorize" button in SwaggerUI by enabling the :ref:`openapi-security-active` configuration. Add your JWT token prepending :code:`Bearer` to it and you'll be able to request protected resources.
Administration
~~~~~~~~~~~~~~
- Two :ref:`health check endpoints <health_check>` are now exposed in a secondary port.
- :ref:`pgrst_logging` now shows the database user.
- It is now possible to execute PostgREST without specifying any configuration variable. The three that were mandatory on the previous versions, are no longer so.
- If :ref:`db-uri` is not set, PostgREST will use the `libpq environment variables <https://www.postgresql.org/docs/current/libpq-envars.html>`_ for the database connection.
- If :ref:`db-schemas` is not set, it will use the database ``public`` schema.
- If :ref:`db-anon-role` is not set, it will not allow anonymous requests.
Error messages
~~~~~~~~~~~~~~
- To increase consistency, all the errors messages are now normalized. The ``hint``, ``details``, ``code`` and ``message`` fields will always be present in the body, each one defaulting to a ``null`` value. In the same way, the :ref:`errors that were raised <raise_error>` with ``SQLSTATE`` now include the ``message`` and ``code`` in the body.
- To further clarify the source of an error, we now add a ``PGRST`` prefix to the error code of all the errors that are PostgREST-specific and don't come from the database. These errors have unique codes that identify them and are documented in the :ref:`pgrst_errors` section.
Documentation improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~
* Added a :doc:`/how-tos/working-with-postgresql-data-types` how-to, which contains explanations and examples on how to work with different PostgreSQL data types such as timestamps, ranges or PostGIS types, among others.
* Added in-database and environment variable settings for each :ref:`configuration variable <config_full_list>`.
* Added the :ref:`file_descriptors` subsection.
* Added a reference page for :doc:`Error documentation </errors>`.
* Moved the :ref:`error_source` and the :ref:`status_codes` sections to the :doc:`errors reference page </errors>`.
* Moved the *Casting type to custom JSON* how-to to the :ref:`casting_range_to_json` subsection.
* Removed direct links for PostgREST versions older than 8.0 from the versions menu.
* Removed the *Embedding table from another schema* how-to.
* Restructured the :ref:`resource_embedding` section:
- Added a :ref:`one-to-many` and :ref:`many-to-one` subsections.
- Renamed the *Embedding through join tables* subsection to :ref:`many-to-many`.
* Split up the *Insertions/Updates* section into :ref:`insert` and :ref:`update`.
Breaking changes
----------------
* Many-to-many relationships now require that foreign key columns be part of the join table composite key
- This was needed to reduce :ref:`embed_disamb` errors in complex schemas(`#2070 <https://github.com/PostgREST/postgrest/issues/2070>`_).
- For migrating to this version, the less invasive method is to use :ref:`computed_relationships` to replace the previous many-to-many relationships.
- Otherwise you can change your join table primary key. For example with ``alter table permission_user drop constraint permission_user_pkey, add primary key (id, user_id, permission_id);``
* Views now are not detected when embedding using :ref:`target_disamb`.
- This embedding form was easily made ambiguous whenever a new view was added(`#2277 <https://github.com/PostgREST/postgrest/issues/2277>`_).
- For migrating to this version, you can use :ref:`computed_relationships` to replace the previous view relationships.
- :ref:`hint_disamb` works as usual on views.
* ``limit/offset`` now limits the affected rows on ``UPDATE``/``DELETE``
- Previously, ``limit``/``offset`` only limited the returned rows but not the actual updated rows(`#2156 <https://github.com/PostgREST/postgrest/issues/2156>`_)
* ``max-rows`` is no longer applied on ``POST``, ``PATCH``, ``PUT`` and ``DELETE`` returned rows
- This was misleading because the affected rows were not really affected by ``max-rows``, only the returned rows were limited(`#2155 <https://github.com/PostgREST/postgrest/issues/2155>`_)
* Return ``204 No Content`` without ``Content-Type`` for RPCs returning ``VOID``
- Previously, those RPCs would return ``null`` as a body with ``Content-Type: application/json`` (`#2001 <https://github.com/PostgREST/postgrest/issues/2001>`_).
* Using ``Prefer: return=representation`` no longer returns a ``Location`` header
- This reduces unnecessary computing for all insertions (`#2312 <https://github.com/PostgREST/postgrest/issues/2312>`_)
Bug fixes
---------
* Return ``204 No Content`` without ``Content-Type`` for ``PUT`` (`#2058 <https://github.com/PostgREST/postgrest/issues/2058>`_)
* Clarify error for failed schema cache load. (`#2107 <https://github.com/PostgREST/postgrest/issues/2107>`_)
- From ``Database connection lost. Retrying the connection`` to ``Could not query the database for the schema cache. Retrying.``
* Fix silently ignoring filter on a non-existent embedded resource (`#1771 <https://github.com/PostgREST/postgrest/issues/1771>`_)
* Remove functions, which are not callable due to unnamed arguments, from schema cache and OpenAPI output. (`#2152 <https://github.com/PostgREST/postgrest/issues/2152>`_)
* Fix accessing JSON array fields with ``->`` and ``->>`` in ``?select=`` and ``?order=``. (`#2145 <https://github.com/PostgREST/postgrest/issues/2145>`_)
* Ignore ``max-rows`` on ``POST``, ``PATCH``, ``PUT`` and ``DELETE`` (`#2155 <https://github.com/PostgREST/postgrest/issues/2155>`_)
* Fix inferring a foreign key column as a primary key column on views (`#2254 <https://github.com/PostgREST/postgrest/issues/2254>`_)
* Restrict generated many-to-many relationships (`#2070 <https://github.com/PostgREST/postgrest/issues/2070>`_)
- Only adds many-to-many relationships when a table has foreign keys to two other tables and these foreign key columns are part of the table's primary key columns.
* Allow casting to types with underscores and numbers (e.g. ``select=oid_array::_int4``) (`#2278 <https://github.com/PostgREST/postgrest/issues/2278>`_)
* Prevent views from breaking one-to-many/many-to-one embeds when using column or foreign key as target (`#2277 <https://github.com/PostgREST/postgrest/issues/2277>`_, `#2238 <https://github.com/PostgREST/postgrest/issues/2238>`_, `#1643 <https://github.com/PostgREST/postgrest/issues/1643>`_)
- When using a column or foreign key as target for embedding (``/tbl?select=*,col-or-fk(*)``), only tables are now detected and views are not.
- You can still use a column or an inferred foreign key on a view to embed a table (``/view?select=*,col-or-fk(*)``)
* Increase the ``db-pool-timeout`` to 1 hour to prevent frequent high connection latency (`#2317 <https://github.com/PostgREST/postgrest/issues/2317>`_)
* The search path now correctly identifies schemas with uppercase and special characters in their names (regression) (`#2341 <https://github.com/PostgREST/postgrest/issues/2341>`_)
* "404 Not Found" on nested routes and "405 Method Not Allowed" errors no longer start an empty database transaction (`#2364 <https://github.com/PostgREST/postgrest/issues/2364>`_)
* Fix inaccurate result count when an inner embed was selected after a normal embed in the query string (`#2342 <https://github.com/PostgREST/postgrest/issues/2342>`_)
* ``OPTIONS`` requests no longer start an empty database transaction (`#2376 <https://github.com/PostgREST/postgrest/issues/2376>`_)
* Allow using columns with dollar sign ($) without double quoting in filters and ``select`` (`#2395 <https://github.com/PostgREST/postgrest/issues/2395>`_)
* Fix loop crash error on startup in PostgreSQL 15 beta 3. ``Log: "UNION types \"char\" and text cannot be matched."`` (`#2410 <https://github.com/PostgREST/postgrest/issues/2410>`_)
* Fix race conditions managing database connection helper (`#2397 <https://github.com/PostgREST/postgrest/issues/2397>`_)
* Allow ``limit=0`` in the request query to return an empty array (`#2269 <https://github.com/PostgREST/postgrest/issues/2269>`_)
Thanks
------
Big thanks from the `PostgREST team <https://github.com/orgs/PostgREST/people>`_ to our sponsors!
.. container:: image-container
.. image:: ../_static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/gnuhost.png
:target: https://gnuhost.eu/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: ../_static/oblivious.jpg
:target: https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* `Franz Gusenbauer <https://www.igutech.at/>`_
* `Daniel Babiak <https://github.com/dbabiak>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
* Remo Rechkemmer
* Severin Ibarluzea
* Tom Saleeba
* Pawel Tyll
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+153
View File
@@ -0,0 +1,153 @@
PostgREST 10.2.0
================
This minor version adds bug fixes and some features that provide stability to v10.0.0. These release notes include the changes added in versions `10.1.0 <https://github.com/PostgREST/postgrest/releases/tag/v10.1.0>`_, `10.1.1 <https://github.com/PostgREST/postgrest/releases/tag/v10.1.1>`_ and `10.1.2 <https://github.com/PostgREST/postgrest/releases/tag/v10.1.2>`_. You can look at the detailed changelog and download the pre-compiled binaries on the `GitHub release page <https://github.com/PostgREST/postgrest/releases/tag/v10.2.0>`_.
Features
--------
Pool Connection Lifetime
~~~~~~~~~~~~~~~~~~~~~~~~
To prevent memory leaks caused by long-lived connections, PostgREST limits their lifetime in the pool through :ref:`db-pool-max-lifetime`.
Pool Connection Acquisition Timeout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There is now a time limit to wait for pool connections to be acquired. If a new request cannot get a connection in the time specified in :ref:`db-pool-acquisition-timeout` then a response with a ``504`` status is returned.
Documentation improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~
* Added HTTP status codes to the :ref:`pgrst_errors`.
* Added a how-to on :ref:`sql-user-management-using-postgres-users-and-passwords`.
* Updated the :ref:`Heroku installation page <deploy_heroku>`.
Changes
-------
* Removed ``db-pool-timeout`` option because it was removed in the ``hasql-pool`` library that PostgREST uses for SQL connections. (`#2444 <https://github.com/PostgREST/postgrest/issues/2444>`_)
Deprecated
----------
* Deprecate bulk-calls when including the ``Prefer: params=multiple-objects`` in the request. It is preferable to use a function with an :ref:`array <s_procs_array>` or JSON parameter for a better performance. (`#1385 <https://github.com/PostgREST/postgrest/issues/1385>`_)
Bug fixes
---------
* Reduce allocations communication with PostgreSQL, particularly for request bodies. (`#2261 <https://github.com/PostgREST/postgrest/issues/2261>`_, `#2349 <https://github.com/PostgREST/postgrest/issues/2349>`_, `#2467 <https://github.com/PostgREST/postgrest/issues/2467>`_)
* Fix ``SIGUSR1`` to fully flush the connection pool. (`#2401 <https://github.com/PostgREST/postgrest/issues/2401>`_, `#2444 <https://github.com/PostgREST/postgrest/issues/2444>`_)
* Fix opening an empty transaction on failed resource embedding. (`#2428 <https://github.com/PostgREST/postgrest/issues/2428>`_)
* Fix embedding the same table multiple times. (`#2455 <https://github.com/PostgREST/postgrest/issues/2455>`_)
* Fix a regression when embedding views where base tables have a different column order for foreign key columns (`#2518 <https://github.com/PostgREST/postgrest/issues/2518>`_)
* Fix a regression with the ``Location`` header when :ref:`inserting <insert>` into views with primary keys from multiple tables (`#2458 <https://github.com/PostgREST/postgrest/issues/2458>`_)
* Fix a regression in OpenAPI output with mode ``follow-privileges`` (`#2356 <https://github.com/PostgREST/postgrest/issues/2356>`_)
* Fix infinite recursion when loading schema cache with self-referencing view (`#2283 <https://github.com/PostgREST/postgrest/issues/2283>`_)
* Return status code ``200`` instead of ``404`` for ``PATCH`` requests which don't affect any rows (`#2343 <https://github.com/PostgREST/postgrest/issues/2343>`_)
* Treat the :ref:`computed relationships <computed_relationships>` that do not return ``SETOF`` as M2O/O2O relationship (`#2481 <https://github.com/PostgREST/postgrest/issues/2481>`_)
* Fix embedding a computed relationship with a normal relationship (`#2534 <https://github.com/PostgREST/postgrest/issues/2534>`_)
* Fix error message when ``[]`` is used inside ``select`` (`#2362 <https://github.com/PostgREST/postgrest/issues/2362>`_)
* Disallow ``!inner`` on computed columns (`#2475 <https://github.com/PostgREST/postgrest/issues/2475>`_)
* Ignore leading and trailing spaces in column names when parsing the query string (`#2285 <https://github.com/PostgREST/postgrest/issues/2285>`_)
* Fix ``UPSERT`` with PostgreSQL 15 (`#2545 <https://github.com/PostgREST/postgrest/issues/2545>`_)
* Fix embedding views with multiple references to the same base column (`#2459 <https://github.com/PostgREST/postgrest/issues/2459>`_)
* Fix regression when embedding views with partial references to multi column foreign keys (`#2548 <https://github.com/PostgREST/postgrest/issues/2548>`_)
* Fix regression when requesting ``limit=0`` and ``db-max-row`` is set (`#2558 <https://github.com/PostgREST/postgrest/issues/2558>`_)
* Return a clear error without hitting the database when trying to update or insert an unknown column with ``?columns`` (`#2542 <https://github.com/PostgREST/postgrest/issues/2542>`_)
* Fix bad M2M embedding on RPC (`#2565 <https://github.com/PostgREST/postgrest/issues/2565>`_)
* Replace misleading error message when no function is found with a hint containing functions/parameters names suggestions (`#2575 <https://github.com/PostgREST/postgrest/issues/2575>`_)
* Move explanation about "single parameters" from the ``message`` to the ``details`` in the error output (`#2582 <https://github.com/PostgREST/postgrest/issues/2582>`_)
* Replace misleading error message when no relationship is found with a hint containing parent/child names suggestions (`#2569 <https://github.com/PostgREST/postgrest/issues/2569>`_)
* Add the required OpenAPI items object when the parameter is an array (`#1405 <https://github.com/PostgREST/postgrest/issues/1405>`_)
* Add upsert headers for ``POST`` requests to the OpenAPI output (`#2592 <https://github.com/PostgREST/postgrest/issues/2592>`_)
* Fix foreign keys pointing to ``VIEW`` instead of ``TABLE`` in OpenAPI output (`#2623 <https://github.com/PostgREST/postgrest/issues/2623>`_)
* Consider any PostgreSQL authentication failure as fatal and exit immediately (`#2622 <https://github.com/PostgREST/postgrest/issues/2622>`_)
* Fix ``NOTIFY pgrst`` not reloading the db connections catalog cache (`#2620 <https://github.com/PostgREST/postgrest/issues/2620>`_)
* Fix ``db-pool-acquisition-timeout`` not logging to stderr when the timeout is reached (`#2667 <https://github.com/PostgREST/postgrest/issues/2667>`_)
* Fix PostgreSQL resource leak with long-lived connections through the :ref:`db-pool-max-lifetime` configuration (`#2638 <https://github.com/PostgREST/postgrest/issues/2638>`_)
* There is now a stricter parsing of the query string. Instead of silently ignoring, the parser now returns a :ref:`PostgREST error <pgrst100>` on invalid syntax. (`#2537 <https://github.com/PostgREST/postgrest/issues/2537>`_)
Thanks
------
Big thanks from the `PostgREST team <https://github.com/orgs/PostgREST/people>`_ to our sponsors!
.. container:: image-container
.. image:: ../_static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/gnuhost.png
:target: https://gnuhost.eu/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: ../_static/oblivious.jpg
:target: https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* `Franz Gusenbauer <https://www.igutech.at/>`_
* `Daniel Babiak <https://github.com/dbabiak>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
* Remo Rechkemmer
* Severin Ibarluzea
* Tom Saleeba
* Pawel Tyll
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+26
View File
@@ -0,0 +1,26 @@
v5.2.0
======
* Explicit qualification introduced in ``v5.0`` is no longer necessary, this section will not be included from this version onwards. A :ref:`db-extra-search-path` configuration parameter was introduced to avoid the need to explictly qualify database objects. If you install PostgreSQL extensions on the ``public`` schema, they'll work normally from now on.
* Now you can filter :ref:`tabs-cols-w-spaces`.
* Included the ability to quote columns that have :ref:`reserved-chars`.
* Thanks to `Zhou Feng <https://github.com/zhoufeng1989>`_, now is possible to reference an external file in :ref:`db-uri`.
* Thanks to `Russell Davies <https://github.com/russelldavies>`_, Json Web Key Sets are now accepted by :ref:`jwt-secret`.
Thanks
------
This release was made possible thanks to:
* `Daniel Babiak <https://github.com/dbabiak>`_
* `Michel Pelletier <https://github.com/michelp>`_
* Tsingson Qin
* Jay Hannah
* Victor Adossi
* Petr Beles
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+79
View File
@@ -0,0 +1,79 @@
.. |br| raw:: html
<br />
v6.0.2
======
Full changelog is available at `PostgREST releases page <https://github.com/PostgREST/postgrest/releases>`_.
Added
-----
* Ignoring payload keys for insert/update can be now done with the ``?columns`` query parameter. See :ref:`specify_columns`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* `websearch_to_tsquery <https://www.postgresql.org/docs/current/functions-textsearch.html#id-1.5.8.19.7.2.2.7.1.1.1>`_ can now be used
through the ``wfts`` operator. See :ref:`fts`.
|br| -- `@herulume <https://github.com/herulume>`_
* Resource Embedding on materialized views is now possible. See :ref:`embedding_views`.
|br| -- `@vitorbaptista <https://github.com/vitorbaptista>`_
* Bulk calling an RPC is now allowed. See :ref:`bulk_call`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* It's now possible to request a ``text/plain`` output. See :ref:`scalar_return_formats`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Config option for specifying PostgREST database pool timeout ``db-pool-timeout``.
|br| -- `@Qu4tro <https://github.com/Qu4tro>`_
* Config option for binding the PostgREST web server to an unix socket. See :ref:`server-unix-socket`.
|br| -- `@Dansvidania <https://github.com/Dansvidania>`_
* Config option for extending the supported media types. See :ref:`raw-media-types`.
|br| -- `@Dansvidania <https://github.com/Dansvidania>`_
* We now offer an statically linked binary for Linux. Look for **postgrest-<version>-linux-x64-static.tar.xz** on the
`releases page <https://github.com/PostgREST/postgrest/releases>`_.
|br| -- `@clojurians-org <https://github.com/clojurians-org>`_
* A :ref:`how_tos` section was added to the documentation.
Changed
-------
* ``SIGHUP`` support was removed. You should use ``SIGUSR1`` instead. See :ref:`schema_reloading`.
* server-host default of ``127.0.0.1`` was changed to ``!4``. See :ref:`server-host`.
Thanks
------
This release is sponsored by:
.. image:: ../_static/cybertec.png
:target: https://www.cybertec-postgresql.com/en/
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* `Daniel Babiak <https://github.com/dbabiak>`_
* Evans Fernandes
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Kofi Gumbs
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+106
View File
@@ -0,0 +1,106 @@
.. |br| raw:: html
<br />
v7.0.0
======
You can download this release at the `PostgREST v7.0.0 release page <https://github.com/PostgREST/postgrest/releases/tag/v7.0.0>`_.
Added
-----
* Support for :ref:`Switching to a schema <multiple-schemas>` defined in :ref:`db-schemas`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_, `@mahmoudkassem <https://github.com/mahmoudkassem>`_
* Support for :ref:`planned_count` and :ref:`estimated_count`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_, `@LorenzHenk <https://github.com/LorenzHenk>`_
* Support for the :ref:`on_conflict <on_conflict>` query parameter to UPSERT based on a unique constraint.
|br| -- `@ykst <https://github.com/ykst>`_
* Support for :ref:`Resource Embedding Disambiguation <embed_disamb>`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Support for user defined socket permission via :ref:`server-unix-socket-mode` config option
|br| -- `@Dansvidania <https://github.com/Dansvidania>`_
* HTTP logic improvements -- `@steve-chavez <https://github.com/steve-chavez>`_
+ Support for HTTP HEAD requests.
+ GUCs for :ref:`guc_req_path_method`.
+ Support for :ref:`pre_req_headers`.
+ Allow overriding provided headers(Content-Type, Location, etc) by :ref:`guc_resp_hdrs`
+ Access to the ``Authorization`` header value through ``request.header.authorization``
* Documentation improvements
+ Explanation for :doc:`Schema Structure <../schema_structure>`.
+ Reference for :ref:`s_proc_embed`.
+ Reference for :ref:`mutation_embed`.
+ Reference for filters on :ref:`json_columns`.
+ How-to for :ref:`providing_img`.
+ Added :ref:`community_tutorials` section.
Fixed
-----
* Allow embedding a view when its source table foreign key is UNIQUE
|br| -- `@bwbroersma <https://github.com/bwbroersma>`_
* ``Accept: application/vnd.pgrst.object+json`` behavior is now enforced for POST/PATCH/DELETE regardless of ``Prefer: return=minimal``
|br| -- `@dwagin <https://github.com/dwagin>`_
* Fix self join resource embedding on PATCH
|br| -- `@herulume <https://github.com/herulume>`_, `@steve-chavez <https://github.com/steve-chavez>`_
* Allow PATCH/DELETE without ``Prefer: return=minimal`` on tables with no SELECT privileges
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Fix many to many resource embedding for RPC/PATCH
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
Changed
-------
* :ref:`bulk_call` should now be done by specifying a ``Prefer: params=multiple-objects`` header. This fixes a performance regression when calling stored procedures.
* Resource Embedding now outputs an error when multiple relationships between two tables are found, see :ref:`embed_disamb`.
* ``server-proxy-uri`` config option has been renamed to :ref:`openapi-server-proxy-uri`.
* Default Unix Socket file mode from 755 to 660
Thanks
------
This release was made possible thanks to:
.. image:: ../_static/cybertec.png
:target: https://www.cybertec-postgresql.com/en/
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* `Daniel Babiak <https://github.com/dbabiak>`_
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Kofi Gumbs
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+69
View File
@@ -0,0 +1,69 @@
.. |br| raw:: html
<br />
v7.0.1
======
You can see the full changelog at `PostgREST v7.0.1 release page <https://github.com/PostgREST/postgrest/releases/tag/v7.0.1>`_.
Fixed
-----
* Fix overloaded computed columns on RPC
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix POST, PATCH, DELETE with ``?select=`` and ``Prefer: return=minimal`` and PATCH with empty body
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix missing ``openapi-server-proxy-uri`` config option
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Fix ``Content-Profile`` not working for POST RPC
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Fix PUT restriction for including all columns in payload
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Documentation improvements
+ Added package managers to :ref:`install`.
Changed
-------
* From this version onwards, the release page will include a single Linux static executable that can be run on any Linux distribution.
Thanks
------
This release was made possible thanks to:
.. image:: ../_static/cybertec.png
:target: https://www.cybertec-postgresql.com/en/
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* `Daniel Babiak <https://github.com/dbabiak>`_
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Kofi Gumbs
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
If you'd like to join them, consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+191
View File
@@ -0,0 +1,191 @@
.. |br| raw:: html
<br />
v8.0.0
======
You can download this release at the `PostgREST v8.0.0 release page <https://github.com/PostgREST/postgrest/releases/tag/v8.0.0>`_.
Added
-----
* Allow HTTP status override through the :ref:`response.status <guc_resp_status>` GUC.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Allow :ref:`s_procs_variadic`.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Allow :ref:`embedding_view_chains` recursively to any depth.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* No downtime when reloading the schema cache. See :ref:`schema_reloading`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Allow schema cache reloading using PostgreSQL :ref:`NOTIFY <schema_reloading_notify>` command. This enables :ref:`auto_schema_reloading`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Allow sending the header ``Prefer: headers-only`` to get a response with a ``Location`` header. See :ref:`insert`.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
* Allow :ref:`external_connection_poolers` such as PgBouncer in transaction pooling mode.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
* Allow :ref:`config_reloading` by sending a SIGUSR2 signal.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Allow ``Bearer`` with and without capitalization as authentication schema. See :ref:`client_auth`.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* :ref:`in_db_config` that can be :ref:`reloaded with NOTIFY <config_reloading_notify>`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Allow OPTIONS to generate HTTP methods based on views triggers. See :ref:`OPTIONS requests <options_requests>`.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
* Show timestamps for server diagnostic information. See :ref:`pgrst_logging`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Config options for showing a full OpenAPI output regardless of the JWT role privileges and for disabling it altogether. See :ref:`openapi-mode`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Config option for logging level. See :ref:`log-level`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Config option for enabling or disabling prepared statements. See :ref:`db-prepared-statements`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Config option for specifying how to terminate the transactions (allowing rollbacks, useful for testing). See :ref:`db-tx-end`.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Documentation improvements
+ Added the :doc:`../schema_cache` page.
+ Moved the :ref:`schema_reloading` reference from :doc:`../admin` to :doc:`../schema_cache`
Changed
-------
* Docker images are now optimized to be built from the scratch image. This reduces the compressed image size from over 30 MB to about 4 MB.
For more details, see `Docker image built with Nix <https://github.com/PostgREST/postgrest/tree/main/nix/tools/docker#user-content-docker-image-built-with-nix>`_.
|br| -- `@monacoremo <https://github.com/monacoremo>`_
* The Docker image no longer has an internal ``/etc/postgrest.conf`` file, you must use :ref:`env_variables_config` to configure it.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* The ``pg_listen`` `utility <https://github.com/begriffs/pg_listen>`_ is no longer needed to automatically reload the schema cache
and it's replaced entirely by database notifications. See :ref:`auto_schema_reloading`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* POST requests for insertions no longer include a ``Location`` header in the response by default and behave the same way as having a
``Prefer: return=minimal`` header in the request. This prevents permissions errors when having a write-only table. See :ref:`insert`.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
* Modified the default logging level from ``info`` to ``error``. See :ref:`log-level`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Changed the error message for a not found RPC on a stale schema (see :ref:`stale_function_signature`) and for the unsupported case of
overloaded functions with the same argument names but different types.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
* Changed the error message for the no relationship found error. See :ref:`stale_fk_relationships`.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
Fixed
-----
* Fix showing UNKNOWN on ``postgrest --help`` invocation.
|br| -- `@monacoremo <https://github.com/monacoremo>`_
* Removed single column restriction to allow composite foreign keys in join tables.
|br| -- `@goteguru <https://github.com/goteguru>`_
* Fix expired JWTs starting an empty transaction on the db.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Fix location header for POST request with ``select=`` without PK.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix error messages on connection failure for localized PostgreSQL on Windows.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix ``application/octet-stream`` appending ``charset=utf-8``.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Fix overloading of functions with unnamed arguments.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Return ``405 Method not Allowed`` for GET of volatile RPC instead of 500.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix RPC return type handling and embedding for domains with composite base type.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix embedding through views that have COALESCE with subselect.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix parsing of boolean config values for Docker environment variables, now it accepts double quoted truth values ``("true", "false")`` and numbers ``("1", "0")``.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix using ``app.settings.xxx`` config options in Docker, now they can be used as ``PGRST_APP_SETTINGS_xxx``.
|br| -- `@wolfgangwalther <https://github.com/wolfgangwalther>`_
* Fix panic when attempting to run with unix socket on non-unix host and properly close unix domain socket on exit.
|br| -- `@monacoremo <https://github.com/monacoremo>`_
* Disregard internal junction (in non-exposed schema) when embedding.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Fix requests for overloaded functions from HTML forms to no longer hang.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
Thanks
------
Big thanks from the `PostgREST team <https://github.com/orgs/PostgREST/people>`_ to our sponsors!
.. container:: image-container
.. image:: ../_static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/gnuhost.png
:target: https://gnuhost.eu/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: ../_static/oblivious.jpg
:target: https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* `Franz Gusenbauer <https://www.igutech.at/>`_
* `Daniel Babiak <https://github.com/dbabiak>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
* Remo Rechkemmer
* Severin Ibarluzea
* Tom Saleeba
* Pawel Tyll
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+130
View File
@@ -0,0 +1,130 @@
PostgREST 9.0.0
===============
This major version is released with PostgreSQL 14 compatibility and is accompanied with new features and bug fixes. You can look at the detailed changelog and download the pre-compiled binaries on the `GitHub release page <https://github.com/PostgREST/postgrest/releases/tag/v9.0.0>`_.
Features
--------
PostgreSQL 14 compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~
PostgreSQL 14 Beta 1 tightened its GUC naming scheme making it impossible to use multiple dots (``.``) and dashes (``-``) on custom GUC parameters, this caused our :ref:`old HTTP Context <guc_legacy_names>` to fail across all requests. Thankfully, `@robertsosinski <https://github.com/robertsosinski>`_ got the PostgreSQL team to reconsider allowing multiple dots in the GUC name, allowing us to avoid a major breaking change. You can see the full discussion `here <https://www.postgresql.org/message-id/17045-6a4a9f0d1513f72b%40postgresql.org>`_.
Still, dashes cannot be used on PostgreSQL 14 custom GUC parameters, so we changed our HTTP Context :ref:`to namespace using a mix of dots and JSON <guc_req_headers_cookies_claims>`. On older PostgreSQL versions we still use the :ref:`guc_legacy_names`. If you wish to use the new JSON GUCs on these versions, set the :ref:`db-use-legacy-gucs` config option to false.
Resource Embedding with Top-level Filtering
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Historically, Resource Embedding was always done with a query that included the equivalent of a ``LEFT JOIN``, which meant you could not
exclude any of the top-level resource rows. You can now use :ref:`embedding_top_level_filter` to do the equivalent of an ``INNER JOIN``, thus you can filter the top-level resource rows with any of the available operators.
Partitioned Tables
~~~~~~~~~~~~~~~~~~
Partitioned tables now integrate with all the feature set. You can :ref:`embed partitioned tables <embedding_partitioned_tables>`, UPSERT, INSERT(with a correctly generated Location header) and make OPTIONS requests on them. They're also included in the generated OpenAPI.
Functions(RPC)
~~~~~~~~~~~~~~
* Functions with a :ref:`single unnamed parameter <s_proc_single_unnamed>` can now be used to POST raw ``bytea``, ``text`` or ``json/jsonb``.
Horizontal Filtering
~~~~~~~~~~~~~~~~~~~~
* The ``unknown`` value for three-valued logic can now be used on the ``is`` :ref:`operator <operators>`.
* Escaping double quotes(``"``) in double-quoted surrounded strings is now possible by using backslashes, e.g. ``?col=in.("Double\"Quote")``. Backslashes can be escaped with a preceding backslash, e.g. ``?col=in.("Back\\slash")``. See :ref:`reserved-chars`.
Administration
~~~~~~~~~~~~~~
* A ``Retry-After`` header is now added when PostgREST is doing :ref:`automatic_recovery`.
Error messages
~~~~~~~~~~~~~~
* :ref:`embed_disamb` now shows an improved error message that includes relevant hints for clearing out the ambiguous embedding.
Documentation improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~
* Added ``curl`` snippets to the :doc:`API <../api>` page.
* Added the :ref:`automatic_recovery` section.
* Added the :ref:`nested_embedding` section.
* Added the :ref:`logical_operators` section.
* Added the :ref:`templates` and :ref:`devops` sections to the :doc:`Ecosystem </ecosystem>`.
Bug fixes
---------
* Correct RPC return type handling for RETURNS TABLE with a single column (`#1930 <https://github.com/PostgREST/postgrest/issues/1930>`_).
* Schema Cache query failing with ``standard_conforming_strings = off`` (`#1992 <https://github.com/PostgREST/postgrest/issues/1992>`_).
* OpenAPI missing default values for String types (`#1871 <https://github.com/PostgREST/postgrest/issues/1871>`_).
Breaking changes
----------------
* Dropped support for PostgreSQL 9.5 as it already reached its end-of-life according to `PostgreSQL versioning policy <https://www.postgresql.org/support/versioning/>`_.
* Partitions of a `partitioned table <https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE>`_ are no longer included in the :doc:`../schema_cache`. This is so errors are not generated when doing resource embedding on partitioned tables.
* Dropped support for doing :ref:`hint_disamb` using dots instead of exclamation marks, e.g. doing ``select=*,projects.client_id(*)`` instead of ``select=*,projects!client_id(*)``). Using dots was undocumented and deprecated back in `v6.0.2 <https://github.com/PostgREST/postgrest/releases/tag/v6.0.2>`_.
Thanks
------
Big thanks from the `PostgREST team <https://github.com/orgs/PostgREST/people>`_ to our sponsors!
.. container:: image-container
.. image:: ../_static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/gnuhost.png
:target: https://gnuhost.eu/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: ../_static/oblivious.jpg
:target: https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* `Franz Gusenbauer <https://www.igutech.at/>`_
* `Daniel Babiak <https://github.com/dbabiak>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
* Remo Rechkemmer
* Severin Ibarluzea
* Tom Saleeba
* Pawel Tyll
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+89
View File
@@ -0,0 +1,89 @@
PostgREST 9.0.1
===============
This version includes important fixes for production environments and other miscellaneous fixes. You can download the pre-compiled binaries on the `GitHub release page <https://github.com/PostgREST/postgrest/releases/tag/v9.0.1>`_.
Bug Fixes
---------
* Keep working when ``EMFILE (Too many open files)`` is reached. (`#2042 <https://github.com/PostgREST/postgrest/issues/2042>`_)
* Disable parallel GC for better performance on higher core CPUs (`#2294 <https://github.com/PostgREST/postgrest/issues/2294>`_). Thanks to `NoRedInk for their blog post <https://blog.noredink.com/post/666654908557180928/tuning-haskell-rts-for-kubernetes-part-2>`_ that lead us to this fix.
* Fix using CPU while idle. (`#1076 <https://github.com/PostgREST/postgrest/issues/1076>`_)
* Fix reading database configuration properly when ``=`` is present in the value. (`#2120 <https://github.com/PostgREST/postgrest/issues/2120>`_)
* Fix ``is`` not working with upper or mixed case values like ``NULL``, ``TrUe``, ``FaLsE``. (`#2077 <https://github.com/PostgREST/postgrest/issues/2077>`_)
* Execute deferred constraint triggers when using ``Prefer: tx=rollback``. (`#2020 <https://github.com/PostgREST/postgrest/issues/2020>`_)
* Ignore ``Content-Type`` headers for ``GET`` requests when calling RPCs. (`#2147 <https://github.com/PostgREST/postgrest/issues/2147>`_)
* Previously, ``GET`` without parameters, but with ``Content-Type: text/plain`` or ``Content-Type: application/octet-stream`` would fail with ``404 Not Found``, even if a function without arguments was available.
* Fix wrong CORS header from ``Authentication`` to ``Authorization``. (`#1724 <https://github.com/PostgREST/postgrest/issues/1724>`_)
* Fix ``json`` and ``jsonb`` columns showing a type in OpenAPI spec. (`#2165 <https://github.com/PostgREST/postgrest/issues/2165>`_)
* Remove trigger functions from the schema cache and OpenAPI output, because they can't be called directly anyway. (`#2135 <https://github.com/PostgREST/postgrest/issues/2135>`_)
* Remove aggregates, procedures and window functions from the schema cache and OpenAPI output. (`#2101 <https://github.com/PostgREST/postgrest/issues/2101>`_)
* Fix schema cache loading when views with ``XMLTABLE`` and ``DEFAULT`` are present. (`#2024 <https://github.com/PostgREST/postgrest/issues/2024>`_)
* Fix ``--dump-schema`` running with a wrong PG version. (`#2153 <https://github.com/PostgREST/postgrest/issues/2153>`_)
* Fix misleading disambiguation error where the content of the ``relationship`` key looks like valid syntax. (`#2239 <https://github.com/PostgREST/postgrest/issues/2239>`_)
Thanks
------
Big thanks from the `PostgREST team <https://github.com/orgs/PostgREST/people>`_ to our sponsors!
.. container:: image-container
.. image:: ../_static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/2ndquadrant.png
:target: https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo
:width: 13em
.. image:: ../_static/retool.png
:target: https://retool.com/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/gnuhost.png
:target: https://gnuhost.eu/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../_static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: ../_static/oblivious.jpg
:target: https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
* Evans Fernandes
* `Jan Sommer <https://github.com/nerfpops>`_
* `Franz Gusenbauer <https://www.igutech.at/>`_
* `Daniel Babiak <https://github.com/dbabiak>`_
* Tsingson Qin
* Michel Pelletier
* Jay Hannah
* Robert Stolarz
* Nicholas DiBiase
* Christopher Reid
* Nathan Bouscal
* Daniel Rafaj
* David Fenko
* Remo Rechkemmer
* Severin Ibarluzea
* Tom Saleeba
* Pawel Tyll
If you like to join them please consider `supporting PostgREST development <https://github.com/PostgREST/postgrest#user-content-supporting-development>`_.
+6
View File
@@ -0,0 +1,6 @@
docutils==0.20.1
sphinx>=4.3.0
sphinx-copybutton
sphinx-rtd-theme>=0.5.1
sphinx-tabs
urllib3==2.2.3
+237
View File
@@ -0,0 +1,237 @@
.. _schema_cache:
Schema Cache
============
Certain PostgREST features require metadata from the database schema. Getting this metadata requires executing expensive queries, so
in order to avoid repeating this work, PostgREST uses a schema cache.
+--------------------------------------------+-------------------------------------------------------------------------------+
| Feature | Required Metadata |
+============================================+===============================================================================+
| :ref:`resource_embedding` | Foreign key constraints |
+--------------------------------------------+-------------------------------------------------------------------------------+
| :ref:`Stored Functions <s_procs>` | Function signature (parameters, return type, volatility and |
| | `overloading <https://www.postgresql.org/docs/current/xfunc-overload.html>`_) |
+--------------------------------------------+-------------------------------------------------------------------------------+
| :ref:`Upserts <upsert>` | Primary keys |
+--------------------------------------------+-------------------------------------------------------------------------------+
| :ref:`Insertions <insert>` | Primary keys (optional: only if the Location header is requested) |
+--------------------------------------------+-------------------------------------------------------------------------------+
| :ref:`OPTIONS requests <options_requests>` | View INSTEAD OF TRIGGERS and primary keys |
+--------------------------------------------+-------------------------------------------------------------------------------+
| :ref:`open-api` | Table columns, primary keys and foreign keys |
+ +-------------------------------------------------------------------------------+
| | View columns and INSTEAD OF TRIGGERS |
+ +-------------------------------------------------------------------------------+
| | Function signature |
+--------------------------------------------+-------------------------------------------------------------------------------+
.. _stale_schema:
The Stale Schema Cache
----------------------
When you make changes on the metadata mentioned above, the schema cache will turn stale on a running PostgREST. Future requests that use the above features will need the :ref:`schema cache to be reloaded <schema_reloading>`; otherwise, you'll get an error instead of the expected result.
For instance, let's see what would happen if you have a stale schema cache for foreign key relationships and function signatures.
.. _stale_fk_relationships:
Stale Foreign Key Relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose you add a ``cities`` table to your database and define a foreign key that references an existing ``countries`` table. Then, you make a request to get the ``cities`` and their belonging ``countries``.
.. tabs::
.. code-tab:: http
GET /cities?select=name,country:countries(id,name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/cities?select=name,country:countries(id,name)"
The result will be an error:
.. code-block:: json
{
"hint": "Verify that 'cities' and 'countries' exist in the schema 'api' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
"details": null,
"code": "PGRST200",
"message": "Could not find a relationship between 'cities' and 'countries' in the schema cache"
}
As you can see, PostgREST couldn't find the newly created foreign key in the schema cache. See :ref:`schema_reloading` and :ref:`auto_schema_reloading` to solve this issue.
.. _stale_function_signature:
Stale Function Signature
~~~~~~~~~~~~~~~~~~~~~~~~
The same issue will occur on newly created functions on a running PostgREST.
.. code-block:: plpgsql
CREATE FUNCTION plus_one(num integer)
RETURNS integer AS $$
SELECT num + 1;
$$ LANGUAGE SQL IMMUTABLE;
.. tabs::
.. code-tab:: http
GET /rpc/plus_one?num=1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one?num=1"
.. code-block:: json
{
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
"details": null,
"code": "PGRST202",
"message": "Could not find the api.plus_one(num) function in the schema cache"
}
Here, PostgREST tries to find the function on the stale schema to no avail. See :ref:`schema_reloading` and :ref:`auto_schema_reloading` to solve this issue.
.. _schema_reloading:
Schema Cache Reloading
----------------------
To reload the cache without restarting the PostgREST server, send a SIGUSR1 signal to the server process.
.. code:: bash
killall -SIGUSR1 postgrest
For docker you can do:
.. code:: bash
docker kill -s SIGUSR1 <container>
# or in docker-compose
docker-compose kill -s SIGUSR1 <service>
There's no downtime when reloading the schema cache. The reloading will happen on a background thread while requests keep being served.
.. _schema_reloading_notify:
Reloading with NOTIFY
~~~~~~~~~~~~~~~~~~~~~
There are environments where you can't send the SIGUSR1 Unix Signal (like on managed containers in cloud services or on Windows systems). For this reason, PostgREST also allows you to reload its schema cache through PostgreSQL `NOTIFY <https://www.postgresql.org/docs/current/sql-notify.html>`_ as follows:
.. code-block:: postgresql
NOTIFY pgrst, 'reload schema'
The ``"pgrst"`` notification channel is enabled by default. For configuring the channel, see :ref:`db-channel` and :ref:`db-channel-enabled`.
.. _auto_schema_reloading:
Automatic Schema Cache Reloading
--------------------------------
You can do automatic schema cache reloading in a pure SQL way and forget about stale schema cache errors with an `event trigger <https://www.postgresql.org/docs/current/event-trigger-definition.html>`_ and ``NOTIFY``.
.. code-block:: postgresql
-- Create an event trigger function
CREATE OR REPLACE FUNCTION pgrst_watch() RETURNS event_trigger
LANGUAGE plpgsql
AS $$
BEGIN
NOTIFY pgrst, 'reload schema';
END;
$$;
-- This event trigger will fire after every ddl_command_end event
CREATE EVENT TRIGGER pgrst_watch
ON ddl_command_end
EXECUTE PROCEDURE pgrst_watch();
Now, whenever the ``pgrst_watch`` trigger is fired in the database, PostgREST will automatically reload the schema cache.
To disable auto reloading, drop the trigger:
.. code-block:: postgresql
DROP EVENT TRIGGER pgrst_watch
Finer-Grained Event Trigger
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can refine the previous event trigger and only react to the events relevant to the schema cache. This also prevents unnecessary
reloading when creating temporary tables(``CREATE TEMP TABLE``) inside functions.
.. code-block:: postgresql
-- watch create and alter
CREATE OR REPLACE FUNCTION pgrst_ddl_watch() RETURNS event_trigger AS $$
DECLARE
cmd record;
BEGIN
FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands()
LOOP
IF cmd.command_tag IN (
'CREATE SCHEMA', 'ALTER SCHEMA'
, 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE'
, 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE'
, 'CREATE VIEW', 'ALTER VIEW'
, 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW'
, 'CREATE FUNCTION', 'ALTER FUNCTION'
, 'CREATE TRIGGER'
, 'CREATE TYPE', 'ALTER TYPE'
, 'CREATE RULE'
, 'COMMENT'
)
-- don't notify in case of CREATE TEMP table or other objects created on pg_temp
AND cmd.schema_name is distinct from 'pg_temp'
THEN
NOTIFY pgrst, 'reload schema';
END IF;
END LOOP;
END; $$ LANGUAGE plpgsql;
-- watch drop
CREATE OR REPLACE FUNCTION pgrst_drop_watch() RETURNS event_trigger AS $$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
LOOP
IF obj.object_type IN (
'schema'
, 'table'
, 'foreign table'
, 'view'
, 'materialized view'
, 'function'
, 'trigger'
, 'type'
, 'rule'
)
AND obj.is_temporary IS false -- no pg_temp objects
THEN
NOTIFY pgrst, 'reload schema';
END IF;
END LOOP;
END; $$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER pgrst_ddl_watch
ON ddl_command_end
EXECUTE PROCEDURE pgrst_ddl_watch();
CREATE EVENT TRIGGER pgrst_drop_watch
ON sql_drop
EXECUTE PROCEDURE pgrst_drop_watch();
+96
View File
@@ -0,0 +1,96 @@
.. note::
This page is a work in progress.
.. _schema_isolation:
Schema Isolation
================
A PostgREST instance exposes all the tables, views, and stored procedures of a single `PostgreSQL schema <https://www.postgresql.org/docs/current/ddl-schemas.html>`_ (a namespace of database objects). This means private data or implementation details can go inside different private schemas and be invisible to HTTP clients.
It is recommended that you don't expose tables on your API schema. Instead expose views and stored procedures which insulate the internal details from the outside world.
This allows you to change the internals of your schema and maintain backwards compatibility. It also keeps your code easier to refactor, and provides a natural way to do API versioning.
.. image:: _static/db.png
.. _func_privs:
Functions
=========
By default, when a function is created, the privilege to execute it is not restricted by role. The function access is ``PUBLIC`` — executable by all roles (more details at `PostgreSQL Privileges page <https://www.postgresql.org/docs/current/ddl-priv.html>`_). This is not ideal for an API schema. To disable this behavior, you can run the following SQL statement:
.. code-block:: postgres
ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
This will change the privileges for all functions created in the future in all schemas. Currently there is no way to limit it to a single schema. In our opinion it's a good practice anyway.
.. note::
It is however possible to limit the effect of this clause only to functions you define. You can put the above statement at the beginning of the API schema definition, and then at the end reverse it with:
.. code-block:: postgres
ALTER DEFAULT PRIVILEGES GRANT EXECUTE ON FUNCTIONS TO PUBLIC;
This will work because the :code:`alter default privileges` statement has effect on function created *after* it is executed. See `PostgreSQL alter default privileges <https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html>`_ for more details.
After that, you'll need to grant EXECUTE privileges on functions explicitly:
.. code-block:: postgres
GRANT EXECUTE ON FUNCTION login TO anonymous;
GRANT EXECUTE ON FUNCTION signup TO anonymous;
You can also grant execute on all functions in a schema to a higher privileged role:
.. code-block:: postgres
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA api TO web_user;
Security definer
----------------
A function is executed with the privileges of the user who calls it. This means that the user has to have all permissions to do the operations the procedure performs.
If the function accesses private database objects, your :ref:`API roles <roles>` won't be able to successfully execute the function.
Another option is to define the function with the :code:`SECURITY DEFINER` option. Then only one permission check will take place, the permission to call the function, and the operations in the function will have the authority of the user who owns the function itself.
.. code-block:: postgres
-- login as a user wich has privileges on the private schemas
-- create a sample function
create or replace function login(email text, pass text) returns jwt_token as $$
begin
-- access to a private schema called 'auth'
select auth.user_role(email, pass) into _role;
-- other operations
-- ...
end;
$$ language plpgsql security definer;
Note the ``SECURITY DEFINER`` keywords at the end of the function. See `PostgreSQL documentation <https://www.postgresql.org/docs/current/sql-createfunction.html#SQL-CREATEFUNCTION-SECURITY>`_ for more details.
Views
=====
Views are invoked with the privileges of the view owner, much like stored procedures with the ``SECURITY DEFINER`` option. When created by a SUPERUSER role, all `row-level security <https://www.postgresql.org/docs/current/ddl-rowsecurity.html>`_ will be bypassed unless a different, non-SUPERUSER owner is specified.
For changing this, we can create a non-SUPERUSER role and make this role the view's owner.
.. code-block:: postgres
CREATE ROLE api_views_owner NOINHERIT;
ALTER VIEW sample_view OWNER TO api_views_owner;
Rules
-----
Insertion on views with complex `rules <https://www.postgresql.org/docs/current/sql-createrule.html>`_ might not work out of the box with PostgREST.
It's recommended that you `use triggers instead of rules <https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_rules>`_.
If you want to keep using rules, a workaround is to wrap the view insertion in a stored procedure and call it through the :ref:`s_procs` interface.
For more details, see this `github issue <https://github.com/PostgREST/postgrest/issues/1283>`_.
+17
View File
@@ -0,0 +1,17 @@
let
docs =
import ./default.nix;
inherit (docs) pkgs;
in
pkgs.mkShell {
name = "postgrest-docs";
buildInputs = [
docs.build
docs.serve
docs.spellcheck
docs.dictcheck
docs.linkcheck
];
}
+226
View File
@@ -0,0 +1,226 @@
.. _tut0:
Tutorial 0 - Get it Running
===========================
:author: `begriffs <https://github.com/begriffs>`_
Welcome to PostgREST! In this pre-tutorial we're going to get things running so you can create your first simple API.
PostgREST is a standalone web server which turns a PostgreSQL database into a RESTful API. It serves an API that is customized based on the structure of the underlying database.
.. image:: ../_static/tuts/tut0-request-flow.png
To make an API we'll simply be building a database. All the endpoints and permissions come from database objects like tables, views, roles, and stored procedures. These tutorials will cover a number of common scenarios and how to model them in the database.
By the end of this tutorial you'll have a working database, PostgREST server, and a simple single-user todo list API.
Step 1. Install PostgreSQL
--------------------------
If you're already familiar with using PostgreSQL and have it installed on your system you can use the existing installation (see :ref:`pg-dependency` for minimum requirements). For this tutorial we'll describe how to use the database in Docker because database configuration is otherwise too complicated for a simple tutorial.
If Docker is not installed, you can get it `here <https://www.docker.com/get-started>`_. Next, let's pull and start the database image:
.. code-block:: bash
sudo docker run --name tutorial -p 5433:5432 \
-e POSTGRES_PASSWORD=mysecretpassword \
-d postgres
This will run the Docker instance as a daemon and expose port 5433 to the host system so that it looks like an ordinary PostgreSQL server to the rest of the system.
Step 2. Install PostgREST
-------------------------
PostgREST is distributed as a single binary, with versions compiled for major distributions of Linux/BSD/Windows. Visit the `latest release <https://github.com/PostgREST/postgrest/releases/latest>`_ for a list of downloads. In the event that your platform is not among those already pre-built, see :ref:`build_source` for instructions how to build it yourself. Also let us know to add your platform in the next release.
The pre-built binaries for download are :code:`.tar.xz` compressed files (except Windows which is a zip file). To extract the binary, go into the terminal and run
.. code-block:: bash
# download from https://github.com/PostgREST/postgrest/releases/latest
tar xJf postgrest-<version>-<platform>.tar.xz
The result will be a file named simply :code:`postgrest` (or :code:`postgrest.exe` on Windows). At this point try running it with
.. code-block:: bash
./postgrest -h
If everything is working correctly it will print out its version and the available options. You can continue to run this binary from where you downloaded it, or copy it to a system directory like :code:`/usr/local/bin` on Linux so that you will be able to run it from any directory.
.. note::
PostgREST requires libpq, the PostgreSQL C library, to be installed on your system. Without the library you'll get an error like "error while loading shared libraries: libpq.so.5." Here's how to fix it:
.. raw:: html
<p>
<details>
<summary>Ubuntu or Debian</summary>
<div class="highlight-bash"><div class="highlight">
<pre>sudo apt-get install libpq-dev</pre>
</div></div>
</details>
<details>
<summary>Fedora, CentOS, or Red Hat</summary>
<div class="highlight-bash"><div class="highlight">
<pre>sudo yum install postgresql-libs</pre>
</div></div>
</details>
<details>
<summary>OS X</summary>
<div class="highlight-bash"><div class="highlight">
<pre>brew install postgresql</pre>
</div></div>
</details>
<details>
<summary>Windows</summary>
<p>All of the DLL files that are required to run PostgREST are available in the windows installation of PostgreSQL server.
Once installed they are found in the BIN folder, e.g: C:\Program Files\PostgreSQL\10\bin. Add this directory to your PATH
variable. Run the following from an administrative command prompt (adjusting the actual BIN path as necessary of course)
<pre>setx /m PATH "%PATH%;C:\Program Files\PostgreSQL\10\bin"</pre>
</p>
</details>
</p>
Step 3. Create Database for API
-------------------------------
Connect to the SQL console (psql) inside the container. To do so, run this from your command line:
.. code-block:: bash
sudo docker exec -it tutorial psql -U postgres
You should see the psql command prompt:
::
psql (9.6.3)
Type "help" for help.
postgres=#
The first thing we'll do is create a `named schema <https://www.postgresql.org/docs/current/ddl-schemas.html>`_ for the database objects which will be exposed in the API. We can choose any name we like, so how about "api." Execute this and the other SQL statements inside the psql prompt you started.
.. code-block:: postgres
create schema api;
Our API will have one endpoint, :code:`/todos`, which will come from a table.
.. code-block:: postgres
create table api.todos (
id serial primary key,
done boolean not null default false,
task text not null,
due timestamptz
);
insert into api.todos (task) values
('finish tutorial 0'), ('pat self on back');
Next make a role to use for anonymous web requests. When a request comes in, PostgREST will switch into this role in the database to run queries.
.. code-block:: postgres
create role web_anon nologin;
grant usage on schema api to web_anon;
grant select on api.todos to web_anon;
The :code:`web_anon` role has permission to access things in the :code:`api` schema, and to read rows in the :code:`todos` table.
It's a good practice to create a dedicated role for connecting to the database, instead of using the highly privileged ``postgres`` role. So we'll do that, name the role ``authenticator`` and also grant it the ability to switch to the ``web_anon`` role :
.. code-block:: postgres
create role authenticator noinherit login password 'mysecretpassword';
grant web_anon to authenticator;
Now quit out of psql; it's time to start the API!
.. code-block:: psql
\q
Step 4. Run PostgREST
---------------------
PostgREST can use a configuration file to tell it how to connect to the database. Create a file :code:`tutorial.conf` with this inside:
.. code-block:: ini
db-uri = "postgres://authenticator:mysecretpassword@localhost:5433/postgres"
db-schemas = "api"
db-anon-role = "web_anon"
The configuration file has other :doc:`options <../configuration>`, but this is all we need.
If you are not using Docker, make sure that your port number is correct and replace `postgres` with the name of the database where you added the todos table.
Now run the server:
.. code-block:: bash
./postgrest tutorial.conf
You should see
.. code-block:: text
Listening on port 3000
Attempting to connect to the database...
Connection successful
It's now ready to serve web requests. There are many nice graphical API exploration tools you can use, but for this tutorial we'll use :code:`curl` because it's likely to be installed on your system already. Open a new terminal (leaving the one open that PostgREST is running inside). Try doing an HTTP request for the todos.
.. code-block:: bash
curl http://localhost:3000/todos
The API replies:
.. code-block:: json
[
{
"id": 1,
"done": false,
"task": "finish tutorial 0",
"due": null
},
{
"id": 2,
"done": false,
"task": "pat self on back",
"due": null
}
]
With the current role permissions, anonymous requests have read-only access to the :code:`todos` table. If we try to add a new todo we are not able.
.. code-block:: bash
curl http://localhost:3000/todos -X POST \
-H "Content-Type: application/json" \
-d '{"task": "do bad thing"}'
Response is 401 Unauthorized:
.. code-block:: json
{
"hint": null,
"details": null,
"code": "42501",
"message": "permission denied for table todos"
}
There we have it, a basic API on top of the database! In the next tutorials we will see how to extend the example with more sophisticated user access controls, and more tables and queries.
Now that you have PostgREST running, try the next tutorial, :ref:`tut1`
+263
View File
@@ -0,0 +1,263 @@
.. _tut1:
Tutorial 1 - The Golden Key
===========================
:author: `begriffs <https://github.com/begriffs>`_
In :ref:`tut0` we created a read-only API with a single endpoint to list todos. There are many directions we can go to make this API more interesting, but one good place to start would be allowing some users to change data in addition to reading it.
Step 1. Add a Trusted User
--------------------------
The previous tutorial created a :code:`web_anon` role in the database with which to execute anonymous web requests. Let's make a role called :code:`todo_user` for users who authenticate with the API. This role will have the authority to do anything to the todo list.
.. code-block:: postgres
-- run this in psql using the database created
-- in the previous tutorial
create role todo_user nologin;
grant todo_user to authenticator;
grant usage on schema api to todo_user;
grant all on api.todos to todo_user;
grant usage, select on sequence api.todos_id_seq to todo_user;
Step 2. Make a Secret
---------------------
Clients authenticate with the API using JSON Web Tokens. These are JSON objects which are cryptographically signed using a password known to only us and the server. Because clients do not know the password, they cannot tamper with the contents of their tokens. PostgREST will detect counterfeit tokens and will reject them.
Let's create a password and provide it to PostgREST. Think of a nice long one, or use a tool to generate it. **Your password must be at least 32 characters long.**
.. note::
Unix tools can generate a nice password for you:
.. code-block:: bash
# Allow "tr" to process non-utf8 byte sequences
export LC_CTYPE=C
# read random bytes and keep only alphanumerics
< /dev/urandom tr -dc A-Za-z0-9 | head -c32
Open the :code:`tutorial.conf` (created in the previous tutorial) and add a line with the password:
.. code-block:: ini
# PASSWORD MUST BE AT LEAST 32 CHARS LONG
# add this line to tutorial.conf:
jwt-secret = "<the password you made>"
If the PostgREST server is still running from the previous tutorial, restart it to load the updated configuration file.
Step 3. Sign a Token
--------------------
Ordinarily your own code in the database or in another server will create and sign authentication tokens, but for this tutorial we will make one "by hand." Go to `jwt.io <https://jwt.io/#debugger-io>`_ and fill in the fields like this:
.. figure:: ../_static/tuts/tut1-jwt-io.png
:alt: jwt.io interface
How to create a token at https://jwt.io
**Remember to fill in the password you generated rather than the word "secret".** After you have filled in the password and payload, the encoded data on the left will update. Copy the encoded token.
.. note::
While the token may look well obscured, it's easy to reverse engineer the payload. The token is merely signed, not encrypted, so don't put things inside that you don't want a determined client to see.
Step 4. Make a Request
----------------------
Back in the terminal, let's use :code:`curl` to add a todo. The request will include an HTTP header containing the authentication token.
.. code-block:: bash
export TOKEN="<paste token here>"
curl http://localhost:3000/todos -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"task": "learn how to auth"}'
And now we have completed all three items in our todo list, so let's set :code:`done` to true for them all with a :code:`PATCH` request.
.. code-block:: bash
curl http://localhost:3000/todos -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"done": true}'
A request for the todos shows three of them, and all completed.
.. code-block:: bash
curl http://localhost:3000/todos
.. code-block:: json
[
{
"id": 1,
"done": true,
"task": "finish tutorial 0",
"due": null
},
{
"id": 2,
"done": true,
"task": "pat self on back",
"due": null
},
{
"id": 3,
"done": true,
"task": "learn how to auth",
"due": null
}
]
Step 5. Add Expiration
----------------------
Currently our authentication token is valid for all eternity. The server, as long as it continues using the same JWT password, will honor the token.
It's better policy to include an expiration timestamp for tokens using the :code:`exp` claim. This is one of two JWT claims that PostgREST treats specially.
+--------------+----------------------------------------------------------------+
| Claim | Interpretation |
+==============+================================================================+
| :code:`role` | The database role under which to execute SQL for API request |
+--------------+----------------------------------------------------------------+
| :code:`exp` | Expiration timestamp for token, expressed in "Unix epoch time" |
+--------------+----------------------------------------------------------------+
.. note::
Epoch time is defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), January 1st 1970, minus the number of leap seconds that have taken place since then.
To observe expiration in action, we'll add an :code:`exp` claim of five minutes in the future to our previous token. First find the epoch value of five minutes from now. In psql run this:
.. code-block:: postgres
select extract(epoch from now() + '5 minutes'::interval) :: integer;
Go back to jwt.io and change the payload to
.. code-block:: json
{
"role": "todo_user",
"exp": 123456789
}
**NOTE**: Don't forget to change the dummy epoch value :code:`123456789` in the snippet above to the epoch value returned by the psql command.
Copy the updated token as before, and save it as a new environment variable.
.. code-block:: bash
export NEW_TOKEN="<paste new token>"
Try issuing this request in curl before and after the expiration time:
.. code-block:: bash
curl http://localhost:3000/todos \
-H "Authorization: Bearer $NEW_TOKEN"
After expiration, the API returns HTTP 401 Unauthorized:
.. code-block:: json
{
"hint": null,
"details": null,
"code": "PGRST301",
"message": "JWT expired"
}
Bonus Topic: Immediate Revocation
---------------------------------
Even with token expiration there are times when you may want to immediately revoke access for a specific token. For instance, suppose you learn that a disgruntled employee is up to no good and his token is still valid.
To revoke a specific token we need a way to tell it apart from others. Let's add a custom :code:`email` claim that matches the email of the client issued the token.
Go ahead and make a new token with the payload
.. code-block:: json
{
"role": "todo_user",
"email": "disgruntled@mycompany.com"
}
Save it to an environment variable:
.. code-block:: bash
export WAYWARD_TOKEN="<paste new token>"
PostgREST allows us to specify a stored procedure to run during attempted authentication. The function can do whatever it likes, including raising an exception to terminate the request.
First make a new schema and add the function:
.. code-block:: plpgsql
create schema auth;
grant usage on schema auth to web_anon, todo_user;
create or replace function auth.check_token() returns void
language plpgsql
as $$
begin
if current_setting('request.jwt.claims', true)::json->>'email' =
'disgruntled@mycompany.com' then
raise insufficient_privilege
using hint = 'Nope, we are on to you';
end if;
end
$$;
Next update :code:`tutorial.conf` and specify the new function:
.. code-block:: ini
# add this line to tutorial.conf
db-pre-request = "auth.check_token"
Restart PostgREST for the change to take effect. Next try making a request with our original token and then with the revoked one.
.. code-block:: bash
# this request still works
curl http://localhost:3000/todos -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"done": true}'
# this one is rejected
curl http://localhost:3000/todos -X PATCH \
-H "Authorization: Bearer $WAYWARD_TOKEN" \
-H "Content-Type: application/json" \
-d '{"task": "AAAHHHH!", "done": false}'
The server responds with 403 Forbidden:
.. code-block:: json
{
"hint": "Nope, we are on to you",
"details": null,
"code": "42501",
"message": "insufficient_privilege"
}
-22
View File
@@ -1,22 +0,0 @@
# This Dockerfile is only used as a development environment for
# non-nix systems, i.e. Windows.
FROM nixos/nix:latest
RUN apk --no-cache add \
wget
RUN nix-env -iA cachix -f https://cachix.org/api/v1/install \
&& cachix use postgrest
# We need an unprivileged user here, to make PG run at all.
RUN adduser --disabled-password --ingroup root nix \
&& chown -R nix:root /nix
USER nix:root
ENV USER=nix
VOLUME /nix
VOLUME /postgrest
WORKDIR /postgrest
CMD nix-shell
-6
View File
@@ -204,12 +204,6 @@ postgrest-loadtest
# You can loadtest comparing to a different branch
postgrest-loadtest-against master
# You can simulate latency client/postgrest and postgrest/database
PGRST_DELAY=5ms PGDELAY=5ms postgrest-loadtest
# You can build postgrest directly with cabal for faster iteration
PGRST_BUILD_CABAL=1 postgrest-loadtest
# Produce a markdown report to be used on CI
postgrest-loadtest-report
```
-12
View File
@@ -1,12 +0,0 @@
version: '3'
services:
nix:
container_name: postgrest-nix
build: .
volumes:
- ../:/postgrest
- nix:/nix
volumes:
nix:
+3 -3
View File
@@ -1,6 +1,6 @@
# Pinned version of Nixpkgs, generated with postgrest-nixpkgs-upgrade.
{
date = "2023-03-25";
rev = "dbf5322e93bcc6cfc52268367a8ad21c09d76fea";
tarballHash = "0lwk4v9dkvd28xpqch0b0jrac4xl9lwm6snrnzx8k5lby72kmkng";
date = "2023-01-12";
rev = "92f9580a4c369b4b51a7b6a5e77da43720134c9f";
tarballHash = "0w9bz4f2bmkj4a59n4z279zcgs9clyc40a4ny312rafyaknzghvw";
}
-1
View File
@@ -7,5 +7,4 @@
postgresql-default = import ./postgresql-default.nix;
postgresql-legacy = import ./postgresql-legacy.nix;
postgresql-future = import ./postgresql-future.nix;
slocat = import ./slocat.nix;
}
+4 -4
View File
@@ -43,8 +43,8 @@ let
(prev.callHackageDirect
{
pkg = "hasql-notifications";
ver = "0.2.0.5";
sha256 = "sha256-KV36zs/RTgJh/oBBPZaNiQshusmakWnjYTcdoNa4JLA=";
ver = "0.2.0.4";
sha256 = "sha256-fm1xiDyvDkb5WLOJ73/s8wrWEW23XFS7luAv2brfr8I=";
}
{ });
@@ -52,8 +52,8 @@ let
(prev.callHackageDirect
{
pkg = "hasql-pool";
ver = "0.10";
sha256 = "sha256-kHzoqtNV9BFWnn1h560JRqMooQRwxokVKgDRBexamNI=";
ver = "0.9";
sha256 = "sha256-5UshbbaBVY8eJ/9VagNVVxonRwMcd7UmGqDc35pJNFY=";
}
{ });
} // extraOverrides final prev;
-13
View File
@@ -1,13 +0,0 @@
final: prev:
{
slocat = prev.buildGoModule {
name = "slocat";
src = prev.fetchFromGitHub {
owner = "robx";
repo = "slocat";
rev = "52e7512c6029fd00483e41ccce260a3b4b9b3b64";
sha256 = "sha256-qn6luuh5wqREu3s8RfuMCP5PKdS2WdwPrujRYTpfzQ8=";
};
vendorSha256 = "sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo=";
};
}
+1 -4
View File
@@ -59,7 +59,4 @@ let
survey =
import "${patched-static-haskell-nix}/survey" { inherit normalPkgs compiler defaultCabalPackageVersionComingWithGhc; };
in
{
inherit survey;
package = survey.haskellPackages."${name}";
}
survey.haskellPackages."${name}"
+2 -12
View File
@@ -37,22 +37,12 @@ let
checkedShellScript
{
name = "postgrest-run";
docs = "Run PostgREST after building it interactively with cabal-install";
args =
[
"ARG_USE_ENV([PGRST_DB_ANON_ROLE], [postgrest_test_anonymous], [PostgREST anonymous role])"
"ARG_USE_ENV([PGRST_DB_POOL], [1], [PostgREST pool size])"
"ARG_USE_ENV([PGRST_DB_POOL_ACQUISITION_TIMEOUT], [1], [PostgREST pool size])"
"ARG_LEFTOVERS([PostgREST arguments])"
];
docs = "Run PostgREST after buidling it interactively with cabal-install";
args = [ "ARG_LEFTOVERS([PostgREST arguments])" ];
inRootDir = true;
withEnv = postgrest.env;
}
''
export PGRST_DB_ANON_ROLE
export PGRST_DB_POOL
export PGRST_DB_POOL_ACQUISITION_TIMEOUT
exec ${cabal-install}/bin/cabal v2-run ${devCabalOptions} --verbose=0 -- \
postgrest "''${_arg_leftovers[@]}"
'';
-1
View File
@@ -304,5 +304,4 @@ buildToolbox
hsieGraphModules
hsieGraphSymbols
];
extra = { inherit pushCachix; };
}
+1 -4
View File
@@ -56,14 +56,11 @@ let
export PGRST_LOG_LEVEL="crit"
mkdir -p "$(dirname "$_arg_output")"
abs_output="$(realpath "$_arg_output")"
# shellcheck disable=SC2145
${withTools.withPg} --fixtures "$_arg_testdir"/fixtures.sql \
${withTools.withSlowPg} \
${withTools.withPgrst} \
${withTools.withSlowPgrst} \
sh -c "cd \"$_arg_testdir\" && ${runner} -targets targets.http -output \"$abs_output\" \"''${_arg_leftovers[@]}\""
sh -c "cd \"$_arg_testdir\" && ${runner} -targets targets.http -output \"$_arg_output\" \"''${_arg_leftovers[@]}\""
${vegeta}/bin/vegeta report -type=text "$_arg_output"
'';
+3 -4
View File
@@ -72,15 +72,14 @@ let
today_date="$(date '+%Y%m%d')"
today_date_for_changelog="$(date '+%Y-%m-%d')"
bump_pre="$major.$minor.$patch.$today_date"
bump_pre_minor="$major.$((minor+1)).0.$today_date"
bump_patch="$major.$minor.$((patch+1))"
bump_minor="$major.$((minor+1)).0"
bump_major="$((major+1)).0.0"
PS3="Please select the new version: "
select new_version in "$bump_pre" "$bump_pre_minor" "$bump_patch" "$bump_minor" "$bump_major"; do
select new_version in "$bump_pre" "$bump_patch" "$bump_minor" "$bump_major"; do
case "$REPLY" in
1|2|3|4|5)
1|2|3|4)
echo "Selected $new_version"
break
;;
@@ -96,7 +95,7 @@ let
echo "Committing ..."
git add postgrest.cabal > /dev/null
if [[ "$new_version" != "$bump_pre" && "$new_version" != "$bump_pre_minor" ]]; then
if [[ "$new_version" != "$bump_pre" ]]; then
echo "Updating CHANGELOG.md ..."
sed -i -E "s/Unreleased/&\n\n## [$new_version] - $today_date_for_changelog/" CHANGELOG.md > /dev/null
git add CHANGELOG.md > /dev/null
@@ -1,8 +1,6 @@
# PostgREST
[![Join the chat at https://gitter.im/begriffs/postgrest](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/begriffs/postgrest)
[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/postgrest)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/postgrest)
[![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](http://postgrest.org)
[![Build Status](https://github.com/postgrest/postgrest/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/PostgREST/postgrest/actions?query=branch%3Amain)
+15 -115
View File
@@ -1,7 +1,6 @@
{ bash-completion
, buildToolbox
, cabal-install
, cabalTools
, checkedShellScript
, curl
, devCabalOptions
@@ -9,20 +8,15 @@
, lib
, postgresqlVersions
, postgrest
, slocat
, writeText
}:
let
withTmpDb =
{ name, postgresql }:
let
commandName = "postgrest-with-${name}";
superuserRole = "postgres";
in
checkedShellScript
{
name = commandName;
docs = "Run the given command in a temporary database with ${name}. If you wish to mutate the database, login with the '${superuserRole}' role.";
name = "postgrest-with-${name}";
docs = "Run the given command in a temporary database with ${name}";
args =
[
"ARG_OPTIONAL_SINGLE([fixtures], [f], [SQL file to load fixtures from], [test/spec/fixtures/load.sql])"
@@ -31,8 +25,6 @@ let
"ARG_USE_ENV([PGUSER], [postgrest_test_authenticator], [Authenticator PG role])"
"ARG_USE_ENV([PGDATABASE], [postgres], [PG database name])"
"ARG_USE_ENV([PGRST_DB_SCHEMAS], [test], [Schema to expose])"
"ARG_USE_ENV([PGTZ], [utc], [Timezone to use])"
"ARG_USE_ENV([PGOPTIONS], [-c search_path=public,test], [PG options to use])"
];
positionalCompletion = "_command";
inRootDir = true;
@@ -61,8 +53,6 @@ let
export PGUSER
export PGDATABASE
export PGRST_DB_SCHEMAS
export PGTZ
export PGOPTIONS
HBA_FILE="$tmpdir/pg_hba.conf"
echo "local $PGDATABASE some_protected_user password" > "$HBA_FILE"
@@ -71,13 +61,12 @@ let
log "Initializing database cluster..."
# We try to make the database cluster as independent as possible from the host
# by specifying the timezone, locale and encoding.
# initdb -U creates a superuser(man initdb)
PGTZ=UTC initdb --no-locale --encoding=UTF8 --nosync -U "${superuserRole}" --auth=trust \
PGTZ=UTC initdb --no-locale --encoding=UTF8 --nosync -U "$PGUSER" --auth=trust \
>> "$setuplog"
log "Starting the database cluster..."
# Instead of listening on a local port, we will listen on a unix domain socket.
pg_ctl -l "$tmpdir/db.log" -w start -o "-F -c listen_addresses=\"\" -c hba_file=$HBA_FILE -k $PGHOST -c log_statement=\"all\" " \
pg_ctl -l "$tmpdir/db.log" -w start -o "-F -c listen_addresses=\"\" -c hba_file=$HBA_FILE -k $PGHOST -c log_statement=\"all\"" \
>> "$setuplog"
# shellcheck disable=SC2317
@@ -88,17 +77,10 @@ let
}
trap stop EXIT
log "Creating a minimally privileged $PGUSER connection role..."
createuser "$PGUSER" -U "${superuserRole}" --host="$tmpdir/socket" --no-createdb --no-inherit --no-superuser --no-createrole --no-replication --login
log "Loading fixtures under the ${superuserRole} role..."
psql -U "${superuserRole}" -v PGUSER="$PGUSER" -v ON_ERROR_STOP=1 -f "$_arg_fixtures" >> "$setuplog"
log "Loading fixtures..."
psql -v ON_ERROR_STOP=1 -f "$_arg_fixtures" >> "$setuplog"
log "Done. Running command..."
echo "${commandName}: You can connect with: psql 'postgres:///$PGDATABASE?host=$tmpdir/socket' -U ${superuserRole}"
echo "${commandName}: You can tail the logs with: tail -f $tmpdir/db.log"
("$_arg_command" "''${_arg_leftovers[@]}")
'';
@@ -148,81 +130,6 @@ let
withPg = builtins.head withPgVersions;
withSlowPg =
checkedShellScript
{
name = "postgrest-with-slow-pg";
docs = "Run the given command with simulated high latency postgresql";
args =
[
"ARG_POSITIONAL_SINGLE([command], [Command to run])"
"ARG_LEFTOVERS([command arguments])"
"ARG_USE_ENV([PGHOST], [], [PG host (socket name)])"
"ARG_USE_ENV([PGDELAY], [0ms], [extra PG latency (duration)])"
];
positionalCompletion = "_command";
inRootDir = true;
redirectTixFiles = false;
withTmpDir = true;
}
''
delay="''${PGDELAY:-0ms}"
echo "delaying data to/from postgres by $delay"
REALPGHOST="$PGHOST"
export PGHOST="$tmpdir/socket"
mkdir -p "$PGHOST"
${slocat}/bin/slocat -delay "$delay" -src "$PGHOST/.s.PGSQL.5432" -dst "$REALPGHOST/.s.PGSQL.5432" &
SLOCAT_PID=$!
# shellcheck disable=SC2317
stop_slocat() {
kill "$SLOCAT_PID" || true
wait "$SLOCAT_PID" || true
}
trap stop_slocat EXIT
sleep 1 # should wait for socket file to appear instead
("$_arg_command" "''${_arg_leftovers[@]}")
'';
withSlowPgrst =
checkedShellScript
{
name = "postgrest-with-slow-postgrest";
docs = "Run the given command with simulated high latency postgrest";
args =
[
"ARG_POSITIONAL_SINGLE([command], [Command to run])"
"ARG_LEFTOVERS([command arguments])"
"ARG_USE_ENV([PGRST_SERVER_UNIX_SOCKET], [], [PostgREST host (socket name)])"
"ARG_USE_ENV([PGRST_DELAY], [0ms], [extra PostgREST latency (duration)])"
];
positionalCompletion = "_command";
inRootDir = true;
redirectTixFiles = false;
withTmpDir = true;
}
''
delay="''${PGRST_DELAY:-0ms}"
echo "delaying data to/from PostgREST by $delay"
REAL_PGRST_SERVER_UNIX_SOCKET="$PGRST_SERVER_UNIX_SOCKET"
export PGRST_SERVER_UNIX_SOCKET="$tmpdir/postgrest.socket"
${slocat}/bin/slocat -delay "$delay" -src "$PGRST_SERVER_UNIX_SOCKET" -dst "$REAL_PGRST_SERVER_UNIX_SOCKET" &
SLOCAT_PID=$!
# shellcheck disable=SC2317
stop_slocat() {
kill "$SLOCAT_PID" || true
wait "$SLOCAT_PID" || true
}
trap stop_slocat EXIT
sleep 1 # should wait for socket file to appear instead
("$_arg_command" "''${_arg_leftovers[@]}")
'';
withGit =
let
name = "postgrest-with-git";
@@ -343,23 +250,16 @@ let
export PGRST_SERVER_UNIX_SOCKET="$tmpdir"/postgrest.socket
rm -f result
if [ -z "''${PGRST_BUILD_CABAL:-}" ]; then
echo -n "Building postgrest (nix)... "
nix-build -A postgrestPackage > "$tmpdir"/build.log 2>&1 || {
echo "failed, output:"
cat "$tmpdir"/build.log
exit 1
}
PGRST_CMD=./result/bin/postgrest
else
echo -n "Building postgrest (cabal)... "
postgrest-build
PGRST_CMD=postgrest-run
fi
echo -n "Building postgrest... "
nix-build -A postgrestPackage > "$tmpdir"/build.log 2>&1 || {
echo "failed, output:"
cat "$tmpdir"/build.log
exit 1
}
echo "done."
echo -n "Starting postgrest... "
$PGRST_CMD ${legacyConfig} > "$tmpdir"/run.log 2>&1 &
./result/bin/postgrest ${legacyConfig} > "$tmpdir"/run.log 2>&1 &
pid=$!
# shellcheck disable=SC2317
cleanup() {
@@ -381,7 +281,7 @@ in
buildToolbox
{
name = "postgrest-with";
tools = [ withPgAll withGit withPgrst withSlowPg withSlowPgrst ] ++ withPgVersions;
tools = [ withPgAll withGit withPgrst ] ++ withPgVersions;
# make withTools available for other nix files
extra = { inherit withGit withPg withPgAll withPgrst withSlowPg withSlowPgrst; };
extra = { inherit withGit withPg withPgAll withPgrst; };
}
+7 -12
View File
@@ -1,5 +1,5 @@
name: postgrest
version: 11.1.0
version: 10.2.0
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
@@ -34,8 +34,7 @@ library
default-extensions: OverloadedStrings
NoImplicitPrelude
hs-source-dirs: src
exposed-modules: PostgREST.Admin
PostgREST.App
exposed-modules: PostgREST.App
PostgREST.AppState
PostgREST.Auth
PostgREST.CLI
@@ -47,7 +46,7 @@ library
PostgREST.Cors
PostgREST.SchemaCache
PostgREST.SchemaCache.Identifiers
PostgREST.SchemaCache.Routine
PostgREST.SchemaCache.Proc
PostgREST.SchemaCache.Relationship
PostgREST.SchemaCache.Table
PostgREST.Error
@@ -61,7 +60,6 @@ library
PostgREST.Plan.CallPlan
PostgREST.Plan.MutatePlan
PostgREST.Plan.ReadPlan
PostgREST.Plan.Types
PostgREST.RangeQuery
PostgREST.ApiRequest
PostgREST.ApiRequest.Preferences
@@ -71,6 +69,7 @@ library
PostgREST.Response.OpenAPI
PostgREST.Response.GucHeader
PostgREST.Version
PostgREST.Workers
other-modules: Paths_postgrest
build-depends: base >= 4.9 && < 4.17
, HTTP >= 4000.3.7 && < 4000.5
@@ -86,13 +85,12 @@ library
, contravariant-extras >= 0.3.3 && < 0.4
, cookie >= 0.4.2 && < 0.5
, either >= 4.4.1 && < 5.1
, extra >= 1.7.0 && < 2.0
, fuzzyset >= 0.2.3
, gitrev >= 1.2 && < 1.4
, hasql >= 1.6.1.1 && < 1.7
, hasql-dynamic-statements >= 0.3.1 && < 0.4
, hasql-notifications >= 0.1 && < 0.3
, hasql-pool >= 0.10 && < 0.11
, hasql-pool >= 0.9 && < 0.10
, hasql-transaction >= 1.0.1 && < 1.1
, heredoc >= 0.2 && < 0.3
, http-types >= 0.12.2 && < 0.13
@@ -188,8 +186,6 @@ test-suite spec
Feature.CorsSpec
Feature.ExtraSearchPathSpec
Feature.LegacyGucsSpec
Feature.NoSuperuserSpec
Feature.ObservabilitySpec
Feature.OpenApi.DisabledOpenApiSpec
Feature.OpenApi.IgnorePrivOpenApiSpec
Feature.OpenApi.OpenApiSpec
@@ -214,16 +210,15 @@ test-suite spec
Feature.Query.QuerySpec
Feature.Query.RangeSpec
Feature.Query.RawOutputTypesSpec
Feature.Query.RelatedQueriesSpec
Feature.Query.RpcSpec
Feature.Query.SingularSpec
Feature.Query.SpreadQueriesSpec
Feature.Query.UnicodeSpec
Feature.Query.UpdateSpec
Feature.Query.UpsertSpec
Feature.RollbackSpec
Feature.RpcPreRequestGucsSpec
SpecHelper
TestTypes
build-depends: base >= 4.9 && < 4.17
, aeson >= 2.0.3 && < 2.2
, aeson-qq >= 0.8.1 && < 0.9
@@ -233,7 +228,7 @@ test-suite spec
, bytestring >= 0.10.8 && < 0.12
, case-insensitive >= 1.2 && < 1.3
, containers >= 0.5.7 && < 0.7
, hasql-pool >= 0.10 && < 0.11
, hasql-pool >= 0.9 && < 0.10
, hasql-transaction >= 1.0.1 && < 1.1
, heredoc >= 0.2 && < 0.3
, hspec >= 2.3 && < 2.10
-87
View File
@@ -1,87 +0,0 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
module PostgREST.Admin
( runAdmin
) where
import qualified Data.Text as T
import qualified Hasql.Session as SQL
import qualified Network.HTTP.Types.Status as HTTP
import qualified Network.Wai as Wai
import qualified Network.Wai.Handler.Warp as Warp
import Control.Monad.Extra (whenJust)
import Network.Socket
import Network.Socket.ByteString
import PostgREST.AppState (AppState)
import PostgREST.Config (AppConfig (..))
import qualified PostgREST.AppState as AppState
import Protolude
runAdmin :: AppConfig -> AppState -> Warp.Settings -> IO ()
runAdmin conf@AppConfig{configAdminServerPort} appState settings =
whenJust configAdminServerPort $ \adminPort -> do
AppState.logWithZTime appState $ "Admin server listening on port " <> show adminPort
void . forkIO $ Warp.runSettings (settings & Warp.setPort adminPort) adminApp
where
adminApp = admin appState conf
-- | PostgREST admin application
admin :: AppState.AppState -> AppConfig -> Wai.Application
admin appState appConfig req respond = do
isMainAppReachable <- any isRight <$> reachMainApp appConfig
isSchemaCacheLoaded <- isJust <$> AppState.getSchemaCache appState
isConnectionUp <-
if configDbChannelEnabled appConfig
then AppState.getIsListenerOn appState
else isRight <$> AppState.usePool appState (SQL.sql "SELECT 1")
case Wai.pathInfo req of
["ready"] ->
respond $ Wai.responseLBS (if isMainAppReachable && isConnectionUp && isSchemaCacheLoaded then HTTP.status200 else HTTP.status503) [] mempty
["live"] ->
respond $ Wai.responseLBS (if isMainAppReachable then HTTP.status200 else HTTP.status503) [] mempty
_ ->
respond $ Wai.responseLBS HTTP.status404 [] mempty
-- Try to connect to the main app socket
-- Note that it doesn't even send a valid HTTP request, we just want to check that the main app is accepting connections
-- The code for resolving the "*4", "!4", "*6", "!6", "*" special values is taken from
-- https://hackage.haskell.org/package/streaming-commons-0.2.2.4/docs/src/Data.Streaming.Network.html#bindPortGenEx
reachMainApp :: AppConfig -> IO [Either IOException ()]
reachMainApp AppConfig{..} =
case configServerUnixSocket of
Just path -> do
sock <- socket AF_UNIX Stream 0
(:[]) <$> try (do
connect sock $ SockAddrUnix path
withSocketsDo $ bracket (pure sock) close sendEmpty)
Nothing -> do
let
host | configServerHost `elem` ["*4", "!4", "*6", "!6", "*"] = Nothing
| otherwise = Just configServerHost
filterAddrs xs =
case configServerHost of
"*4" -> ipv4Addrs xs ++ ipv6Addrs xs
"!4" -> ipv4Addrs xs
"*6" -> ipv6Addrs xs ++ ipv4Addrs xs
"!6" -> ipv6Addrs xs
_ -> xs
ipv4Addrs = filter ((/=) AF_INET6 . addrFamily)
ipv6Addrs = filter ((==) AF_INET6 . addrFamily)
addrs <- getAddrInfo (Just $ defaultHints { addrSocketType = Stream }) (T.unpack <$> host) (Just . show $ configServerPort)
tryAddr `traverse` filterAddrs addrs
where
sendEmpty sock = void $ send sock mempty
tryAddr :: AddrInfo -> IO (Either IOException ())
tryAddr addr = do
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
try $ do
connect sock $ addrAddress addr
withSocketsDo $ bracket (pure sock) close sendEmpty
+265 -117
View File
@@ -3,7 +3,6 @@ Module : PostgREST.Request.ApiRequest
Description : PostgREST functions to translate HTTP request to a domain type called ApiRequest.
-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
@@ -33,22 +32,27 @@ import qualified Data.Set as S
import qualified Data.Text.Encoding as T
import qualified Data.Vector as V
import Data.Either.Combinators (mapBoth)
import Control.Arrow ((***))
import Data.Aeson.Types (emptyArray, emptyObject)
import Data.List (lookup, union)
import Data.Ranged.Ranges (emptyRange, rangeIntersection,
rangeIsEmpty)
import Data.Tree (Tree (..))
import Network.HTTP.Types.Header (RequestHeaders, hCookie)
import Network.HTTP.Types.URI (parseSimpleQuery)
import Network.Wai (Request (..))
import Network.Wai.Parse (parseHttpAccept)
import Web.Cookie (parseCookies)
import PostgREST.ApiRequest.Preferences (PreferCount (..),
PreferParameters (..),
PreferRepresentation (..),
PreferResolution (..),
PreferTransaction (..))
import PostgREST.ApiRequest.QueryParams (QueryParams (..))
import PostgREST.ApiRequest.Types (ApiRequestError (..),
RangeError (..))
RangeError (..),
SelectItem (..))
import PostgREST.Config (AppConfig (..),
OpenAPIMode (..))
import PostgREST.MediaType (MTPlanAttrs (..),
@@ -58,9 +62,13 @@ import PostgREST.RangeQuery (NonnegRange, allRange,
convertToLimitZeroRange,
hasLimitZero,
rangeRequested)
import PostgREST.SchemaCache (SchemaCache (..))
import PostgREST.SchemaCache.Identifiers (FieldName,
QualifiedIdentifier (..),
Schema)
import PostgREST.SchemaCache.Proc (ProcDescription (..),
ProcParam (..), ProcsMap,
procReturnsScalar)
import qualified PostgREST.ApiRequest.Preferences as Preferences
import qualified PostgREST.ApiRequest.QueryParams as QueryParams
@@ -82,7 +90,6 @@ data Payload
-- ^ Keys of the object or if it's an array these keys are guaranteed to
-- be the same across all its objects
}
| ProcessedUrlEncoded { payArray :: [(Text, Text)], payKeys :: S.Set Text }
| RawJSON { payRaw :: LBS.ByteString }
| RawPay { payRaw :: LBS.ByteString }
@@ -107,9 +114,41 @@ data PathInfo
}
-- | The target db object of a user action
data Target = TargetIdent QualifiedIdentifier
| TargetProc{tProc :: QualifiedIdentifier, tpIsRootSpec :: Bool}
| TargetProc{tProc :: ProcDescription, tpIsRootSpec :: Bool}
| TargetDefaultSpec{tdsSchema :: Schema} -- The default spec offered at root "/"
-- | RPC query param value `/rpc/func?v=<value>`, used for VARIADIC functions on form-urlencoded POST and GETs
-- | It can be fixed `?v=1` or repeated `?v=1&v=2&v=3.
data RpcParamValue = Fixed Text | Variadic [Text]
instance JSON.ToJSON RpcParamValue where
toJSON (Fixed v) = JSON.toJSON v
toJSON (Variadic v) = JSON.toJSON v
toRpcParamValue :: ProcDescription -> (Text, Text) -> (Text, RpcParamValue)
toRpcParamValue proc (k, v) | prmIsVariadic k = (k, Variadic [v])
| otherwise = (k, Fixed v)
where
prmIsVariadic prm = isJust $ find (\ProcParam{ppName, ppVar} -> ppName == prm && ppVar) $ pdParams proc
-- | Convert rpc params `/rpc/func?a=val1&b=val2` to json `{"a": "val1", "b": "val2"}
jsonRpcParams :: ProcDescription -> [(Text, Text)] -> Payload
jsonRpcParams proc prms =
if not $ pdHasVariadic proc then -- if proc has no variadic param, save steps and directly convert to json
ProcessedJSON (JSON.encode $ HM.fromList $ second JSON.toJSON <$> prms) (S.fromList $ fst <$> prms)
else
let paramsMap = HM.fromListWith mergeParams $ toRpcParamValue proc <$> prms in
ProcessedJSON (JSON.encode paramsMap) (S.fromList $ HM.keys paramsMap)
where
mergeParams :: RpcParamValue -> RpcParamValue -> RpcParamValue
mergeParams (Variadic a) (Variadic b) = Variadic $ b ++ a
mergeParams v _ = v -- repeated params for non-variadic parameters are not merged
targetToJsonRpcParams :: Maybe Target -> [(Text, Text)] -> Maybe Payload
targetToJsonRpcParams target params =
case target of
Just TargetProc{tProc} -> Just $ jsonRpcParams tProc params
_ -> Nothing
{-|
Describes what the user wants to do. This data type is a
translation of the raw elements of an HTTP request into domain
@@ -118,60 +157,37 @@ data Target = TargetIdent QualifiedIdentifier
if it is an action we are able to perform.
-}
data ApiRequest = ApiRequest {
iAction :: Action -- ^ Similar but not identical to HTTP method, e.g. Create/Invoke both POST
, iRange :: HM.HashMap Text NonnegRange -- ^ Requested range of rows within response
, iTopLevelRange :: NonnegRange -- ^ Requested range of rows from the top level
, iTarget :: Target -- ^ The target, be it calling a proc or accessing a table
, iPayload :: Maybe Payload -- ^ Data sent by client and used for mutation actions
, iPreferences :: Preferences.Preferences -- ^ Prefer header values
, iQueryParams :: QueryParams.QueryParams
, iColumns :: S.Set FieldName -- ^ parsed colums from &columns parameter and payload
, iHeaders :: [(ByteString, ByteString)] -- ^ HTTP request headers
, iCookies :: [(ByteString, ByteString)] -- ^ Request Cookies
, iPath :: ByteString -- ^ Raw request path
, iMethod :: ByteString -- ^ Raw request method
, iSchema :: Schema -- ^ The request schema. Can vary depending on profile headers.
, iNegotiatedByProfile :: Bool -- ^ If schema was was chosen according to the profile spec https://www.w3.org/TR/dx-prof-conneg/
, iAcceptMediaType :: MediaType -- ^ The media type in the Accept header
, iContentMediaType :: MediaType -- ^ The media type in the Content-Type header
iAction :: Action -- ^ Similar but not identical to HTTP method, e.g. Create/Invoke both POST
, iRange :: HM.HashMap Text NonnegRange -- ^ Requested range of rows within response
, iTopLevelRange :: NonnegRange -- ^ Requested range of rows from the top level
, iTarget :: Target -- ^ The target, be it calling a proc or accessing a table
, iPayload :: Maybe Payload -- ^ Data sent by client and used for mutation actions
, iPreferRepresentation :: PreferRepresentation -- ^ If client wants created items echoed back
, iPreferParameters :: Maybe PreferParameters -- ^ How to pass parameters to a stored procedure
, iPreferCount :: Maybe PreferCount -- ^ Whether the client wants a result count
, iPreferResolution :: Maybe PreferResolution -- ^ Whether the client wants to UPSERT or ignore records on PK conflict
, iPreferTransaction :: Maybe PreferTransaction -- ^ Whether the clients wants to commit or rollback the transaction
, iQueryParams :: QueryParams.QueryParams
, iColumns :: S.Set FieldName -- ^ parsed colums from &columns parameter and payload
, iHeaders :: [(ByteString, ByteString)] -- ^ HTTP request headers
, iCookies :: [(ByteString, ByteString)] -- ^ Request Cookies
, iPath :: ByteString -- ^ Raw request path
, iMethod :: ByteString -- ^ Raw request method
, iSchema :: Schema -- ^ The request schema. Can vary depending on profile headers.
, iNegotiatedByProfile :: Bool -- ^ If schema was was chosen according to the profile spec https://www.w3.org/TR/dx-prof-conneg/
, iAcceptMediaType :: MediaType -- ^ The media type in the Accept header
, iBinaryField :: Maybe FieldName -- ^ field used for raw output
}
-- | Examines HTTP request and translates it into user intent.
userApiRequest :: AppConfig -> Request -> RequestBody -> Either ApiRequestError ApiRequest
userApiRequest conf req reqBody = do
pInfo@PathInfo{..} <- getPathInfo conf $ pathInfo req
act <- getAction pInfo method
qPrms <- first QueryParamError $ QueryParams.parse (pathIsProc && act `elem` [ActionInvoke InvGet, ActionInvoke InvHead]) $ rawQueryString req
(acceptMediaType, contentMediaType) <- getMediaTypes conf hdrs act pInfo
(schema, negotiatedByProfile) <- getSchema conf hdrs method
(topLevelRange, ranges) <- getRanges method qPrms hdrs
(payload, columns) <- getPayload reqBody contentMediaType qPrms act pInfo
return $ ApiRequest {
iAction = act
, iTarget = if | pathIsProc -> TargetProc (QualifiedIdentifier schema pathName) pathIsRootSpec
| pathIsDefSpec -> TargetDefaultSpec schema
| otherwise -> TargetIdent $ QualifiedIdentifier schema pathName
, iRange = ranges
, iTopLevelRange = topLevelRange
, iPayload = payload
, iPreferences = Preferences.fromHeaders hdrs
, iQueryParams = qPrms
, iColumns = columns
, iHeaders = iHdrs
, iCookies = iCkies
, iPath = rawPathInfo req
, iMethod = method
, iSchema = schema
, iNegotiatedByProfile = negotiatedByProfile
, iAcceptMediaType = acceptMediaType
, iContentMediaType = contentMediaType
}
where
method = requestMethod req
hdrs = requestHeaders req
lookupHeader = flip lookup hdrs
iHdrs = [ (CI.foldedCase k, v) | (k,v) <- hdrs, k /= hCookie]
iCkies = maybe [] parseCookies $ lookupHeader "Cookie"
userApiRequest :: AppConfig -> SchemaCache -> Request -> RequestBody -> Either ApiRequestError ApiRequest
userApiRequest conf sCache req reqBody = do
qPrms <- first QueryParamError $ QueryParams.parse $ rawQueryString req
pInfo <- getPathInfo conf $ pathInfo req
act <- getAction pInfo $ requestMethod req
mediaTypes <- getMediaTypes conf (requestHeaders req) act pInfo
negotiatedSchema <- getSchema conf (requestHeaders req) (requestMethod req)
apiRequest conf sCache req reqBody qPrms pInfo act mediaTypes negotiatedSchema
getPathInfo :: AppConfig -> [Text] -> Either ApiRequestError PathInfo
getPathInfo AppConfig{configOpenApiMode, configDbRootSpec} path =
@@ -233,71 +249,114 @@ getSchema AppConfig{configDbSchemas} hdrs method = do
acceptProfile = T.decodeUtf8 <$> lookupHeader "Accept-Profile"
lookupHeader = flip lookup hdrs
getRanges :: ByteString -> QueryParams -> RequestHeaders -> Either ApiRequestError (NonnegRange, HM.HashMap Text NonnegRange)
getRanges method QueryParams{qsOrder,qsRanges} hdrs
apiRequest :: AppConfig -> SchemaCache -> Request -> RequestBody -> QueryParams.QueryParams -> PathInfo -> Action -> (MediaType, MediaType) -> (Schema, Bool) -> Either ApiRequestError ApiRequest
apiRequest conf sCache req reqBody queryparams@QueryParams{..} PathInfo{pathName, pathIsProc, pathIsRootSpec, pathIsDefSpec} action (acceptMediaType, contentMediaType) (schema, negotiatedByProfile)
| isInvalidRange = Left $ InvalidRange (if rangeIsEmpty headerRange then LowerGTUpper else NegativeLimit)
| shouldParsePayload && isLeft payload = either (Left . InvalidBody) witness payload
| not expectParams && not (L.null qsParams) = Left $ ParseRequestError "Unexpected param or filter missing operator" ("Failed to parse " <> show qsParams)
| method `elem` ["PATCH", "DELETE"] && not (null qsRanges) && null qsOrder = Left LimitNoOrderError
| method == "PUT" && topLevelRange /= allRange = Left PutLimitNotAllowedError
| otherwise = Right (topLevelRange, ranges)
where
-- According to the RFC (https://www.rfc-editor.org/rfc/rfc9110.html#name-range),
-- the Range header must be ignored for all methods other than GET
headerRange = if method == "GET" then rangeRequested hdrs else allRange
limitRange = fromMaybe allRange (HM.lookup "limit" qsRanges)
headerAndLimitRange = rangeIntersection headerRange limitRange
-- Bypass all the ranges and send only the limit zero range (0 <= x <= -1) if
-- limit=0 is present in the query params (not allowed for the Range header)
ranges = HM.insert "limit" (convertToLimitZeroRange limitRange headerAndLimitRange) qsRanges
-- The only emptyRange allowed is the limit zero range
isInvalidRange = topLevelRange == emptyRange && not (hasLimitZero limitRange)
topLevelRange = fromMaybe allRange $ HM.lookup "limit" ranges -- if no limit is specified, get all the request rows
| method == "PUT" && topLevelRange /= allRange = Left PutRangeNotAllowedError
| otherwise = do
checkedTarget <- target
bField <- binaryField conf acceptMediaType checkedTarget queryparams
return ApiRequest {
iAction = action
, iTarget = checkedTarget
, iRange = ranges
, iTopLevelRange = topLevelRange
, iPayload = relevantPayload
, iPreferRepresentation = fromMaybe None preferRepresentation
, iPreferParameters = preferParameters
, iPreferCount = preferCount
, iPreferResolution = preferResolution
, iPreferTransaction = preferTransaction
, iQueryParams = queryparams
, iColumns = payloadColumns
, iHeaders = [ (CI.foldedCase k, v) | (k,v) <- hdrs, k /= hCookie]
, iCookies = maybe [] parseCookies $ lookupHeader "Cookie"
, iPath = rawPathInfo req
, iMethod = method
, iSchema = schema
, iNegotiatedByProfile = negotiatedByProfile
, iAcceptMediaType = acceptMediaType
, iBinaryField = bField
}
where
expectParams = pathIsProc && method /= "POST"
getPayload :: RequestBody -> MediaType -> QueryParams.QueryParams -> Action -> PathInfo -> Either ApiRequestError (Maybe Payload, S.Set FieldName)
getPayload reqBody contentMediaType QueryParams{qsColumns} action PathInfo{pathIsProc}= do
checkedPayload <- if shouldParsePayload then payload else Right Nothing
let cols = case (checkedPayload, columns) of
(Just ProcessedJSON{payKeys}, _) -> payKeys
(Just ProcessedUrlEncoded{payKeys}, _) -> payKeys
(Just RawJSON{}, Just cls) -> cls
_ -> S.empty
return (checkedPayload, cols)
where
payload :: Either ApiRequestError (Maybe Payload)
payload = mapBoth InvalidBody Just $ case (contentMediaType, pathIsProc) of
(MTApplicationJSON, _) ->
if isJust columns
then Right $ RawJSON reqBody
else note "All object keys must match" . payloadAttributes reqBody
=<< if LBS.null reqBody && pathIsProc
then Right emptyObject
else first BS.pack $ JSON.eitherDecode reqBody
(MTTextCSV, _) -> do
json <- csvToJson <$> first BS.pack (CSV.decodeByName reqBody)
note "All lines must have same number of fields" $ payloadAttributes (JSON.encode json) json
(MTUrlEncoded, isProc) -> do
let params = (T.decodeUtf8 *** T.decodeUtf8) <$> parseSimpleQuery (LBS.toStrict reqBody)
if isProc
then Right $ ProcessedUrlEncoded params (S.fromList $ fst <$> params)
else
let paramsMap = HM.fromList $ (identity *** JSON.String) <$> params in
Right $ ProcessedJSON (JSON.encode paramsMap) $ S.fromList (HM.keys paramsMap)
(MTTextPlain, True) -> Right $ RawPay reqBody
(MTTextXML, True) -> Right $ RawPay reqBody
(MTOctetStream, True) -> Right $ RawPay reqBody
(ct, _) -> Left $ "Content-Type not acceptable: " <> MediaType.toMime ct
columns = case action of
ActionMutate MutationCreate -> qsColumns
ActionMutate MutationUpdate -> qsColumns
ActionInvoke InvPost -> qsColumns
_ -> Nothing
shouldParsePayload = case (action, contentMediaType) of
(ActionMutate MutationCreate, _) -> True
(ActionInvoke InvPost, _) -> True
(ActionMutate MutationSingleUpsert, _) -> True
(ActionMutate MutationUpdate, _) -> True
_ -> False
payloadColumns =
case (contentMediaType, action) of
(_, ActionInvoke InvGet) -> S.fromList $ fst <$> qsParams
(_, ActionInvoke InvHead) -> S.fromList $ fst <$> qsParams
(MTUrlEncoded, _) -> S.fromList $ map (T.decodeUtf8 . fst) $ parseSimpleQuery $ LBS.toStrict reqBody
_ -> case (relevantPayload, columns) of
(Just ProcessedJSON{payKeys}, _) -> payKeys
(Just RawJSON{}, Just cls) -> cls
_ -> S.empty
payload :: Either ByteString Payload
payload = case (contentMediaType, pathIsProc) of
(MTApplicationJSON, _) ->
if isJust columns
then Right $ RawJSON reqBody
else note "All object keys must match" . payloadAttributes reqBody
=<< if LBS.null reqBody && pathIsProc
then Right emptyObject
else first BS.pack $ JSON.eitherDecode reqBody
(MTTextCSV, _) -> do
json <- csvToJson <$> first BS.pack (CSV.decodeByName reqBody)
note "All lines must have same number of fields" $ payloadAttributes (JSON.encode json) json
(MTUrlEncoded, _) ->
let paramsMap = HM.fromList $ (T.decodeUtf8 *** JSON.String . T.decodeUtf8) <$> parseSimpleQuery (LBS.toStrict reqBody) in
Right $ ProcessedJSON (JSON.encode paramsMap) $ S.fromList (HM.keys paramsMap)
(MTTextPlain, True) -> Right $ RawPay reqBody
(MTTextXML, True) -> Right $ RawPay reqBody
(MTOctetStream, True) -> Right $ RawPay reqBody
(ct, _) -> Left $ "Content-Type not acceptable: " <> MediaType.toMime ct
topLevelRange = fromMaybe allRange $ HM.lookup "limit" ranges -- if no limit is specified, get all the request rows
columns = case action of
ActionMutate MutationCreate -> qsColumns
ActionMutate MutationUpdate -> qsColumns
ActionInvoke InvPost -> qsColumns
_ -> Nothing
target
| pathIsProc = (`TargetProc` pathIsRootSpec) <$> callFindProc schema pathName
| pathIsDefSpec = Right $ TargetDefaultSpec schema
| otherwise = Right $ TargetIdent $ QualifiedIdentifier schema pathName
where
callFindProc procSch procNam = findProc
(QualifiedIdentifier procSch procNam) payloadColumns (preferParameters == Just SingleObject) (dbProcs sCache)
contentMediaType (action == ActionInvoke InvPost)
shouldParsePayload = case (action, contentMediaType) of
(ActionMutate MutationCreate, _) -> True
(ActionInvoke InvPost, MTUrlEncoded) -> False
(ActionInvoke InvPost, _) -> True
(ActionMutate MutationSingleUpsert, _) -> True
(ActionMutate MutationUpdate, _) -> True
_ -> False
relevantPayload = case (contentMediaType, action) of
-- Though ActionInvoke GET/HEAD doesn't really have a payload, we use the payload variable as a way
-- to store the query string arguments to the function.
(_, ActionInvoke InvGet) -> targetToJsonRpcParams (rightToMaybe target) qsParams
(_, ActionInvoke InvHead) -> targetToJsonRpcParams (rightToMaybe target) qsParams
(MTUrlEncoded, ActionInvoke InvPost) -> targetToJsonRpcParams (rightToMaybe target) $ (T.decodeUtf8 *** T.decodeUtf8) <$> parseSimpleQuery (LBS.toStrict reqBody)
_ | shouldParsePayload -> rightToMaybe payload
| otherwise -> Nothing
method = requestMethod req
hdrs = requestHeaders req
lookupHeader = flip lookup hdrs
Preferences.Preferences{..} = Preferences.fromHeaders hdrs
headerRange = rangeRequested hdrs
limitRange = fromMaybe allRange (HM.lookup "limit" qsRanges)
headerAndLimitRange = rangeIntersection headerRange limitRange
-- Bypass all the ranges and send only the limit zero range (0 <= x <= -1) if
-- limit=0 is present in the query params (not allowed for the Range header)
ranges = HM.insert "limit" (convertToLimitZeroRange limitRange headerAndLimitRange) qsRanges
-- The only emptyRange allowed is the limit zero range
isInvalidRange = topLevelRange == emptyRange && not (hasLimitZero limitRange)
{-|
Find the best match from a list of media types accepted by the
@@ -386,3 +445,92 @@ requestMediaTypes conf action path =
[MTApplicationJSON, MTSingularJSON, MTGeoJSON, MTTextCSV] ++
[MTPlan $ MTPlanAttrs Nothing PlanJSON mempty | configDbPlanEnabled conf]
rawMediaTypes = configRawMediaTypes conf `union` [MTOctetStream, MTTextPlain, MTTextXML]
{-|
Search a pg proc by matching name and arguments keys to parameters. Since a function can be overloaded,
the name is not enough to find it. An overloaded function can have a different volatility or even a different return type.
-}
findProc :: QualifiedIdentifier -> S.Set Text -> Bool -> ProcsMap -> MediaType -> Bool -> Either ApiRequestError ProcDescription
findProc qi argumentsKeys paramsAsSingleObject allProcs contentMediaType isInvPost =
case matchProc of
([], []) -> Left $ NoRpc (qiSchema qi) (qiName qi) (S.toList argumentsKeys) paramsAsSingleObject contentMediaType isInvPost (HM.keys allProcs) lookupProcName
-- If there are no functions with named arguments, fallback to the single unnamed argument function
([], [proc]) -> Right proc
([], procs) -> Left $ AmbiguousRpc (toList procs)
-- Matches the functions with named arguments
([proc], _) -> Right proc
(procs, _) -> Left $ AmbiguousRpc (toList procs)
where
matchProc = overloadedProcPartition lookupProcName
-- First find the proc by name
lookupProcName = HM.lookupDefault mempty qi allProcs
-- The partition obtained has the form (overloadedProcs,fallbackProcs)
-- where fallbackProcs are functions with a single unnamed parameter
overloadedProcPartition = foldr select ([],[])
select proc ~(ts,fs)
| matchesParams proc = (proc:ts,fs)
| hasSingleUnnamedParam proc = (ts,proc:fs)
| otherwise = (ts,fs)
-- If the function is called with post and has a single unnamed parameter
-- it can be called depending on content type and the parameter type
hasSingleUnnamedParam ProcDescription{pdParams=[ProcParam{ppType}]} = isInvPost && case (contentMediaType, ppType) of
(MTApplicationJSON, "json") -> True
(MTApplicationJSON, "jsonb") -> True
(MTTextPlain, "text") -> True
(MTTextXML, "xml") -> True
(MTOctetStream, "bytea") -> True
_ -> False
hasSingleUnnamedParam _ = False
matchesParams proc =
let
params = pdParams proc
firstType = (ppType <$> headMay params)
in
-- exceptional case for Prefer: params=single-object
if paramsAsSingleObject
then length params == 1 && (firstType == Just "json" || firstType == Just "jsonb")
-- If the function has no parameters, the arguments keys must be empty as well
else if null params
then null argumentsKeys && not (isInvPost && contentMediaType `elem` [MTOctetStream, MTTextPlain, MTTextXML])
-- A function has optional and required parameters. Optional parameters have a default value and
-- don't require arguments for the function to be executed, required parameters must have an argument present.
else case L.partition ppReq params of
-- If the function only has required parameters, the arguments keys must match those parameters
(reqParams, []) -> argumentsKeys == S.fromList (ppName <$> reqParams)
-- If the function only has optional parameters, the arguments keys can match none or any of them(a subset)
([], optParams) -> argumentsKeys `S.isSubsetOf` S.fromList (ppName <$> optParams)
-- If the function has required and optional parameters, the arguments keys have to match the required parameters
-- and can match any or none of the default parameters.
(reqParams, optParams) -> argumentsKeys `S.difference` S.fromList (ppName <$> optParams) == S.fromList (ppName <$> reqParams)
-- | If raw(binary) output is requested, check that MediaType is one of the
-- admitted rawMediaTypes and that`?select=...` contains only one field other
-- than `*`
binaryField :: AppConfig -> MediaType -> Target -> QueryParams -> Either ApiRequestError (Maybe FieldName)
binaryField AppConfig{configRawMediaTypes} acceptMediaType target QueryParams{qsSelect}
| returnsScalar target && isRawMediaType =
Right $ Just "pgrst_scalar"
| isRawMediaType =
let
fieldName = fstFieldName qsSelect
in
case fieldName of
Just fld -> Right $ Just fld
Nothing -> Left $ BinaryFieldError acceptMediaType
| otherwise =
Right Nothing
where
isRawMediaType = acceptMediaType `elem` configRawMediaTypes `union` [MTOctetStream, MTTextPlain, MTTextXML] || isRawPlan acceptMediaType
isRawPlan mt = case mt of
MTPlan (MTPlanAttrs (Just MTOctetStream) _ _) -> True
MTPlan (MTPlanAttrs (Just MTTextPlain) _ _) -> True
MTPlan (MTPlanAttrs (Just MTTextXML) _ _) -> True
_ -> False
returnsScalar :: Target -> Bool
returnsScalar (TargetProc proc _) = procReturnsScalar proc
returnsScalar _ = False
fstFieldName :: [Tree SelectItem] -> Maybe FieldName
fstFieldName [Node SelectField{selField=("*", _)} []] = Nothing
fstFieldName [Node SelectField{selField=(fld, _)} []] = Just fld
fstFieldName _ = Nothing
+11 -29
View File
@@ -9,7 +9,6 @@
module PostgREST.ApiRequest.Preferences
( Preferences(..)
, PreferCount(..)
, PreferMissing(..)
, PreferParameters(..)
, PreferRepresentation(..)
, PreferResolution(..)
@@ -34,18 +33,16 @@ import Protolude
-- >>> deriving instance Show PreferParameters
-- >>> deriving instance Show PreferCount
-- >>> deriving instance Show PreferTransaction
-- >>> deriving instance Show PreferMissing
-- >>> deriving instance Show Preferences
-- | Preferences recognized by the application.
data Preferences
= Preferences
{ preferResolution :: Maybe PreferResolution
, preferRepresentation :: PreferRepresentation
, preferRepresentation :: Maybe PreferRepresentation
, preferParameters :: Maybe PreferParameters
, preferCount :: Maybe PreferCount
, preferTransaction :: Maybe PreferTransaction
, preferMissing :: Maybe PreferMissing
}
-- |
@@ -56,23 +53,21 @@ data Preferences
-- >>> pPrint $ fromHeaders [("Prefer", "resolution=ignore-duplicates, count=exact")]
-- Preferences
-- { preferResolution = Just IgnoreDuplicates
-- , preferRepresentation = None
-- , preferRepresentation = Nothing
-- , preferParameters = Nothing
-- , preferCount = Just ExactCount
-- , preferTransaction = Nothing
-- , preferMissing = Nothing
-- }
--
-- Multiple headers can also be used:
--
-- >>> pPrint $ fromHeaders [("Prefer", "resolution=ignore-duplicates"), ("Prefer", "count=exact"), ("Prefer", "missing=null")]
-- >>> pPrint $ fromHeaders [("Prefer", "resolution=ignore-duplicates"), ("Prefer", "count=exact")]
-- Preferences
-- { preferResolution = Just IgnoreDuplicates
-- , preferRepresentation = None
-- , preferRepresentation = Nothing
-- , preferParameters = Nothing
-- , preferCount = Just ExactCount
-- , preferTransaction = Nothing
-- , preferMissing = Just ApplyNulls
-- }
--
-- If a preference is set more than once, only the first is used:
@@ -97,25 +92,23 @@ data Preferences
--
-- Preferences can be separated by arbitrary amounts of space, lower-case header is also recognized:
--
-- >>> pPrint $ fromHeaders [("prefer", "count=exact, tx=commit ,return=representation , missing=default")]
-- >>> pPrint $ fromHeaders [("prefer", "count=exact, tx=commit ,return=minimal")]
-- Preferences
-- { preferResolution = Nothing
-- , preferRepresentation = Full
-- , preferRepresentation = Just None
-- , preferParameters = Nothing
-- , preferCount = Just ExactCount
-- , preferTransaction = Just Commit
-- , preferMissing = Just ApplyDefaults
-- }
--
fromHeaders :: [HTTP.Header] -> Preferences
fromHeaders headers =
Preferences
{ preferResolution = parsePrefs [MergeDuplicates, IgnoreDuplicates]
, preferRepresentation = fromMaybe None $ parsePrefs [Full, None, HeadersOnly]
, preferParameters = parsePrefs [SingleObject]
, preferRepresentation = parsePrefs [Full, None, HeadersOnly]
, preferParameters = parsePrefs [SingleObject, MultipleObjects]
, preferCount = parsePrefs [ExactCount, PlannedCount, EstimatedCount]
, preferTransaction = parsePrefs [Commit, Rollback]
, preferMissing = parsePrefs [ApplyDefaults, ApplyNulls]
}
where
prefHeaders = filter ((==) HTTP.hPrefer . fst) headers
@@ -176,10 +169,13 @@ instance ToHeaderValue PreferRepresentation where
-- | How to pass parameters to stored procedures.
data PreferParameters
= SingleObject -- ^ Pass all parameters as a single json object to a stored procedure.
| MultipleObjects -- ^ Pass an array of json objects as params to a stored procedure.
deriving Eq
-- TODO: Deprecate params=multiple-objects in next major version
instance ToHeaderValue PreferParameters where
toHeaderValue SingleObject = "params=single-object"
toHeaderValue MultipleObjects = "params=multiple-objects"
-- | How to determine the count of (expected) results
data PreferCount
@@ -208,17 +204,3 @@ instance ToHeaderValue PreferTransaction where
toHeaderValue Rollback = "tx=rollback"
instance ToAppliedHeader PreferTransaction
-- |
-- How to handle the insertion/update when the keys specified in ?columns are not present
-- in the json body.
data PreferMissing
= ApplyDefaults -- ^ Use the default column value for missing values.
| ApplyNulls -- ^ Use the null value for missing values.
deriving Eq
instance ToHeaderValue PreferMissing where
toHeaderValue ApplyDefaults = "missing=default"
toHeaderValue ApplyNulls = "missing=null"
instance ToAppliedHeader PreferMissing

Some files were not shown because too many files have changed in this diff Show More