From a67c14c3688f145fce48a2ba2f3da3f3140cd290 Mon Sep 17 00:00:00 2001
From: Gani Georgiev
Date: Thu, 2 Mar 2023 18:56:18 +0200
Subject: [PATCH] added support for @request.headers.*
---
apis/record_helpers.go | 15 ++++++++++++---
apis/record_helpers_test.go | 7 +++++++
models/request_data.go | 11 ++++++-----
resolvers/record_field_resolver.go | 3 +++
resolvers/record_field_resolver_test.go | 11 +++++++++++
.../base/FilterAutocompleteInput.svelte | 1 +
.../collections/CollectionRulesTab.svelte | 2 +-
7 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/apis/record_helpers.go b/apis/record_helpers.go
index 96e7de31..d8e9ad75 100644
--- a/apis/record_helpers.go
+++ b/apis/record_helpers.go
@@ -30,9 +30,18 @@ func RequestData(c echo.Context) *models.RequestData {
}
result := &models.RequestData{
- Method: c.Request().Method,
- Query: map[string]any{},
- Data: map[string]any{},
+ Method: c.Request().Method,
+ Query: map[string]any{},
+ Data: map[string]any{},
+ Headers: map[string]string{},
+ }
+
+ // extract the first value of all headers and normalizes the keys
+ // ("X-Token" is converted to "x_token")
+ for k, v := range c.Request().Header {
+ if len(v) > 0 {
+ result.Headers[strings.ToLower(strings.ReplaceAll(k, "-", "_"))] = v[0]
+ }
}
result.AuthRecord, _ = c.Get(ContextAuthRecordKey).(*models.Record)
diff --git a/apis/record_helpers_test.go b/apis/record_helpers_test.go
index 7f96c2ff..765182ce 100644
--- a/apis/record_helpers_test.go
+++ b/apis/record_helpers_test.go
@@ -17,6 +17,7 @@ func TestRequestData(t *testing.T) {
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/?test=123", strings.NewReader(`{"test":456}`))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
+ req.Header.Set("X-Token-Test", "123")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
@@ -38,6 +39,12 @@ func TestRequestData(t *testing.T) {
t.Fatalf("Expected Method %v, got %v", http.MethodPost, result.Method)
}
+ rawHeaders, _ := json.Marshal(result.Headers)
+ expectedHeaders := `{"content_type":"application/json","x_token_test":"123"}`
+ if v := string(rawHeaders); v != expectedHeaders {
+ t.Fatalf("Expected Query %v, got %v", expectedHeaders, v)
+ }
+
rawQuery, _ := json.Marshal(result.Query)
expectedQuery := `{"test":"123"}`
if v := string(rawQuery); v != expectedQuery {
diff --git a/models/request_data.go b/models/request_data.go
index 693795c3..e574c0c7 100644
--- a/models/request_data.go
+++ b/models/request_data.go
@@ -9,11 +9,12 @@ import (
// RequestData defines a HTTP request data struct, usually used
// as part of the `@request.*` filter resolver.
type RequestData struct {
- Method string `json:"method"`
- Query map[string]any `json:"query"`
- Data map[string]any `json:"data"`
- AuthRecord *Record `json:"authRecord"`
- Admin *Admin `json:"admin"`
+ Method string `json:"method"`
+ Query map[string]any `json:"query"`
+ Data map[string]any `json:"data"`
+ Headers map[string]string `json:"headers"`
+ AuthRecord *Record `json:"authRecord"`
+ Admin *Admin `json:"admin"`
}
// HasModifierDataKeys loosely checks if the current struct has any modifier Data keys.
diff --git a/resolvers/record_field_resolver.go b/resolvers/record_field_resolver.go
index 220abbfe..9bd18af2 100644
--- a/resolvers/record_field_resolver.go
+++ b/resolvers/record_field_resolver.go
@@ -84,6 +84,7 @@ func NewRecordFieldResolver(
`^\@request\.auth\.[\w\.\:]*\w+$`,
`^\@request\.data\.[\w\.\:]*\w+$`,
`^\@request\.query\.[\w\.\:]*\w+$`,
+ `^\@request\.headers\.\w+$`,
`^\@collection\.\w+\.[\w\.\:]*\w+$`,
},
}
@@ -92,6 +93,7 @@ func NewRecordFieldResolver(
if r.requestData != nil {
r.staticRequestData["method"] = r.requestData.Method
r.staticRequestData["query"] = r.requestData.Query
+ r.staticRequestData["headers"] = r.requestData.Headers
r.staticRequestData["data"] = r.requestData.Data
r.staticRequestData["auth"] = nil
if r.requestData.AuthRecord != nil {
@@ -132,6 +134,7 @@ func (r *RecordFieldResolver) UpdateQuery(query *dbx.SelectQuery) error {
// project.screen.status
// @request.status
// @request.query.filter
+// @request.headers.x_token
// @request.auth.someRelation.name
// @request.data.someRelation.name
// @request.data.someField
diff --git a/resolvers/record_field_resolver_test.go b/resolvers/record_field_resolver_test.go
index 206e32c4..28d6d34c 100644
--- a/resolvers/record_field_resolver_test.go
+++ b/resolvers/record_field_resolver_test.go
@@ -23,6 +23,10 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
}
requestData := &models.RequestData{
+ Headers: map[string]string{
+ "a": "123",
+ "b": "456",
+ },
Query: map[string]any{
"a": nil,
"b": 123,
@@ -438,6 +442,9 @@ func TestRecordFieldResolverResolveStaticRequestDataFields(t *testing.T) {
"b": 456,
"c": map[string]int{"sub": 1},
},
+ Headers: map[string]string{
+ "d": "789",
+ },
AuthRecord: authRecord,
}
@@ -456,6 +463,10 @@ func TestRecordFieldResolverResolveStaticRequestDataFields(t *testing.T) {
{"@request.query", true, ``},
{"@request.query.a", false, `123`},
{"@request.query.a.missing", false, ``},
+ {"@request.headers", true, ``},
+ {"@request.headers.missing", false, ``},
+ {"@request.headers.d", false, `456`},
+ {"@request.headers.d.sub", true, ``},
{"@request.data", true, ``},
{"@request.data.b", false, `456`},
{"@request.data.number", false, `10`}, // number field normalization
diff --git a/ui/src/components/base/FilterAutocompleteInput.svelte b/ui/src/components/base/FilterAutocompleteInput.svelte
index 4e8e6c0d..152979ee 100644
--- a/ui/src/components/base/FilterAutocompleteInput.svelte
+++ b/ui/src/components/base/FilterAutocompleteInput.svelte
@@ -256,6 +256,7 @@
result.push("@request.method");
result.push("@request.query.");
result.push("@request.data.");
+ result.push("@request.headers.");
result.push("@request.auth.id");
result.push("@request.auth.collectionId");
result.push("@request.auth.collectionName");
diff --git a/ui/src/components/collections/CollectionRulesTab.svelte b/ui/src/components/collections/CollectionRulesTab.svelte
index 6fcfed3c..74ece011 100644
--- a/ui/src/components/collections/CollectionRulesTab.svelte
+++ b/ui/src/components/collections/CollectionRulesTab.svelte
@@ -45,7 +45,7 @@
The request fields could be accessed with the special @request filter:
- @request.method
+ @request.headers.*
@request.query.*
@request.data.*
@request.auth.*