This is an automated email from the ASF dual-hosted git repository.

ronething pushed a commit to branch feat/response-rewrite
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git

commit 2d1c77708778b08532a22614a27638f017493a44
Merge: 908f1688 4cd10056
Author: Ashing Zheng <[email protected]>
AuthorDate: Thu Oct 30 12:09:04 2025 +0800

    Merge remote-tracking branch 'origin/master' into feat/response-rewrite
    
    Signed-off-by: Ashing Zheng <[email protected]>

 .../annotations/plugins/authorization.go           |  61 +++++++++++
 .../adc/translator/annotations/plugins/plugins.go  |   2 +
 internal/adc/translator/annotations_test.go        |  22 ++++
 test/e2e/ingress/annotations.go                    | 119 +++++++++++++++++++++
 4 files changed, 204 insertions(+)

diff --cc internal/adc/translator/annotations/plugins/authorization.go
index 00000000,83b64c5b..2dee12ea
mode 000000,100644..100644
--- a/internal/adc/translator/annotations/plugins/authorization.go
+++ b/internal/adc/translator/annotations/plugins/authorization.go
@@@ -1,0 -1,61 +1,61 @@@
+ // Licensed to the Apache Software Foundation (ASF) under one or more
+ // contributor license agreements.  See the NOTICE file distributed with
+ // this work for additional information regarding copyright ownership.
+ // The ASF licenses this file to You under the Apache License, Version 2.0
+ // (the "License"); you may not use this file except in compliance with
+ // the License.  You may obtain a copy of the License at
+ //
+ //    http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Unless required by applicable law or agreed to in writing, software
+ // distributed under the License is distributed on an "AS IS" BASIS,
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ // See the License for the specific language governing permissions and
+ // limitations under the License.
+ 
+ package plugins
+ 
+ import (
+       adctypes "github.com/apache/apisix-ingress-controller/api/adc"
+       
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
+ )
+ 
+ type basicAuth struct{}
+ 
+ // NewkeyBasicHandler creates a handler to convert
+ // annotations about basicAuth control to APISIX basic-auth plugin.
+ func NewBasicAuthHandler() PluginAnnotationsHandler {
+       return &basicAuth{}
+ }
+ 
+ func (b *basicAuth) PluginName() string {
+       return "basic-auth"
+ }
+ 
 -func (b *basicAuth) Handle(e annotations.Extractor) (interface{}, error) {
++func (b *basicAuth) Handle(e annotations.Extractor) (any, error) {
+       if e.GetStringAnnotation(annotations.AnnotationsAuthType) != 
"basicAuth" {
+               return nil, nil
+       }
+       plugin := adctypes.BasicAuthConfig{}
+       return &plugin, nil
+ }
+ 
+ type keyAuth struct{}
+ 
+ // NewkeyAuthHandler creates a handler to convert
+ // annotations about keyAuth control to APISIX key-auth plugin.
+ func NewKeyAuthHandler() PluginAnnotationsHandler {
+       return &keyAuth{}
+ }
+ 
+ func (k *keyAuth) PluginName() string {
+       return "key-auth"
+ }
+ 
 -func (k *keyAuth) Handle(e annotations.Extractor) (interface{}, error) {
++func (k *keyAuth) Handle(e annotations.Extractor) (any, error) {
+       if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "keyAuth" {
+               return nil, nil
+       }
+       plugin := adctypes.KeyAuthConfig{}
+       return &plugin, nil
+ }
diff --cc internal/adc/translator/annotations/plugins/plugins.go
index f49fe8f8,8ebb0fb3..a0cd78f8
--- a/internal/adc/translator/annotations/plugins/plugins.go
+++ b/internal/adc/translator/annotations/plugins/plugins.go
@@@ -40,7 -40,8 +40,9 @@@ var 
                NewCorsHandler(),
                NewCSRFHandler(),
                NewFaultInjectionHandler(),
+               NewBasicAuthHandler(),
+               NewKeyAuthHandler(),
 +              NewResponseRewriteHandler(),
        }
  )
  
diff --cc test/e2e/ingress/annotations.go
index 8683935e,f7a19a1f..a4e9e10d
--- a/test/e2e/ingress/annotations.go
+++ b/test/e2e/ingress/annotations.go
@@@ -382,57 -382,48 +382,99 @@@ spec
              name: httpbin-service-e2e-test
              port:
                number: 80
