diff --git a/docs/en/latest/concepts/annotations.md b/docs/en/latest/concepts/annotations.md index 4f0bd93a49e..26af6a21b9b 100644 --- a/docs/en/latest/concepts/annotations.md +++ b/docs/en/latest/concepts/annotations.md @@ -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. diff --git a/pkg/providers/ingress/translation/annotations/plugins/response_rewrite.go b/pkg/providers/ingress/translation/annotations/plugins/response_rewrite.go index 673fc88dbc0..f03a1d9491a 100644 --- a/pkg/providers/ingress/translation/annotations/plugins/response_rewrite.go +++ b/pkg/providers/ingress/translation/annotations/plugins/response_rewrite.go @@ -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 } diff --git a/pkg/providers/ingress/translation/annotations/plugins/response_rewrite_test.go b/pkg/providers/ingress/translation/annotations/plugins/response_rewrite_test.go index 6682d289c5a..302f7a21d9f 100644 --- a/pkg/providers/ingress/translation/annotations/plugins/response_rewrite_test.go +++ b/pkg/providers/ingress/translation/annotations/plugins/response_rewrite_test.go @@ -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)) @@ -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") diff --git a/pkg/providers/ingress/translation/annotations/types.go b/pkg/providers/ingress/translation/annotations/types.go index 56d2b622fab..503e79b2e49 100644 --- a/pkg/providers/ingress/translation/annotations/types.go +++ b/pkg/providers/ingress/translation/annotations/types.go @@ -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" diff --git a/pkg/types/apisix/v1/plugin_types.go b/pkg/types/apisix/v1/plugin_types.go index dd6bf9b93f4..d6e611f54e8 100644 --- a/pkg/types/apisix/v1/plugin_types.go +++ b/pkg/types/apisix/v1/plugin_types.go @@ -16,6 +16,8 @@ package v1 import ( "encoding/json" + "fmt" + "strings" "github.com/incubator4/go-resty-expr/expr" ) @@ -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 +}