Skip to content
Snippets Groups Projects
Commit e194f655 authored by Yordan Kinkov's avatar Yordan Kinkov
Browse files

Return string when accessing a header in Rego

parent 15589a53
No related branches found
No related tags found
No related merge requests found
......@@ -172,7 +172,26 @@ endpoints for working with arbitrary dynamically uploaded policies.
### Access HTTP Headers inside a policy
HTTP Request Headers are passed to the evaluation runtime on each request. One could access any header by name within
the Rego source code using `input.header.name` or `input.header["name"]`.
the Rego source code using `input.headers.Name` or `input.headers["Name"]`.
##### **Important**
Header names are passed to the Rego runtime in a canonical format. This means that the first character and any characters following a
hyphen are uppercase and the rest are lowercase.
Example:
The policy service receives a request with these headers:
```
accept-encoding: gzip, deflate
Accept-Language: en-us
fOO: Bar
x-loCATion: Baz
```
Inside a policy these headers could be accessed as follows:
```
input.headers["Accept-Encoding"]
input.headers["Accept-Language"]
input.headers["Foo"]
input.headers["X-Location"]
```
### Policy Extensions Functions
......
......@@ -23,10 +23,18 @@ func Middleware() func(http.Handler) http.Handler {
}
func ToContext(ctx context.Context, r *http.Request) context.Context {
return context.WithValue(ctx, headerKey, r.Header)
headers := make(map[string]string, len(r.Header)+1)
for name := range r.Header {
headers[name] = r.Header.Get(name)
}
// add Host header to headers map
headers["Host"] = r.Host
return context.WithValue(ctx, headerKey, headers)
}
func FromContext(ctx context.Context) (http.Header, bool) {
header, ok := ctx.Value(headerKey).(http.Header)
func FromContext(ctx context.Context) (map[string]string, bool) {
header, ok := ctx.Value(headerKey).(map[string]string)
return header, ok
}
......@@ -10,10 +10,10 @@ import (
)
func TestMiddleware(t *testing.T) {
expected := http.Header{"Authorization": []string{"my-token"}}
expected := map[string]string{"Authorization": "my-token", "Host": "example.com"}
req := httptest.NewRequest("POST", "/example", nil)
req.Header = expected
req.Header = http.Header{"Authorization": []string{"my-token"}}
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
value, ok := header.FromContext(r.Context())
......
......@@ -21,7 +21,7 @@ import (
//go:generate counterfeiter . Storage
//go:generate counterfeiter . RegoCache
const HeaderKey = "header"
const HeaderKey = "headers"
type Cache interface {
Set(ctx context.Context, key, namespace, scope string, value []byte, ttl int) error
......
......@@ -37,7 +37,7 @@ func TestService_Evaluate(t *testing.T) {
testPolicyWithStaticData := `package testgroup.example default allow = false allow { data.msg == "hello world" }`
// prepare test policy accessing headers during evaluation
testPolicyAccessingHeaders := `package testgroup.example token := input.header["Authorization"]`
testPolicyAccessingHeaders := `package testgroup.example token := input.headers["Authorization"]`
// prepare test query that can be retrieved from rego queryCache
testQuery, err := rego.New(
......@@ -347,7 +347,7 @@ func TestService_Evaluate(t *testing.T) {
},
},
res: &goapolicy.EvaluateResult{
Result: map[string]interface{}{"token": []interface{}{"my-token"}},
Result: map[string]interface{}{"token": "my-token"},
},
},
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment