Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow response header rewrite via Ingress annotations #1861

Merged
merged 3 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/en/latest/concepts/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,30 @@ This annotation configures the new body in the response.
k8s.apisix.apache.org/response-rewrite-body: "bar-body"
```

### Add header

This annotation configures to append the new headers in the response.

```yaml
k8s.apisix.apache.org/response-rewrite-add-header: "testkey1:testval1,testkey2:testval2"
```

### Set header

This annotation configures to rewrite the new headers in the response.

```yaml
k8s.apisix.apache.org/response-rewrite-set-header: "testkey1:testval1,testkey2:testval2"
```

### Remove header

This annotation configures to remove headers in the response.

```yaml
k8s.apisix.apache.org/response-rewrite-remove-header: "testkey1,testkey2"
```

### Body Base64

When set, the body of the request will be decoded before writing to the client.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,10 @@ func (c *responseRewrite) Handle(e annotations.Extractor) (interface{}, error) {
plugin.StatusCode, _ = strconv.Atoi(e.GetStringAnnotation(annotations.AnnotationsResponseRewriteStatusCode))
plugin.Body = e.GetStringAnnotation(annotations.AnnotationsResponseRewriteBody)
plugin.BodyBase64 = e.GetBoolAnnotation(annotations.AnnotationsResponseRewriteBodyBase64)
headers := make(apisixv1.Headers)
headers.Add(e.GetStringsAnnotation(annotations.AnnotationsResponseRewriteHeaderAdd))
headers.Set(e.GetStringsAnnotation(annotations.AnnotationsResponseRewriteHeaderSet))
headers.Remove(e.GetStringsAnnotation(annotations.AnnotationsResponseRewriteHeaderRemove))
plugin.Headers = headers
return &plugin, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ import (

func TestResponseRewriteHandler(t *testing.T) {
anno := map[string]string{
annotations.AnnotationsEnableResponseRewrite: "true",
annotations.AnnotationsResponseRewriteStatusCode: "200",
annotations.AnnotationsResponseRewriteBody: "bar_body",
annotations.AnnotationsResponseRewriteBodyBase64: "false",
annotations.AnnotationsEnableResponseRewrite: "true",
annotations.AnnotationsResponseRewriteStatusCode: "200",
annotations.AnnotationsResponseRewriteBody: "bar_body",
annotations.AnnotationsResponseRewriteBodyBase64: "false",
annotations.AnnotationsResponseRewriteHeaderAdd: "testkey1:testval1,testkey2:testval2",
annotations.AnnotationsResponseRewriteHeaderRemove: "testkey1,testkey2",
annotations.AnnotationsResponseRewriteHeaderSet: "testkey1:testval1,testkey2:testval2",
}
p := NewResponseRewriteHandler()
out, err := p.Handle(annotations.NewExtractor(anno))
Expand All @@ -37,9 +40,13 @@ func TestResponseRewriteHandler(t *testing.T) {
assert.Equal(t, 200, config.StatusCode)
assert.Equal(t, "bar_body", config.Body)
assert.Equal(t, false, config.BodyBase64)

assert.Equal(t, "response-rewrite", p.PluginName())

assert.Equal(t, []string{"testkey1:testval1", "testkey2:testval2"}, config.Headers.GetAddedHeaders())
assert.Equal(t, []string{"testkey1", "testkey2"}, config.Headers.GetRemovedHeaders())
assert.Equal(t, map[string]string{
"testkey1": "testval1",
"testkey2": "testval2",
}, config.Headers.GetSetHeaders())
anno[annotations.AnnotationsEnableResponseRewrite] = "false"
out, err = p.Handle(annotations.NewExtractor(anno))
assert.Nil(t, err, "checking given error")
Expand Down
11 changes: 7 additions & 4 deletions pkg/providers/ingress/translation/annotations/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,13 @@ const (
AnnotationsRewriteTargetRegexTemplate = AnnotationsPrefix + "rewrite-target-regex-template"

// response-rewrite plugin
AnnotationsEnableResponseRewrite = AnnotationsPrefix + "enable-response-rewrite"
AnnotationsResponseRewriteStatusCode = AnnotationsPrefix + "response-rewrite-status-code"
AnnotationsResponseRewriteBody = AnnotationsPrefix + "response-rewrite-body"
AnnotationsResponseRewriteBodyBase64 = AnnotationsPrefix + "response-rewrite-body-base64"
AnnotationsEnableResponseRewrite = AnnotationsPrefix + "enable-response-rewrite"
AnnotationsResponseRewriteStatusCode = AnnotationsPrefix + "response-rewrite-status-code"
AnnotationsResponseRewriteBody = AnnotationsPrefix + "response-rewrite-body"
AnnotationsResponseRewriteBodyBase64 = AnnotationsPrefix + "response-rewrite-body-base64"
AnnotationsResponseRewriteHeaderAdd = AnnotationsPrefix + "response-rewrite-add-header"
AnnotationsResponseRewriteHeaderSet = AnnotationsPrefix + "response-rewrite-set-header"
AnnotationsResponseRewriteHeaderRemove = AnnotationsPrefix + "response-rewrite-remove-header"

// forward-auth plugin
AnnotationsForwardAuthURI = AnnotationsPrefix + "auth-uri"
Expand Down
80 changes: 80 additions & 0 deletions pkg/types/apisix/v1/plugin_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package v1

import (
"encoding/json"
"fmt"
"strings"

"github.com/incubator4/go-resty-expr/expr"
)
Expand Down Expand Up @@ -199,3 +201,81 @@ func (p *Headers) DeepCopy() *Headers {
p.DeepCopyInto(out)
return out
}

func (p *Headers) Add(headersToAdd []string) {
if p == nil {
return
}
if headersToAdd != nil {
addedHeader := make([]string, 0)
for _, h := range headersToAdd {
kv := strings.Split(h, ":")
if len(kv) < 2 {
continue
}
addedHeader = append(addedHeader, fmt.Sprintf("%s:%s", kv[0], kv[1]))
}
(*p)["add"] = addedHeader
}
}

func (p *Headers) GetAddedHeaders() []string {
if p == nil || (*p)["add"] == nil {
return nil
}
addedheaders, ok := (*p)["add"].([]string)
if ok {
return addedheaders
}
return nil
}

func (p *Headers) Set(headersToSet []string) {
if p == nil {
return
}
if headersToSet != nil {
setHeaders := make(map[string]string, 0)
for _, h := range headersToSet {
kv := strings.Split(h, ":")
if len(kv) < 2 {
continue
}
setHeaders[kv[0]] = kv[1]
}
(*p)["set"] = setHeaders
}
}

func (p *Headers) GetSetHeaders() map[string]string {
if p == nil || (*p)["set"] == nil {
return nil
}
addedheaders, ok := (*p)["set"].(map[string]string)
if ok {
return addedheaders
}
return nil
}

func (p *Headers) Remove(headersToRemove []string) {
if p == nil {
return
}
if headersToRemove != nil {
removeHeaders := make([]string, 0)
removeHeaders = append(removeHeaders, headersToRemove...)
(*p)["remove"] = removeHeaders
}
}

func (p *Headers) GetRemovedHeaders() []string {
if p == nil || (*p)["remove"] == nil {
return nil
}
removedHeaders, ok := (*p)["remove"].([]string)
if ok {
return removedHeaders
}
return nil
}