From 73d335e976494cb96d7af197130248c3487f973b Mon Sep 17 00:00:00 2001 From: Joel Jakobsson Date: Mon, 7 Jul 2025 17:26:51 +0200 Subject: [PATCH] fix(openapi): respect function volatility for GET methods The OpenAPI specification was incorrectly exposing GET methods for VOLATILE functions, even though such functions properly reject GET requests at runtime with "405 Method Not Allowed". This created a mismatch between the advertised API specification and the actual runtime behavior. VOLATILE functions should only be callable via POST since they may have side effects, while STABLE and IMMUTABLE functions can safely be called via GET since they don't modify database state. Fix by checking the pdVolatility field in makeProcPathItem() and only including GET methods in the OpenAPI PathItem for non-volatile functions. The runtime behavior was already correct; this fixes only the OpenAPI documentation generation. --- CHANGELOG.md | 1 + src/PostgREST/Response/OpenAPI.hs | 9 ++++---- test/spec/Feature/OpenApi/OpenApiSpec.hs | 27 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ec8188a7..3f62b756f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix OpenAPI broken docs link by @taimoorzaeem in #4048 +- Fix OpenAPI specification incorrectly exposing GET methods for volatile functions by @joelonsql in #4174 ## [13.0.4] - 2025-06-17 diff --git a/src/PostgREST/Response/OpenAPI.hs b/src/PostgREST/Response/OpenAPI.hs index fe40e3c0f..9ca526932 100644 --- a/src/PostgREST/Response/OpenAPI.hs +++ b/src/PostgREST/Response/OpenAPI.hs @@ -30,7 +30,8 @@ import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) import PostgREST.SchemaCache.Relationship (Cardinality (..), Relationship (..), RelationshipsMap) -import PostgREST.SchemaCache.Routine (Routine (..), +import PostgREST.SchemaCache.Routine (FuncVolatility (..), + Routine (..), RoutineParam (..)) import PostgREST.SchemaCache.Table (Column (..), Table (..), TablesMap, @@ -355,9 +356,9 @@ makeProcPathItem pd = ("/rpc/" ++ toS (pdName pd), pe) & parameters .~ makeProcGetParams (pdParams pd) postOp = procOp & parameters .~ makeProcPostParams pd - pe = (mempty :: PathItem) - & get ?~ getOp - & post ?~ postOp + pe = case pdVolatility pd of + Volatile -> (mempty :: PathItem) & post ?~ postOp + _ -> (mempty :: PathItem) & get ?~ getOp & post ?~ postOp makeRootPathItem :: (FilePath, PathItem) makeRootPathItem = ("/", p) diff --git a/test/spec/Feature/OpenApi/OpenApiSpec.hs b/test/spec/Feature/OpenApi/OpenApiSpec.hs index fbe227a32..c035bbe7b 100644 --- a/test/spec/Feature/OpenApi/OpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/OpenApiSpec.hs @@ -1058,6 +1058,33 @@ spec = describe "OpenAPI" $ do } |] + it "only includes POST method for volatile functions" $ do + r <- simpleBody <$> get "/" + let volatileGet = r ^? key "paths" . key "/rpc/reset_table" . key "get" + volatilePost = r ^? key "paths" . key "/rpc/reset_table" . key "post" + + liftIO $ do + volatileGet `shouldBe` Nothing + volatilePost `shouldNotBe` Nothing + + it "includes GET and POST methods for stable functions" $ do + r <- simpleBody <$> get "/" + let stableGet = r ^? key "paths" . key "/rpc/getallusers" . key "get" + stablePost = r ^? key "paths" . key "/rpc/getallusers" . key "post" + + liftIO $ do + stableGet `shouldNotBe` Nothing + stablePost `shouldNotBe` Nothing + + it "includes GET and POST methods for immutable functions" $ do + r <- simpleBody <$> get "/" + let immutableGet = r ^? key "paths" . key "/rpc/jwt_test" . key "get" + immutablePost = r ^? key "paths" . key "/rpc/jwt_test" . key "post" + + liftIO $ do + immutableGet `shouldNotBe` Nothing + immutablePost `shouldNotBe` Nothing + describe "Security" $ it "does not include security or security definitions by default" $ do r <- simpleBody <$> get "/"