+ `
+                       ingressKeyAuth = `
+ apiVersion: networking.k8s.io/v1
+ kind: Ingress
+ metadata:
+   name: key-auth
+   annotations:
+     k8s.apisix.apache.org/auth-type: "keyAuth"
+ spec:
+   ingressClassName: %s
+   rules:
+   - host: httpbin.example
+     http:
+       paths:
+       - path: /ip
+         pathType: Exact
+         backend:
+           service:
+             name: httpbin-service-e2e-test
+             port:
+               number: 80
+ `
+                       ingressBasicAuth = `
+ apiVersion: networking.k8s.io/v1
+ kind: Ingress
+ metadata:
+   name: basic-auth
+   annotations:
+     k8s.apisix.apache.org/auth-type: "basicAuth"
+ spec:
+   ingressClassName: %s
+   rules:
+   - host: httpbin.example
+     http:
+       paths:
+       - path: /get
+         pathType: Exact
+         backend:
+           service:
+             name: httpbin-service-e2e-test
+             port:
+               number: 80
 +`
 +                      responseRewrite = `
 +apiVersion: networking.k8s.io/v1
 +kind: Ingress
 +metadata:
 +  name: response-rewrite
 +  annotations:
 +    k8s.apisix.apache.org/enable-response-rewrite: "true"
 +    k8s.apisix.apache.org/response-rewrite-status-code: "400"
 +    k8s.apisix.apache.org/response-rewrite-body: "custom response body"
 +    k8s.apisix.apache.org/response-rewrite-body-base64: "false"
 +    k8s.apisix.apache.org/response-rewrite-set-header: 
"X-Custom-Header:custom-value"
 +    k8s.apisix.apache.org/response-rewrite-add-header: 
"X-Add-Header:added-value"
 +    k8s.apisix.apache.org/response-rewrite-remove-header: "Server"
 +spec:
 +  ingressClassName: %s
 +  rules:
 +  - host: httpbin.example
 +    http:
 +      paths:
 +      - path: /get
 +        pathType: Exact
 +        backend:
 +          service:
 +            name: httpbin-service-e2e-test
 +            port:
 +              number: 80
 +`
 +                      responseRewriteBase64 = `
 +apiVersion: networking.k8s.io/v1
 +kind: Ingress
 +metadata:
 +  name: response-rewrite-base64
 +  annotations:
 +    k8s.apisix.apache.org/enable-response-rewrite: "true"
 +    k8s.apisix.apache.org/response-rewrite-status-code: "400"
 +    k8s.apisix.apache.org/response-rewrite-body: 
