fill request with header and cookie data
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
7a39d86018
commit
505c59ba75
6
go.mod
6
go.mod
@ -1,8 +1,8 @@
|
||||
module github.com/unistack-org/micro-server-http/v3
|
||||
module go.unistack.org/micro-server-http/v3
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/unistack-org/micro/v3 v3.7.6
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
|
||||
go.unistack.org/micro/v3 v3.8.5
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309
|
||||
)
|
||||
|
11
go.sum
11
go.sum
@ -7,12 +7,13 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
|
||||
github.com/unistack-org/micro-proto v0.0.9 h1:KrWLS4FUX7UAWNAilQf70uad6ZPf/0EudeddCXllRVc=
|
||||
github.com/unistack-org/micro-proto v0.0.9/go.mod h1:Cckwmzd89gvS7ThxzZp9kQR/EOdksFQcsTAtDDyKwrg=
|
||||
github.com/unistack-org/micro/v3 v3.7.6 h1:cobNkaicZR+8nbDWRUmX3/CSLh6ZNSytK2zWth4s4IM=
|
||||
github.com/unistack-org/micro/v3 v3.7.6/go.mod h1:Ke/8WJlNZi4ZYwL9HcsANAbQ66/HocTBEZM+od99/mM=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
|
||||
go.unistack.org/micro-proto/v3 v3.1.0 h1:q39FwjFiRZn+Ux/tt+d3bJTmDtsQQWa+3SLYVo1vLfA=
|
||||
go.unistack.org/micro-proto/v3 v3.1.0/go.mod h1:DpRhYCBXlmSJ/AAXTmntvlh7kQkYU6eFvlmYAx4BQS8=
|
||||
go.unistack.org/micro/v3 v3.8.5 h1:DIYWRsQF+NPhKZP45sCtNsUhaRw6u2+Ps7U+pKU7i3s=
|
||||
go.unistack.org/micro/v3 v3.8.5/go.mod h1:KMMmOmbgo/D52/rCAbqeKbBsgEEbSKM69he54J3ZIuA=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
27
handler.go
27
handler.go
@ -9,13 +9,13 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/unistack-org/micro/v3/errors"
|
||||
"github.com/unistack-org/micro/v3/logger"
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
"github.com/unistack-org/micro/v3/register"
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
rhttp "github.com/unistack-org/micro/v3/util/http"
|
||||
rflutil "github.com/unistack-org/micro/v3/util/reflect"
|
||||
"go.unistack.org/micro/v3/errors"
|
||||
"go.unistack.org/micro/v3/logger"
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
"go.unistack.org/micro/v3/register"
|
||||
"go.unistack.org/micro/v3/server"
|
||||
rhttp "go.unistack.org/micro/v3/util/http"
|
||||
rflutil "go.unistack.org/micro/v3/util/reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -31,8 +31,8 @@ var (
|
||||
type patHandler struct {
|
||||
mtype *methodType
|
||||
rcvr reflect.Value
|
||||
name string
|
||||
pat *rhttp.Trie
|
||||
name string
|
||||
}
|
||||
|
||||
type httpHandler struct {
|
||||
@ -68,7 +68,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
ct := DefaultContentType
|
||||
if htype := r.Header.Get("Content-Type"); htype != "" {
|
||||
if htype := r.Header.Get(metadata.HeaderContentType); htype != "" {
|
||||
ct = htype
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
path := r.URL.Path
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
h.errorHandler(ctx, nil, w, r, fmt.Errorf("path must contains /"), http.StatusBadRequest)
|
||||
h.errorHandler(ctx, nil, w, r, fmt.Errorf("path must starts with /"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -117,11 +117,9 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
var hldr patHandler
|
||||
var handler *httpHandler
|
||||
|
||||
//fmt.Printf("try to find handler\n")
|
||||
for _, hpat := range h.handlers {
|
||||
handlertmp := hpat.(*httpHandler)
|
||||
for _, hldrtmp := range handlertmp.handlers[r.Method] {
|
||||
//fmt.Printf("ssss method %v path %v %#+v\n", r.Method, path, hldrtmp)
|
||||
_, mp, ok := hldrtmp.pat.Search(r.Method, path)
|
||||
if ok {
|
||||
match = true
|
||||
@ -171,7 +169,6 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
replyv = reflect.New(hldr.mtype.ReplyType.Elem())
|
||||
|
||||
function := hldr.mtype.method.Func
|
||||
// function := hldr.rcvr
|
||||
var returnValues []reflect.Value
|
||||
|
||||
if err = cf.ReadBody(r.Body, argv.Interface()); err != nil && err != io.EOF {
|
||||
@ -241,13 +238,13 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
scode := int(200)
|
||||
appErr := fn(ctx, hr, replyv.Interface())
|
||||
|
||||
w.Header().Set("Content-Type", ct)
|
||||
w.Header().Set(metadata.HeaderContentType, ct)
|
||||
if md, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||
for k, v := range md {
|
||||
w.Header().Set(k, v)
|
||||
}
|
||||
}
|
||||
if nct := w.Header().Get("Content-Type"); nct != ct {
|
||||
if nct := w.Header().Get(metadata.HeaderContentType); nct != ct {
|
||||
if cf, err = h.newCodec(nct); err != nil {
|
||||
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
|
12
http.go
12
http.go
@ -13,12 +13,12 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/unistack-org/micro/v3/broker"
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
"github.com/unistack-org/micro/v3/logger"
|
||||
"github.com/unistack-org/micro/v3/register"
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
rhttp "github.com/unistack-org/micro/v3/util/http"
|
||||
"go.unistack.org/micro/v3/broker"
|
||||
"go.unistack.org/micro/v3/codec"
|
||||
"go.unistack.org/micro/v3/logger"
|
||||
"go.unistack.org/micro/v3/register"
|
||||
"go.unistack.org/micro/v3/server"
|
||||
rhttp "go.unistack.org/micro/v3/util/http"
|
||||
"golang.org/x/net/netutil"
|
||||
)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
"go.unistack.org/micro/v3/codec"
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
)
|
||||
|
||||
type httpMessage struct {
|
||||
|
23
options.go
23
options.go
@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
"go.unistack.org/micro/v3/server"
|
||||
)
|
||||
|
||||
// SetError pass error to caller
|
||||
@ -125,3 +125,24 @@ type registerRPCHandlerKey struct{}
|
||||
func RegisterRPCHandler(b bool) server.Option {
|
||||
return server.SetOption(registerRPCHandlerKey{}, b)
|
||||
}
|
||||
|
||||
type headerKey struct{}
|
||||
|
||||
type handlerOptions struct {
|
||||
headers []string
|
||||
cookies []string
|
||||
}
|
||||
|
||||
type FillRequestOption func(*handlerOptions)
|
||||
|
||||
func Header(headers ...string) FillRequestOption {
|
||||
return func(o *handlerOptions) {
|
||||
o.headers = append(o.headers, headers...)
|
||||
}
|
||||
}
|
||||
|
||||
func Cookie(cookies ...string) FillRequestOption {
|
||||
return func(o *handlerOptions) {
|
||||
o.cookies = append(o.cookies, cookies...)
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ package http
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
"go.unistack.org/micro/v3/codec"
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
"go.unistack.org/micro/v3/server"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
"go.unistack.org/micro/v3/server"
|
||||
)
|
||||
|
||||
type methodType struct {
|
||||
|
@ -7,11 +7,11 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/unistack-org/micro/v3/broker"
|
||||
"github.com/unistack-org/micro/v3/codec"
|
||||
"github.com/unistack-org/micro/v3/metadata"
|
||||
"github.com/unistack-org/micro/v3/register"
|
||||
"github.com/unistack-org/micro/v3/server"
|
||||
"go.unistack.org/micro/v3/broker"
|
||||
"go.unistack.org/micro/v3/codec"
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
"go.unistack.org/micro/v3/register"
|
||||
"go.unistack.org/micro/v3/server"
|
||||
)
|
||||
|
||||
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
|
||||
|
55
util.go
Normal file
55
util.go
Normal file
@ -0,0 +1,55 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
rutil "go.unistack.org/micro/v3/util/reflect"
|
||||
)
|
||||
|
||||
func FillRequest(ctx context.Context, req interface{}, opts ...FillRequestOption) error {
|
||||
var err error
|
||||
options := handlerOptions{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
for idx := 0; idx < len(options.headers)/2; idx += 2 {
|
||||
k := http.CanonicalHeaderKey(options.headers[idx])
|
||||
v, ok := md[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if err = rutil.SetFieldByPath(req, v, k); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cookies := strings.Split(md["Cookie"], ";")
|
||||
cmd := make(map[string]string, len(cookies))
|
||||
for _, cookie := range cookies {
|
||||
kv := strings.Split(cookie, "=")
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
cmd[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
|
||||
}
|
||||
for idx := 0; idx < len(options.cookies)/2; idx += 2 {
|
||||
k := http.CanonicalHeaderKey(options.cookies[idx])
|
||||
v, ok := cmd[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if err = rutil.SetFieldByPath(req, v, k); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
56
util_test.go
Normal file
56
util_test.go
Normal file
@ -0,0 +1,56 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.unistack.org/micro/v3/metadata"
|
||||
)
|
||||
|
||||
func TestFillrequest(t *testing.T) {
|
||||
md := metadata.New(1)
|
||||
md.Set("ClientID", "xxx")
|
||||
type request struct {
|
||||
Token string
|
||||
ClientID string
|
||||
}
|
||||
ctx := context.Background()
|
||||
hreq, _ := http.NewRequestWithContext(ctx, http.MethodGet, "/v1", nil)
|
||||
cookie1 := &http.Cookie{Name: "Token", Value: "zzz"}
|
||||
cookie2 := &http.Cookie{Name: "Token", Value: "zzz"}
|
||||
hreq.AddCookie(cookie1)
|
||||
hreq.AddCookie(cookie2)
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_ = hreq.Write(buf)
|
||||
var cookie string
|
||||
var line string
|
||||
var err error
|
||||
for {
|
||||
line, err = buf.ReadString('\n')
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if strings.Contains(line, "Cookie") {
|
||||
cookie = strings.TrimSpace(strings.Split(line, ":")[1])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
md.Set("Cookie", cookie)
|
||||
ctx = metadata.NewIncomingContext(ctx, md)
|
||||
req := &request{}
|
||||
|
||||
if err := FillRequest(ctx, req, Cookie("Token", "true"), Header("ClientID", "true")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if req.ClientID != "xxx" {
|
||||
t.Fatalf("FillRequest error: %#+v", req)
|
||||
}
|
||||
if req.Token != "zzz" {
|
||||
t.Fatalf("FillRequest error: %#+v", req)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user