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

spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-go-plugin-runner.git


The following commit(s) were added to refs/heads/master by this push:
     new 2d6b282  feat: add response filter for plugin (#89)
2d6b282 is described below

commit 2d6b282a14d23caddacdb7ad6529b0d3d33f85dd
Author: soulbird <[email protected]>
AuthorDate: Sun Jun 19 19:59:18 2022 +0800

    feat: add response filter for plugin (#89)
    
    Co-authored-by: soulbird <[email protected]>
---
 cmd/go-runner/plugins/fault_injection.go      |  6 +-
 cmd/go-runner/plugins/fault_injection_test.go |  4 +-
 cmd/go-runner/plugins/limit_req.go            |  8 ++-
 cmd/go-runner/plugins/limit_req_test.go       |  4 +-
 cmd/go-runner/plugins/say.go                  |  6 +-
 cmd/go-runner/plugins/say_test.go             |  4 +-
 docs/en/latest/getting-started.md             |  6 +-
 internal/plugin/conf_test.go                  |  4 +-
 internal/plugin/plugin.go                     | 29 +++++----
 internal/plugin/plugin_test.go                | 93 +++++++++++++++++++--------
 pkg/http/http.go                              | 29 +++++++++
 pkg/plugin/plugin.go                          | 10 ++-
 12 files changed, 148 insertions(+), 55 deletions(-)

diff --git a/cmd/go-runner/plugins/fault_injection.go 
b/cmd/go-runner/plugins/fault_injection.go
index 9f04299..eee3f0c 100644
--- a/cmd/go-runner/plugins/fault_injection.go
+++ b/cmd/go-runner/plugins/fault_injection.go
@@ -77,7 +77,7 @@ func sampleHit(percentage int) bool {
        return rand.Intn(100) < percentage
 }
 
-func (p *FaultInjection) Filter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
+func (p *FaultInjection) RequestFilter(conf interface{}, w 
http.ResponseWriter, r pkgHTTP.Request) {
        fc := conf.(FaultInjectionConf)
        if !sampleHit(fc.Percentage) {
                return
@@ -94,3 +94,7 @@ func (p *FaultInjection) Filter(conf interface{}, w 
http.ResponseWriter, r pkgHT
                log.Errorf("failed to write: %s", err)
        }
 }
+
+func (p *FaultInjection) ResponseFilter(interface{}, pkgHTTP.Response) {
+
+}
diff --git a/cmd/go-runner/plugins/fault_injection_test.go 
b/cmd/go-runner/plugins/fault_injection_test.go
index eb073f9..f5ccdde 100644
--- a/cmd/go-runner/plugins/fault_injection_test.go
+++ b/cmd/go-runner/plugins/fault_injection_test.go
@@ -32,7 +32,7 @@ func TestFaultInjection(t *testing.T) {
        assert.Nil(t, err)
 
        w := httptest.NewRecorder()
-       fi.Filter(conf, w, nil)
+       fi.RequestFilter(conf, w, nil)
        resp := w.Result()
        body, _ := ioutil.ReadAll(resp.Body)
        assert.Equal(t, 400, resp.StatusCode)
@@ -46,7 +46,7 @@ func TestFaultInjection_Percentage(t *testing.T) {
        assert.Nil(t, err)
 
        w := httptest.NewRecorder()
-       fi.Filter(conf, w, nil)
+       fi.RequestFilter(conf, w, nil)
        resp := w.Result()
        assert.Equal(t, 200, resp.StatusCode)
 }
diff --git a/cmd/go-runner/plugins/limit_req.go 
b/cmd/go-runner/plugins/limit_req.go
index 0a8320f..34c8c29 100644
--- a/cmd/go-runner/plugins/limit_req.go
+++ b/cmd/go-runner/plugins/limit_req.go
@@ -62,8 +62,8 @@ func (p *LimitReq) ParseConf(in []byte) (interface{}, error) {
        return conf, nil
 }
 
-// Filter is called when a request hits the route
-func (p *LimitReq) Filter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
+// RequestFilter is called when a request hits the route
+func (p *LimitReq) RequestFilter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
        li := conf.(LimitReqConf).limiter
        rs := li.Reserve()
        if !rs.OK() {
@@ -75,3 +75,7 @@ func (p *LimitReq) Filter(conf interface{}, w 
http.ResponseWriter, r pkgHTTP.Req
        }
        time.Sleep(rs.Delay())
 }
+
+func (p *LimitReq) ResponseFilter(interface{}, pkgHTTP.Response) {
+
+}
diff --git a/cmd/go-runner/plugins/limit_req_test.go 
b/cmd/go-runner/plugins/limit_req_test.go
index baab79b..f5e51c7 100644
--- a/cmd/go-runner/plugins/limit_req_test.go
+++ b/cmd/go-runner/plugins/limit_req_test.go
@@ -38,7 +38,7 @@ func TestLimitReq(t *testing.T) {
                wg.Add(1)
                go func(i int) {
                        w := httptest.NewRecorder()
-                       lr.Filter(conf, w, nil)
+                       lr.RequestFilter(conf, w, nil)
                        resp := w.Result()
                        res[i] = resp
                        wg.Done()
@@ -64,7 +64,7 @@ func TestLimitReq_YouShouldNotPass(t *testing.T) {
        assert.Nil(t, err)
 
        w := httptest.NewRecorder()
-       lr.Filter(conf, w, nil)
+       lr.RequestFilter(conf, w, nil)
        resp := w.Result()
        assert.Equal(t, 503, resp.StatusCode)
 }
diff --git a/cmd/go-runner/plugins/say.go b/cmd/go-runner/plugins/say.go
index 05ed639..49a41ea 100644
--- a/cmd/go-runner/plugins/say.go
+++ b/cmd/go-runner/plugins/say.go
@@ -52,7 +52,7 @@ func (p *Say) ParseConf(in []byte) (interface{}, error) {
        return conf, err
 }
 
-func (p *Say) Filter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
+func (p *Say) RequestFilter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
        body := conf.(SayConf).Body
        if len(body) == 0 {
                return
@@ -64,3 +64,7 @@ func (p *Say) Filter(conf interface{}, w http.ResponseWriter, 
r pkgHTTP.Request)
                log.Errorf("failed to write: %s", err)
        }
 }
+
+func (p *Say) ResponseFilter(interface{}, pkgHTTP.Response) {
+
+}
diff --git a/cmd/go-runner/plugins/say_test.go 
b/cmd/go-runner/plugins/say_test.go
index 61b2362..ce26979 100644
--- a/cmd/go-runner/plugins/say_test.go
+++ b/cmd/go-runner/plugins/say_test.go
@@ -33,7 +33,7 @@ func TestSay(t *testing.T) {
        assert.Equal(t, "hello", conf.(SayConf).Body)
 
        w := httptest.NewRecorder()
-       say.Filter(conf, w, nil)
+       say.RequestFilter(conf, w, nil)
        resp := w.Result()
        body, _ := ioutil.ReadAll(resp.Body)
        assert.Equal(t, 200, resp.StatusCode)
@@ -56,7 +56,7 @@ func TestSay_NoBody(t *testing.T) {
        assert.Equal(t, "", conf.(SayConf).Body)
 
        w := httptest.NewRecorder()
-       say.Filter(conf, w, nil)
+       say.RequestFilter(conf, w, nil)
        resp := w.Result()
        assert.Equal(t, "", resp.Header.Get("X-Resp-A6-Runner"))
 }
diff --git a/docs/en/latest/getting-started.md 
b/docs/en/latest/getting-started.md
index 1146844..e06fc5a 100644
--- a/docs/en/latest/getting-started.md
+++ b/docs/en/latest/getting-started.md
@@ -111,10 +111,10 @@ type SayConf struct {
 }
 ```
 
-`Filter` will be executed on every request with the say plugin configured.
+`RequestFilter` will be executed on every request with the say plugin 
configured.
 
 ```
-func (p *Say) Filter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
+func (p *Say) RequestFilter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
        body := conf.(SayConf).
        if len(body) == 0 {
                return
@@ -128,7 +128,7 @@ func (p *Say) Filter(conf interface{}, w 
http.ResponseWriter, r pkgHTTP.Request)
 }
 ```
 
-We can see that the Filter takes the value of the body set in the 
configuration as the response body. If we call `Write` or `WriteHeader` of the 
`http.ResponseWriter`
+We can see that the RequestFilter takes the value of the body set in the 
configuration as the response body. If we call `Write` or `WriteHeader` of the 
`http.ResponseWriter`
 (respond directly in the plugin), it will response directly in the APISIX 
without touching the upstream. We can also set response headers in the plugin 
and touch the upstream
 at the same time by set RespHeader in `pkgHTTP.Request`.
 
diff --git a/internal/plugin/conf_test.go b/internal/plugin/conf_test.go
index 0a44749..4cb410b 100644
--- a/internal/plugin/conf_test.go
+++ b/internal/plugin/conf_test.go
@@ -97,7 +97,7 @@ func TestPrepareConfBadConf(t *testing.T) {
        f := func(in []byte) (conf interface{}, err error) {
                return nil, errors.New("ouch")
        }
-       RegisterPlugin("bad_conf", f, emptyFilter)
+       RegisterPlugin("bad_conf", f, emptyRequestFilter, emptyResponseFilter)
        name := builder.CreateString("bad_conf")
        value := builder.CreateString(`{"body":"yes"}`)
        prepareConfWithData(builder, name, value)
@@ -239,7 +239,7 @@ func TestGetRuleConf(t *testing.T) {
 }
 
 func TestGetRuleConfCheckConf(t *testing.T) {
-       RegisterPlugin("echo", emptyParseConf, emptyFilter)
+       RegisterPlugin("echo", emptyParseConf, emptyRequestFilter, 
emptyResponseFilter)
        InitConfCache(1 * time.Millisecond)
        builder := flatbuffers.NewBuilder(1024)
 
diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go
index e942d22..74a4bfc 100644
--- a/internal/plugin/plugin.go
+++ b/internal/plugin/plugin.go
@@ -34,11 +34,13 @@ import (
 )
 
 type ParseConfFunc func(in []byte) (conf interface{}, err error)
-type FilterFunc func(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request)
+type RequestFilterFunc func(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request)
+type ResponseFilterFunc func(conf interface{}, w pkgHTTP.Response)
 
 type pluginOpts struct {
-       ParseConf ParseConfFunc
-       Filter    FilterFunc
+       ParseConf      ParseConfFunc
+       RequestFilter  RequestFilterFunc
+       ResponseFilter ResponseFilterFunc
 }
 
 type pluginRegistries struct {
@@ -57,12 +59,13 @@ func (err ErrPluginRegistered) Error() string {
 var (
        pluginRegistry = pluginRegistries{opts: map[string]*pluginOpts{}}
 
-       ErrMissingName            = errors.New("missing name")
-       ErrMissingParseConfMethod = errors.New("missing ParseConf method")
-       ErrMissingFilterMethod    = errors.New("missing Filter method")
+       ErrMissingName                 = errors.New("missing name")
+       ErrMissingParseConfMethod      = errors.New("missing ParseConf method")
+       ErrMissingRequestFilterMethod  = errors.New("missing RequestFilter 
method")
+       ErrMissingResponseFilterMethod = errors.New("missing ResponseFilter 
method")
 )
 
-func RegisterPlugin(name string, pc ParseConfFunc, sv FilterFunc) error {
+func RegisterPlugin(name string, pc ParseConfFunc, sv RequestFilterFunc, rsv 
ResponseFilterFunc) error {
        log.Infof("register plugin %s", name)
 
        if name == "" {
@@ -72,12 +75,16 @@ func RegisterPlugin(name string, pc ParseConfFunc, sv 
FilterFunc) error {
                return ErrMissingParseConfMethod
        }
        if sv == nil {
-               return ErrMissingFilterMethod
+               return ErrMissingRequestFilterMethod
+       }
+       if rsv == nil {
+               return ErrMissingResponseFilterMethod
        }
 
        opt := &pluginOpts{
-               ParseConf: pc,
-               Filter:    sv,
+               ParseConf:      pc,
+               RequestFilter:  sv,
+               ResponseFilter: rsv,
        }
        pluginRegistry.Lock()
        defer pluginRegistry.Unlock()
@@ -105,7 +112,7 @@ func filter(conf RuleConf, w *inHTTP.ReqResponse, r 
pkgHTTP.Request) error {
 
                log.Infof("run plugin %s", c.Name)
 
-               plugin.Filter(c.Value, w, r)
+               plugin.RequestFilter(c.Value, w, r)
 
                if w.HasChange() {
                        // response is generated, no need to continue
diff --git a/internal/plugin/plugin_test.go b/internal/plugin/plugin_test.go
index 12a9399..e95a34d 100644
--- a/internal/plugin/plugin_test.go
+++ b/internal/plugin/plugin_test.go
@@ -36,7 +36,11 @@ var (
                return string(in), nil
        }
 
-       emptyFilter = func(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
+       emptyRequestFilter = func(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
+               return
+       }
+
+       emptyResponseFilter = func(conf interface{}, w pkgHTTP.Response) {
                return
        }
 )
@@ -73,7 +77,7 @@ func TestHTTPReqCall_FailedToParseConf(t *testing.T) {
                assert.Equal(t, "foo", conf.(string))
        }
 
-       RegisterPlugin("baz", bazParseConf, bazFilter)
+       RegisterPlugin("baz", bazParseConf, bazFilter, emptyResponseFilter)
 
        builder := flatbuffers.NewBuilder(1024)
        bazName := builder.CreateString("baz")
@@ -100,7 +104,8 @@ func TestRegisterPlugin(t *testing.T) {
        type args struct {
                name string
                pc   ParseConfFunc
-               sv   FilterFunc
+               sv   RequestFilterFunc
+               rsv  ResponseFilterFunc
        }
        tests := []struct {
                name    string
@@ -112,7 +117,8 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "1",
                                pc:   nil,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrMissingParseConfMethod,
                },
@@ -122,8 +128,19 @@ func TestRegisterPlugin(t *testing.T) {
                                name: "1",
                                pc:   emptyParseConf,
                                sv:   nil,
+                               rsv:  emptyResponseFilter,
+                       },
+                       wantErr: ErrMissingRequestFilterMethod,
+               },
+               {
+                       name: "test_MissingRespFilterMethod",
+                       args: args{
+                               name: "1",
+                               pc:   emptyParseConf,
+                               sv:   emptyRequestFilter,
+                               rsv:  nil,
                        },
-                       wantErr: ErrMissingFilterMethod,
+                       wantErr: ErrMissingResponseFilterMethod,
                },
                {
                        name: "test_MissingParseConfMethod&FilterMethod",
@@ -131,6 +148,17 @@ func TestRegisterPlugin(t *testing.T) {
                                name: "1",
                                pc:   nil,
                                sv:   nil,
+                               rsv:  emptyResponseFilter,
+                       },
+                       wantErr: ErrMissingParseConfMethod,
+               },
+               {
+                       name: "test_MissingParseConfMethod&RespFilterMethod",
+                       args: args{
+                               name: "1",
+                               pc:   nil,
+                               sv:   emptyRequestFilter,
+                               rsv:  nil,
                        },
                        wantErr: ErrMissingParseConfMethod,
                },
@@ -139,16 +167,18 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "",
                                pc:   nil,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrMissingName,
                },
                {
-                       name: "test_MissingName&FilterMethod",
+                       name: "test_MissingName&FilterMethod&RespFilterMethod",
                        args: args{
                                name: "",
                                pc:   emptyParseConf,
                                sv:   nil,
+                               rsv:  nil,
                        },
                        wantErr: ErrMissingName,
                },
@@ -158,6 +188,7 @@ func TestRegisterPlugin(t *testing.T) {
                                name: "",
                                pc:   nil,
                                sv:   nil,
+                               rsv:  nil,
                        },
                        wantErr: ErrMissingName,
                },
@@ -166,7 +197,8 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "plugin1",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: nil,
                },
@@ -175,7 +207,8 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "plugin1",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrPluginRegistered{"plugin1"},
                },
@@ -184,7 +217,8 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "plugin2111%#@#",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: nil,
                },
@@ -193,7 +227,8 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "plugin311*%#@#",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: nil,
                },
@@ -202,14 +237,15 @@ func TestRegisterPlugin(t *testing.T) {
                        args: args{
                                name: "plugin311*%#@#",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrPluginRegistered{"plugin311*%#@#"},
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       if err := RegisterPlugin(tt.args.name, tt.args.pc, 
tt.args.sv); !assert.Equal(t, tt.wantErr, err) {
+                       if err := RegisterPlugin(tt.args.name, tt.args.pc, 
tt.args.sv, tt.args.rsv); !assert.Equal(t, tt.wantErr, err) {
                                t.Errorf("RegisterPlugin() error = %v, wantErr 
%v", err, tt.wantErr)
                        }
                })
@@ -217,12 +253,13 @@ func TestRegisterPlugin(t *testing.T) {
 }
 
 func TestRegisterPluginConcurrent(t *testing.T) {
-       RegisterPlugin("test_concurrent-1", emptyParseConf, emptyFilter)
-       RegisterPlugin("test_concurrent-2", emptyParseConf, emptyFilter)
+       RegisterPlugin("test_concurrent-1", emptyParseConf, emptyRequestFilter, 
emptyResponseFilter)
+       RegisterPlugin("test_concurrent-2", emptyParseConf, emptyRequestFilter, 
emptyResponseFilter)
        type args struct {
                name string
                pc   ParseConfFunc
-               sv   FilterFunc
+               sv   RequestFilterFunc
+               rsv  ResponseFilterFunc
        }
        type test struct {
                name    string
@@ -235,7 +272,8 @@ func TestRegisterPluginConcurrent(t *testing.T) {
                        args: args{
                                name: "test_concurrent-1",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrPluginRegistered{"test_concurrent-1"},
                },
@@ -244,7 +282,8 @@ func TestRegisterPluginConcurrent(t *testing.T) {
                        args: args{
                                name: "test_concurrent-2",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrPluginRegistered{"test_concurrent-2"},
                },
@@ -253,7 +292,8 @@ func TestRegisterPluginConcurrent(t *testing.T) {
                        args: args{
                                name: "test_concurrent-2",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrPluginRegistered{"test_concurrent-2"},
                },
@@ -262,7 +302,8 @@ func TestRegisterPluginConcurrent(t *testing.T) {
                        args: args{
                                name: "test_concurrent-2",
                                pc:   emptyParseConf,
-                               sv:   emptyFilter,
+                               sv:   emptyRequestFilter,
+                               rsv:  emptyResponseFilter,
                        },
                        wantErr: ErrPluginRegistered{"test_concurrent-2"},
                },
@@ -271,7 +312,7 @@ func TestRegisterPluginConcurrent(t *testing.T) {
                t.Run(tt.name, func(t *testing.T) {
                        for i := 0; i < 3; i++ {
                                go func(tt test) {
-                                       if err := RegisterPlugin(tt.args.name, 
tt.args.pc, tt.args.sv); !assert.Equal(t, tt.wantErr, err) {
+                                       if err := RegisterPlugin(tt.args.name, 
tt.args.pc, tt.args.sv, tt.args.rsv); !assert.Equal(t, tt.wantErr, err) {
                                                t.Errorf("RegisterPlugin() 
error = %v, wantErr %v", err, tt.wantErr)
                                        }
                                }(tt)
@@ -300,8 +341,8 @@ func TestFilter(t *testing.T) {
                assert.Equal(t, "bar", conf.(string))
        }
 
-       RegisterPlugin("foo", fooParseConf, fooFilter)
-       RegisterPlugin("bar", barParseConf, barFilter)
+       RegisterPlugin("foo", fooParseConf, fooFilter, emptyResponseFilter)
+       RegisterPlugin("bar", barParseConf, barFilter, emptyResponseFilter)
 
        builder := flatbuffers.NewBuilder(1024)
        fooName := builder.CreateString("foo")
@@ -350,8 +391,8 @@ func TestFilter_SetRespHeaderDoNotBreakReq(t *testing.T) {
        filterSetRespFilter := func(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request) {
                w.Header().Add("foo", "baz")
        }
-       RegisterPlugin("bar", barParseConf, barFilter)
-       RegisterPlugin("filterSetResp", filterSetRespParseConf, 
filterSetRespFilter)
+       RegisterPlugin("bar", barParseConf, barFilter, emptyResponseFilter)
+       RegisterPlugin("filterSetResp", filterSetRespParseConf, 
filterSetRespFilter, emptyResponseFilter)
 
        builder := flatbuffers.NewBuilder(1024)
        barName := builder.CreateString("bar")
@@ -386,7 +427,7 @@ func TestFilter_SetRespHeader(t *testing.T) {
                r.RespHeader().Set("foo", "baz")
        }
 
-       RegisterPlugin("filterSetRespHeader", filterSetRespHeaderParseConf, 
filterSetRespHeaderFilter)
+       RegisterPlugin("filterSetRespHeader", filterSetRespHeaderParseConf, 
filterSetRespHeaderFilter, emptyResponseFilter)
 
        builder := flatbuffers.NewBuilder(1024)
        filterSetRespName := builder.CreateString("filterSetRespHeader")
diff --git a/pkg/http/http.go b/pkg/http/http.go
index 30aaa60..ca3cbd7 100644
--- a/pkg/http/http.go
+++ b/pkg/http/http.go
@@ -79,6 +79,35 @@ type Request interface {
        RespHeader() http.Header
 }
 
+// Response represents the HTTP response from the upstream received by APISIX.
+// In order to avoid semantic misunderstanding,
+// we also use Response to represent the rewritten response from Plugin Runner.
+// Therefore, any instance that implements the Response interface will be 
readable and rewritable.
+type Response interface {
+       // ID returns the request id
+       ID() uint32
+
+       // StatusCode returns the response code
+       StatusCode() int
+
+       // Header returns the response header.
+       //
+       // It allows you to add or set response headers before reaching the 
client.
+       Header() Header
+
+       // Write rewrites the origin response data.
+       //
+       // Unlike `ResponseWriter.Write`, we don't need to 
WriteHeader(http.StatusOK)
+       // before writing the data
+       // Because APISIX will convert code 0 to 200.
+       Write(b []byte) (int, error)
+
+       // WriteHeader rewrites the origin response StatusCode
+       //
+       // WriteHeader can't override written status.
+       WriteHeader(statusCode int)
+}
+
 // Header is like http.Header, but only implements the subset of its methods
 type Header interface {
        // Set sets the header entries associated with key to the single 
element value.
diff --git a/pkg/plugin/plugin.go b/pkg/plugin/plugin.go
index c6b59bc..14540bc 100644
--- a/pkg/plugin/plugin.go
+++ b/pkg/plugin/plugin.go
@@ -33,18 +33,22 @@ type Plugin interface {
        // configuration can't be parsed, it will be skipped.
        ParseConf(in []byte) (conf interface{}, err error)
 
-       // Filter is the method to handle request.
+       // RequestFilter is the method to handle request.
        // It is like the `http.ServeHTTP`, plus the ctx and the configuration 
created by
        // ParseConf.
        //
        // When the `w` is written, the execution of plugin chain will be 
stopped.
        // We don't use onion model like Gin/Caddy because we don't serve the 
whole request lifecycle
        // inside the runner. The plugin is only a filter running at one stage.
-       Filter(conf interface{}, w http.ResponseWriter, r pkgHTTP.Request)
+       RequestFilter(conf interface{}, w http.ResponseWriter, r 
pkgHTTP.Request)
+
+       // ResponseFilter is the method to handle response.
+       // This filter is currently only pre-defined and has not been 
implemented.
+       ResponseFilter(conf interface{}, w pkgHTTP.Response)
 }
 
 // RegisterPlugin register a plugin. Plugin which has the same name can't be 
registered twice.
 // This method should be called before calling `runner.Run`.
 func RegisterPlugin(p Plugin) error {
-       return plugin.RegisterPlugin(p.Name(), p.ParseConf, p.Filter)
+       return plugin.RegisterPlugin(p.Name(), p.ParseConf, p.RequestFilter, 
p.ResponseFilter)
 }

Reply via email to