"Y3VzdG9tIHJlc3BvbnNlIGJvZHk="
 +    k8s.apisix.apache.org/response-rewrite-body-base64: "true"
 +spec:
 +  ingressClassName: %s
 +  rules:
 +  - host: httpbin-base64.example
 +    http:
 +      paths:
 +      - path: /get
 +        pathType: Exact
 +        backend:
 +          service:
 +            name: httpbin-service-e2e-test
 +            port:
 +              number: 80
  `
                )
                BeforeEach(func() {
@@@ -661,62 -652,82 +703,139 @@@ spec
                                s.RequestAssert(test)
                        }
                })
+               It("authentication", func() {
+                       var (
+                               keyAuth = `
+ apiVersion: apisix.apache.org/v2
+ kind: ApisixConsumer
+ metadata:
+   name: key
+ spec:
+   ingressClassName: %s
+   authParameter:
+     keyAuth:
+       value:
+         key: test-key
+ `
+                               basicAuth = `
+ apiVersion: apisix.apache.org/v2
+ kind: ApisixConsumer
+ metadata:
+   name: basic
+ spec:
+   ingressClassName: %s
+   authParameter:
+     basicAuth:
+       value:
+         username: test-user
+         password: test-password
+ `
+                       )
+                       Expect(s.CreateResourceFromString(fmt.Sprintf(keyAuth, 
s.Namespace()))).ShouldNot(HaveOccurred(), "creating ApisixConsumer for 
keyAuth")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(basicAuth, 
s.Namespace()))).ShouldNot(HaveOccurred(), "creating ApisixConsumer for 
basicAuth")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(ingressKeyAuth, 
s.Namespace()))).ShouldNot(HaveOccurred(), "creating Ingress")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(ingressBasicAuth, 
s.Namespace()))).ShouldNot(HaveOccurred(), "creating Ingress")
+ 
+                       tests := []*scaffold.RequestAssert{
+                               {
+                                       Method: "GET",
+                                       Path:   "/get",
+                                       Host:   "httpbin.example",
+                                       BasicAuth: &scaffold.BasicAuth{
+                                               Username: "test-user",
+                                               Password: "test-password",
+                                       },
+                                       Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                               },
+                               {
+                                       Method: "GET",
+                                       Path:   "/get",
+                                       Host:   "httpbin.example",
+                                       BasicAuth: &scaffold.BasicAuth{
+                                               Username: "invalid-user",
+                                               Password: "invalid-password",
+                                       },
+                                       Check: 
scaffold.WithExpectedStatus(http.StatusUnauthorized),
+                               },
+                               {
+                                       Method: "GET",
+                                       Path:   "/ip",
+                                       Host:   "httpbin.example",
+                                       Headers: map[string]string{
+                                               "apikey": "test-key",
+                                       },
+                                       Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                               },
+                               {
+                                       Method: "GET",
+                                       Path:   "/ip",
+                                       Host:   "httpbin.example",
+                                       Headers: map[string]string{
+                                               "apikey": "invalid-key",
+                                       },
+                                       Check: 
scaffold.WithExpectedStatus(http.StatusUnauthorized),
+                               },
+                       }
+                       for _, test := range tests {
+                               s.RequestAssert(test)
+                       }
+               })
 +
 +              It("response-rewrite", func() {
 +                      
Expect(s.CreateResourceFromString(fmt.Sprintf(responseRewrite, 
s.Namespace()))).ShouldNot(HaveOccurred(), "creating Ingress")
 +
 +                      s.RequestAssert(&scaffold.RequestAssert{
 +                              Method: "GET",
 +                              Path:   "/get",
 +                              Host:   "httpbin.example",
 +                              Checks: []scaffold.ResponseCheckFunc{
 +                                      
scaffold.WithExpectedStatus(http.StatusBadRequest),
 +                                      
scaffold.WithExpectedBodyContains("custom response body"),
 +                                      
scaffold.WithExpectedHeader("X-Custom-Header", "custom-value"),
 +                                      
scaffold.WithExpectedHeader("X-Add-Header", "added-value"),
 +                              },
 +                      })
 +
 +                      By("Verify response-rewrite plugin is configured in the 
route")
 +                      routes, err := 
s.DefaultDataplaneResource().Route().List(context.Background())
 +                      Expect(err).NotTo(HaveOccurred(), "listing Route")
 +                      Expect(routes).To(HaveLen(1), "checking Route length")
 +                      
Expect(routes[0].Plugins).To(HaveKey("response-rewrite"), "checking Route 
plugins")
 +
 +                      jsonBytes, err := 
json.Marshal(routes[0].Plugins["response-rewrite"])
 +                      Expect(err).NotTo(HaveOccurred(), "marshalling 
response-rewrite plugin config")
 +                      var rewriteConfig map[string]any
 +                      err = json.Unmarshal(jsonBytes, &rewriteConfig)
 +                      Expect(err).NotTo(HaveOccurred(), "unmarshalling 
response-rewrite plugin config")
 +                      
Expect(rewriteConfig["status_code"]).To(Equal(float64(400)), "checking status 
code")
 +                      Expect(rewriteConfig["body"]).To(Equal("custom response 
body"), "checking body")
 +              })
 +
 +              It("response-rewrite with base64", func() {
 +                      
Expect(s.CreateResourceFromString(fmt.Sprintf(responseRewriteBase64, 
s.Namespace()))).ShouldNot(HaveOccurred(), "creating Ingress")
 +
 +                      s.RequestAssert(&scaffold.RequestAssert{
 +                              Method: "GET",
 +                              Path:   "/get",
 +                              Host:   "httpbin-base64.example",
 +                              Checks: []scaffold.ResponseCheckFunc{
 +                                      
scaffold.WithExpectedStatus(http.StatusBadRequest),
 +                                      
scaffold.WithExpectedBodyContains("custom response body"),
 +                              },
 +                      })
 +                      By("Verify response-rewrite plugin is configured in the 
route")
 +                      routes, err := 
s.DefaultDataplaneResource().Route().List(context.Background())
 +                      Expect(err).NotTo(HaveOccurred(), "listing Route")
 +                      Expect(routes).To(HaveLen(1), "checking Route length")
 +                      
Expect(routes[0].Plugins).To(HaveKey("response-rewrite"), "checking Route 
plugins")
 +
 +                      jsonBytes, err := 
json.Marshal(routes[0].Plugins["response-rewrite"])
 +                      Expect(err).NotTo(HaveOccurred(), "marshalling 
response-rewrite plugin config")
 +                      var rewriteConfig map[string]any
 +                      err = json.Unmarshal(jsonBytes, &rewriteConfig)
 +                      Expect(err).NotTo(HaveOccurred(), "unmarshalling 
response-rewrite plugin config")
 +                      
Expect(rewriteConfig["status_code"]).To(Equal(float64(400)), "checking status 
code")
 +                      Expect(rewriteConfig["body_base64"]).To(BeTrue(), 
"checking body_base64")
 +              })
        })
  })

Reply via email to