Skip to content

Commit

Permalink
feat: add Args
Browse files Browse the repository at this point in the history
  • Loading branch information
spacewander committed May 28, 2021
1 parent 56ca824 commit 05f4082
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 2 deletions.
80 changes: 79 additions & 1 deletion internal/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package http
import (
"net"
"net/http"
"net/url"
"reflect"
"sync"

pkgHTTP "github.com/apache/apisix-go-plugin-runner/pkg/http"
Expand All @@ -33,6 +35,9 @@ type Request struct {

hdr *Header
rawHdr http.Header

args url.Values
rawArgs url.Values
}

func (r *Request) ConfToken() uint32 {
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -130,13 +167,54 @@ 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)
}
if hdrVec > 0 {
hrc.RewriteAddHeaders(builder, hdrVec)
}
if argsVec > 0 {
hrc.RewriteAddArgs(builder, argsVec)
}
rewrite := hrc.RewriteEnd(builder)

hrc.RespStart(builder)
Expand Down
66 changes: 65 additions & 1 deletion internal/http/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package http
import (
"net"
"net/http"
"net/url"
"testing"

"github.com/apache/apisix-go-plugin-runner/internal/util"
Expand Down Expand Up @@ -49,6 +50,7 @@ type reqOpt struct {
method A6.Method
path string
headers []pair
args []pair
}

func buildReq(opt reqOpt) []byte {
Expand Down Expand Up @@ -78,14 +80,36 @@ 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)
}
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)
Expand All @@ -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()
Expand Down Expand Up @@ -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)
}
3 changes: 3 additions & 0 deletions pkg/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package http
import (
"net"
"net/http"
"net/url"
)

// Request represents the HTTP request received by APISIX.
Expand All @@ -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
Expand Down

0 comments on commit 05f4082

Please sign in to comment.