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
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/unistack-org/micro/v3 v3.7.6
|
go.unistack.org/micro/v3 v3.8.5
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
|
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 h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
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/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=
|
go.unistack.org/micro-proto/v3 v3.1.0 h1:q39FwjFiRZn+Ux/tt+d3bJTmDtsQQWa+3SLYVo1vLfA=
|
||||||
github.com/unistack-org/micro-proto v0.0.9/go.mod h1:Cckwmzd89gvS7ThxzZp9kQR/EOdksFQcsTAtDDyKwrg=
|
go.unistack.org/micro-proto/v3 v3.1.0/go.mod h1:DpRhYCBXlmSJ/AAXTmntvlh7kQkYU6eFvlmYAx4BQS8=
|
||||||
github.com/unistack-org/micro/v3 v3.7.6 h1:cobNkaicZR+8nbDWRUmX3/CSLh6ZNSytK2zWth4s4IM=
|
go.unistack.org/micro/v3 v3.8.5 h1:DIYWRsQF+NPhKZP45sCtNsUhaRw6u2+Ps7U+pKU7i3s=
|
||||||
github.com/unistack-org/micro/v3 v3.7.6/go.mod h1:Ke/8WJlNZi4ZYwL9HcsANAbQ66/HocTBEZM+od99/mM=
|
go.unistack.org/micro/v3 v3.8.5/go.mod h1:KMMmOmbgo/D52/rCAbqeKbBsgEEbSKM69he54J3ZIuA=
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
|
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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=
|
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"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/unistack-org/micro/v3/errors"
|
"go.unistack.org/micro/v3/errors"
|
||||||
"github.com/unistack-org/micro/v3/logger"
|
"go.unistack.org/micro/v3/logger"
|
||||||
"github.com/unistack-org/micro/v3/metadata"
|
"go.unistack.org/micro/v3/metadata"
|
||||||
"github.com/unistack-org/micro/v3/register"
|
"go.unistack.org/micro/v3/register"
|
||||||
"github.com/unistack-org/micro/v3/server"
|
"go.unistack.org/micro/v3/server"
|
||||||
rhttp "github.com/unistack-org/micro/v3/util/http"
|
rhttp "go.unistack.org/micro/v3/util/http"
|
||||||
rflutil "github.com/unistack-org/micro/v3/util/reflect"
|
rflutil "go.unistack.org/micro/v3/util/reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -31,8 +31,8 @@ var (
|
|||||||
type patHandler struct {
|
type patHandler struct {
|
||||||
mtype *methodType
|
mtype *methodType
|
||||||
rcvr reflect.Value
|
rcvr reflect.Value
|
||||||
name string
|
|
||||||
pat *rhttp.Trie
|
pat *rhttp.Trie
|
||||||
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpHandler struct {
|
type httpHandler struct {
|
||||||
@ -68,7 +68,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ct := DefaultContentType
|
ct := DefaultContentType
|
||||||
if htype := r.Header.Get("Content-Type"); htype != "" {
|
if htype := r.Header.Get(metadata.HeaderContentType); htype != "" {
|
||||||
ct = htype
|
ct = htype
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
path := r.URL.Path
|
path := r.URL.Path
|
||||||
if !strings.HasPrefix(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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,11 +117,9 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
var hldr patHandler
|
var hldr patHandler
|
||||||
var handler *httpHandler
|
var handler *httpHandler
|
||||||
|
|
||||||
//fmt.Printf("try to find handler\n")
|
|
||||||
for _, hpat := range h.handlers {
|
for _, hpat := range h.handlers {
|
||||||
handlertmp := hpat.(*httpHandler)
|
handlertmp := hpat.(*httpHandler)
|
||||||
for _, hldrtmp := range handlertmp.handlers[r.Method] {
|
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)
|
_, mp, ok := hldrtmp.pat.Search(r.Method, path)
|
||||||
if ok {
|
if ok {
|
||||||
match = true
|
match = true
|
||||||
@ -171,7 +169,6 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
replyv = reflect.New(hldr.mtype.ReplyType.Elem())
|
replyv = reflect.New(hldr.mtype.ReplyType.Elem())
|
||||||
|
|
||||||
function := hldr.mtype.method.Func
|
function := hldr.mtype.method.Func
|
||||||
// function := hldr.rcvr
|
|
||||||
var returnValues []reflect.Value
|
var returnValues []reflect.Value
|
||||||
|
|
||||||
if err = cf.ReadBody(r.Body, argv.Interface()); err != nil && err != io.EOF {
|
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)
|
scode := int(200)
|
||||||
appErr := fn(ctx, hr, replyv.Interface())
|
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 {
|
if md, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||||
for k, v := range md {
|
for k, v := range md {
|
||||||
w.Header().Set(k, v)
|
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 {
|
if cf, err = h.newCodec(nct); err != nil {
|
||||||
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
|
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
|
12
http.go
12
http.go
@ -13,12 +13,12 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/unistack-org/micro/v3/broker"
|
"go.unistack.org/micro/v3/broker"
|
||||||
"github.com/unistack-org/micro/v3/codec"
|
"go.unistack.org/micro/v3/codec"
|
||||||
"github.com/unistack-org/micro/v3/logger"
|
"go.unistack.org/micro/v3/logger"
|
||||||
"github.com/unistack-org/micro/v3/register"
|
"go.unistack.org/micro/v3/register"
|
||||||
"github.com/unistack-org/micro/v3/server"
|
"go.unistack.org/micro/v3/server"
|
||||||
rhttp "github.com/unistack-org/micro/v3/util/http"
|
rhttp "go.unistack.org/micro/v3/util/http"
|
||||||
"golang.org/x/net/netutil"
|
"golang.org/x/net/netutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/unistack-org/micro/v3/codec"
|
"go.unistack.org/micro/v3/codec"
|
||||||
"github.com/unistack-org/micro/v3/metadata"
|
"go.unistack.org/micro/v3/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpMessage struct {
|
type httpMessage struct {
|
||||||
|
23
options.go
23
options.go
@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/unistack-org/micro/v3/server"
|
"go.unistack.org/micro/v3/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetError pass error to caller
|
// SetError pass error to caller
|
||||||
@ -125,3 +125,24 @@ type registerRPCHandlerKey struct{}
|
|||||||
func RegisterRPCHandler(b bool) server.Option {
|
func RegisterRPCHandler(b bool) server.Option {
|
||||||
return server.SetOption(registerRPCHandlerKey{}, b)
|
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 (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/unistack-org/micro/v3/codec"
|
"go.unistack.org/micro/v3/codec"
|
||||||
"github.com/unistack-org/micro/v3/metadata"
|
"go.unistack.org/micro/v3/metadata"
|
||||||
"github.com/unistack-org/micro/v3/server"
|
"go.unistack.org/micro/v3/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/unistack-org/micro/v3/server"
|
"go.unistack.org/micro/v3/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
type methodType struct {
|
type methodType struct {
|
||||||
|
@ -7,11 +7,11 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/unistack-org/micro/v3/broker"
|
"go.unistack.org/micro/v3/broker"
|
||||||
"github.com/unistack-org/micro/v3/codec"
|
"go.unistack.org/micro/v3/codec"
|
||||||
"github.com/unistack-org/micro/v3/metadata"
|
"go.unistack.org/micro/v3/metadata"
|
||||||
"github.com/unistack-org/micro/v3/register"
|
"go.unistack.org/micro/v3/register"
|
||||||
"github.com/unistack-org/micro/v3/server"
|
"go.unistack.org/micro/v3/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
|
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