mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-13 19:33:55 +03:00
server: case insensitive lookup in session variable
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3663 GitOrigin-RevId: b36666d8849a23dad209f9921f140390c2b57496
This commit is contained in:
parent
6c2c46e94e
commit
bc74046ab2
@ -5,6 +5,7 @@
|
||||
### Bug fixes and improvements
|
||||
(Add entries below in the order of server, console, cli, docs, others)
|
||||
|
||||
- server: add custom function for case insensitive lookup in session variable in request transformation
|
||||
- server: Webhook Transforms can now delete request/response bodies explicitly.
|
||||
- server: Fix truncation of session variables with variable length column types in MSSQL (#8158)
|
||||
- server: improve baseline memory consumption for typical workloads
|
||||
|
@ -45,7 +45,7 @@ package graphql-engine
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/hasura/kriti-lang.git
|
||||
tag: 01930d88da1a95eee1e4d5e2a1ba78752548e599
|
||||
tag: v0.3.1
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
@ -208,7 +208,7 @@ constraints: any.Cabal ==3.2.1.0,
|
||||
jose -demos,
|
||||
any.kan-extensions ==5.2.3,
|
||||
any.keys ==3.12.3,
|
||||
any.kriti-lang ==0.3.0,
|
||||
any.kriti-lang ==0.3.1,
|
||||
any.lens ==5.1,
|
||||
lens -benchmark-uniplate -dump-splices +inlining -j +test-hunit +test-properties +test-templates +trustworthy,
|
||||
any.lens-aeson ==1.1.3,
|
||||
|
@ -2075,6 +2075,35 @@ RequestTransformation
|
||||
- :ref:`TemplateEngine`
|
||||
- Template language to be used for this transformation. Default: "Kriti"
|
||||
|
||||
.. note::
|
||||
|
||||
HGE provides the following functions that can be used in the template:
|
||||
|
||||
- ``not``: This function takes a boolean and returns its negation.
|
||||
|
||||
eg::
|
||||
|
||||
> {{not true}}
|
||||
false
|
||||
|
||||
- ``escapeUri``: This function takes a string and escapes it as per URI specification.
|
||||
|
||||
eg::
|
||||
|
||||
> {{ escapeUri "?foo=bar/baz" }}
|
||||
"%3Ffoo%3Dbar%2Fbaz"
|
||||
|
||||
|
||||
- ``getSessionVariable``: This function takes a string and returns the session variable of the given name. This function can throw the following errors:
|
||||
|
||||
- Session variable {variable name} not found
|
||||
- Session variable name should be a string
|
||||
|
||||
eg::
|
||||
|
||||
> {{getSessionVariable "myVariableName"}}
|
||||
"myVariableValue"
|
||||
|
||||
.. _TransformHeaders:
|
||||
|
||||
TransformHeaders
|
||||
|
@ -37,9 +37,9 @@ import Data.Text.Encoding qualified as TE
|
||||
import Data.Validation qualified as V
|
||||
import Hasura.Incremental (Cacheable)
|
||||
import Hasura.Prelude hiding (first)
|
||||
import Hasura.Session (SessionVariables)
|
||||
import Kriti (SerializedError (..), runKriti)
|
||||
import Kriti.Error (serialize)
|
||||
import Hasura.Session (SessionVariables, getSessionVariableValue, mkSessionVariable)
|
||||
import Kriti (SerializedError (..), runKriti, runKritiWith)
|
||||
import Kriti.Error (CustomFunctionError (..), serialize)
|
||||
import Kriti.Parser (parser)
|
||||
import Network.HTTP.Client.Transformable qualified as HTTP
|
||||
import Network.URI qualified as URI
|
||||
@ -73,7 +73,8 @@ data ReqTransformCtx = ReqTransformCtx
|
||||
{ tcUrl :: Maybe J.Value,
|
||||
tcBody :: J.Value,
|
||||
tcSessionVars :: J.Value,
|
||||
tcQueryParams :: Maybe J.Value
|
||||
tcQueryParams :: Maybe J.Value,
|
||||
tcFunctions :: M.HashMap T.Text (J.Value -> Either CustomFunctionError J.Value)
|
||||
}
|
||||
|
||||
instance J.ToJSON ReqTransformCtx where
|
||||
@ -441,7 +442,7 @@ mkReqTemplateTransform :: TemplatingEngine -> TemplateText -> ReqTransformCtx ->
|
||||
mkReqTemplateTransform engine (TemplateText template) ReqTransformCtx {..} =
|
||||
let context = [("$body", tcBody), ("$session_variables", tcSessionVars)] <> catMaybes [("$query_params",) <$> tcQueryParams, ("$base_url",) <$> tcUrl]
|
||||
in case engine of
|
||||
Kriti -> first (TransformErrorBundle . pure . J.toJSON . serialize) $ runKriti template context
|
||||
Kriti -> first (TransformErrorBundle . pure . J.toJSON . serialize) $ runKritiWith (template) context tcFunctions
|
||||
|
||||
-- | Construct a Template Transformation function for Responses
|
||||
mkRespTemplateTransform :: TemplatingEngine -> TemplateText -> RespTransformCtx -> Either TransformErrorBundle J.Value
|
||||
@ -456,8 +457,19 @@ buildReqTransformCtx url sessionVars reqData =
|
||||
{ tcUrl = Just $ J.toJSON url,
|
||||
tcBody = fromMaybe J.Null $ J.decode @J.Value =<< view HTTP.body reqData,
|
||||
tcSessionVars = J.toJSON sessionVars,
|
||||
tcQueryParams = Just $ J.toJSON $ bimap TE.decodeUtf8 (fmap TE.decodeUtf8) <$> view HTTP.queryParams reqData
|
||||
tcQueryParams = Just $ J.toJSON $ bimap TE.decodeUtf8 (fmap TE.decodeUtf8) <$> view HTTP.queryParams reqData,
|
||||
tcFunctions = M.singleton "getSessionVariable" getSessionVar
|
||||
}
|
||||
where
|
||||
getSessionVar :: J.Value -> Either CustomFunctionError J.Value
|
||||
getSessionVar inp = case inp of
|
||||
J.String txt ->
|
||||
case sessionVarValue of
|
||||
Just x -> Right $ J.String x
|
||||
Nothing -> Left . CustomFunctionError $ "Session variable \"" <> txt <> "\" not found"
|
||||
where
|
||||
sessionVarValue = sessionVars >>= getSessionVariableValue (mkSessionVariable txt)
|
||||
_ -> Left $ CustomFunctionError "Session variable name should be a string"
|
||||
|
||||
buildRespTransformCtx :: ReqTransformCtx -> BL.ByteString -> RespTransformCtx
|
||||
buildRespTransformCtx reqCtx respBody =
|
||||
|
@ -0,0 +1,79 @@
|
||||
- description: Test Webhook Transform getSessionVariable function | success
|
||||
url: /v1/metadata
|
||||
headers:
|
||||
X-Hasura-Role: admin
|
||||
status: 200
|
||||
response:
|
||||
body: some value
|
||||
headers: []
|
||||
method: GET
|
||||
webhook_url: http://localhost:1234/
|
||||
query:
|
||||
type: test_webhook_transform
|
||||
args:
|
||||
webhook_url: http://localhost:1234
|
||||
body:
|
||||
hello: world
|
||||
session_variables:
|
||||
myVariable: some value
|
||||
request_transform:
|
||||
body: '{{ getSessionVariable "myVariable" }}'
|
||||
template_engine: Kriti
|
||||
|
||||
- description: Test Webhook Transform getSessionVariable function | non existant session variable
|
||||
url: /v1/metadata
|
||||
headers:
|
||||
X-Hasura-Role: admin
|
||||
status: 200
|
||||
response:
|
||||
body:
|
||||
- error_code: Function Error
|
||||
source_position:
|
||||
end_column: 51
|
||||
start_line: 0
|
||||
end_line: 0
|
||||
start_column: 23
|
||||
message: Session variable "this_variable_doesnt_exist" not found
|
||||
headers: []
|
||||
method: GET
|
||||
webhook_url: http://localhost:1234/
|
||||
query:
|
||||
type: test_webhook_transform
|
||||
args:
|
||||
webhook_url: http://localhost:1234
|
||||
body:
|
||||
hello: world
|
||||
session_variables:
|
||||
myVariable: some value
|
||||
request_transform:
|
||||
body: '{{ getSessionVariable "this_variable_doesnt_exist" }}'
|
||||
template_engine: Kriti
|
||||
|
||||
- description: Test Webhook Transform function | wrong function name
|
||||
url: /v1/metadata
|
||||
headers:
|
||||
X-Hasura-Role: admin
|
||||
status: 200
|
||||
response:
|
||||
body:
|
||||
- error_code: Function Error
|
||||
source_position:
|
||||
end_column: 15
|
||||
start_line: 0
|
||||
end_line: 0
|
||||
start_column: 4
|
||||
message: Function fooFunction is not defined.
|
||||
headers: []
|
||||
method: GET
|
||||
webhook_url: http://localhost:1234/
|
||||
query:
|
||||
type: test_webhook_transform
|
||||
args:
|
||||
webhook_url: http://localhost:1234
|
||||
body:
|
||||
hello: world
|
||||
session_variables:
|
||||
myVariable: some value
|
||||
request_transform:
|
||||
body: '{{ fooFunction "myVariable" }}'
|
||||
template_engine: Kriti
|
@ -238,6 +238,9 @@ class TestMetadata:
|
||||
def test_webhook_transform_bad_eval(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/test_webhook_transform_bad_eval.yaml')
|
||||
|
||||
def test_webhook_transform_custom_functions(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/test_webhook_transform_custom_functions.yaml')
|
||||
|
||||
@pytest.mark.skipif(
|
||||
os.getenv('HASURA_GRAPHQL_PG_SOURCE_URL_1') == os.getenv('HASURA_GRAPHQL_PG_SOURCE_URL_2') or
|
||||
os.getenv('HASURA_GRAPHQL_PG_SOURCE_URL_1') is None or
|
||||
|
Loading…
Reference in New Issue
Block a user