You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2021/05/31 02:07:27 UTC
[apisix-go-plugin-runner] 20/22: feat: add Args
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
commit 05f40828227555cb4b1e181dcaddd2a70cfb543a
Author: spacewander <sp...@gmail.com>
AuthorDate: Fri May 28 10:18:14 2021 +0800
feat: add Args
---
internal/http/request.go | 80 ++++++++++++++++++++++++++++++++++++++++++-
internal/http/request_test.go | 66 ++++++++++++++++++++++++++++++++++-
pkg/http/http.go | 3 ++
3 files changed, 147 insertions(+), 2 deletions(-)
diff --git a/internal/http/request.go b/internal/http/request.go
index c7f2e8d..33b9f74 100644
--- a/internal/http/request.go
+++ b/internal/http/request.go
@@ -17,6 +17,8 @@ package http
import (
"net"
"net/http"
+ "net/url"
+ "reflect"
"sync"
pkgHTTP "github.com/apache/apisix-go-plugin-runner/pkg/http"
@@ -33,6 +35,9 @@ type Request struct {
hdr *Header
rawHdr http.Header
+
+ args url.Values
+ rawArgs url.Values
}
func (r *Request) ConfToken() uint32 {
@@ -79,13 +84,45 @@ func (r *Request) Header() pkgHTTP.Header {
return r.hdr
}
+func cloneUrlValues(oldV url.Values) url.Values {
+ nv := 0
+ for _, vv := range oldV {
+ nv += len(vv)
+ }
+ sv := make([]string, nv)
+ newV := make(url.Values, len(oldV))
+ for k, vv := range oldV {
+ n := copy(sv, vv)
+ newV[k] = sv[:n:n]
+ sv = sv[n:]
+ }
+ return newV
+}
+
+func (r *Request) Args() url.Values {
+ if r.args == nil {
+ args := url.Values{}
+ size := r.r.ArgsLength()
+ obj := A6.TextEntry{}
+ for i := 0; i < size; i++ {
+ if r.r.Args(&obj, i) {
+ args.Add(string(obj.Name()), string(obj.Value()))
+ }
+ }
+ r.args = args
+ r.rawArgs = cloneUrlValues(args)
+ }
+ return r.args
+}
+
func (r *Request) Reset() {
r.path = nil
r.hdr = nil
+ r.args = nil
}
func (r *Request) FetchChanges(id uint32, builder *flatbuffers.Builder) bool {
- if r.path == nil && r.hdr == nil {
+ if r.path == nil && r.hdr == nil && r.args == nil {
return false
}
@@ -130,6 +167,44 @@ func (r *Request) FetchChanges(id uint32, builder *flatbuffers.Builder) bool {
hdrVec = builder.EndVector(size)
}
+ var argsVec flatbuffers.UOffsetT
+ if r.args != nil {
+ args := []flatbuffers.UOffsetT{}
+ oldArgs := r.rawArgs
+ newArgs := r.args
+ for n := range oldArgs {
+ if _, ok := newArgs[n]; !ok {
+ // deleted
+ name := builder.CreateString(n)
+ A6.TextEntryStart(builder)
+ A6.TextEntryAddName(builder, name)
+ te := A6.TextEntryEnd(builder)
+ args = append(args, te)
+ }
+ }
+ for n, v := range newArgs {
+ if raw, ok := oldArgs[n]; !ok || !reflect.DeepEqual(raw, v) {
+ // set / add
+ for _, vv := range v {
+ name := builder.CreateString(n)
+ value := builder.CreateString(vv)
+ A6.TextEntryStart(builder)
+ A6.TextEntryAddName(builder, name)
+ A6.TextEntryAddValue(builder, value)
+ te := A6.TextEntryEnd(builder)
+ args = append(args, te)
+ }
+ }
+ }
+ size := len(args)
+ hrc.RewriteStartArgsVector(builder, size)
+ for i := size - 1; i >= 0; i-- {
+ te := args[i]
+ builder.PrependUOffsetT(te)
+ }
+ argsVec = builder.EndVector(size)
+ }
+
hrc.RewriteStart(builder)
if path > 0 {
hrc.RewriteAddPath(builder, path)
@@ -137,6 +212,9 @@ func (r *Request) FetchChanges(id uint32, builder *flatbuffers.Builder) bool {
if hdrVec > 0 {
hrc.RewriteAddHeaders(builder, hdrVec)
}
+ if argsVec > 0 {
+ hrc.RewriteAddArgs(builder, argsVec)
+ }
rewrite := hrc.RewriteEnd(builder)
hrc.RespStart(builder)
diff --git a/internal/http/request_test.go b/internal/http/request_test.go
index accaa38..64f3ebf 100644
--- a/internal/http/request_test.go
+++ b/internal/http/request_test.go
@@ -17,6 +17,7 @@ package http
import (
"net"
"net/http"
+ "net/url"
"testing"
"github.com/apache/apisix-go-plugin-runner/internal/util"
@@ -49,6 +50,7 @@ type reqOpt struct {
method A6.Method
path string
headers []pair
+ args []pair
}
func buildReq(opt reqOpt) []byte {
@@ -78,7 +80,7 @@ func buildReq(opt reqOpt) []byte {
hdrs = append(hdrs, te)
}
size := len(hdrs)
- hrc.StopStartHeadersVector(builder, size)
+ hrc.RewriteStartHeadersVector(builder, size)
for i := size - 1; i >= 0; i-- {
te := hdrs[i]
builder.PrependUOffsetT(te)
@@ -86,6 +88,28 @@ func buildReq(opt reqOpt) []byte {
hdrVec = builder.EndVector(size)
}
+ argsLen := len(opt.args)
+ var argsVec flatbuffers.UOffsetT
+ if argsLen > 0 {
+ args := []flatbuffers.UOffsetT{}
+ for _, v := range opt.args {
+ name := builder.CreateString(v.name)
+ value := builder.CreateString(v.value)
+ A6.TextEntryStart(builder)
+ A6.TextEntryAddName(builder, name)
+ A6.TextEntryAddValue(builder, value)
+ te := A6.TextEntryEnd(builder)
+ args = append(args, te)
+ }
+ size := len(args)
+ hrc.RewriteStartArgsVector(builder, size)
+ for i := size - 1; i >= 0; i-- {
+ te := args[i]
+ builder.PrependUOffsetT(te)
+ }
+ argsVec = builder.EndVector(size)
+ }
+
hrc.ReqStart(builder)
hrc.ReqAddId(builder, 233)
hrc.ReqAddConfToken(builder, 1)
@@ -101,6 +125,9 @@ func buildReq(opt reqOpt) []byte {
if hdrVec > 0 {
hrc.ReqAddHeaders(builder, hdrVec)
}
+ if argsVec > 0 {
+ hrc.ReqAddArgs(builder, argsVec)
+ }
r := hrc.ReqEnd(builder)
builder.Finish(r)
return builder.FinishedBytes()
@@ -187,3 +214,40 @@ func TestHeader(t *testing.T) {
}
assert.Equal(t, exp, res)
}
+
+func TestArgs(t *testing.T) {
+ out := buildReq(reqOpt{args: []pair{
+ {"del", "a"},
+ {"override", "a"},
+ {"add", "a"},
+ }})
+ r := CreateRequest(out)
+ args := r.Args()
+ args.Add("add", "b")
+ args.Set("set", "a")
+ args.Set("override", "b")
+ args.Del("del")
+
+ builder := util.GetBuilder()
+ assert.True(t, r.FetchChanges(1, builder))
+ rewrite := getRewriteAction(t, builder)
+
+ exp := url.Values{}
+ exp.Set("set", "a")
+ exp.Set("override", "b")
+ exp.Add("add", "a")
+ exp.Add("add", "b")
+ deleted := ""
+ res := url.Values{}
+ for i := 0; i < rewrite.ArgsLength(); i++ {
+ e := &A6.TextEntry{}
+ rewrite.Args(e, i)
+ if e.Value() == nil {
+ deleted = string(e.Name())
+ } else {
+ res.Add(string(e.Name()), string(e.Value()))
+ }
+ }
+ assert.Equal(t, exp, res)
+ assert.Equal(t, "del", deleted)
+}
diff --git a/pkg/http/http.go b/pkg/http/http.go
index cbbceeb..cfc4284 100644
--- a/pkg/http/http.go
+++ b/pkg/http/http.go
@@ -17,6 +17,7 @@ package http
import (
"net"
"net/http"
+ "net/url"
)
// Request represents the HTTP request received by APISIX.
@@ -43,6 +44,8 @@ type Request interface {
SetPath([]byte)
// Header returns the HTTP headers
Header() Header
+ // Args returns the query string
+ Args() url.Values
}
// Header is like http.Header, but only implements the subset of its methods