Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
2
vendor/github.com/go-kit/kit/transport/doc.go
generated
vendored
Normal file
2
vendor/github.com/go-kit/kit/transport/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package transport contains bindings to concrete transports.
|
||||
package transport
|
||||
37
vendor/github.com/go-kit/kit/transport/grpc/README.md
generated
vendored
Normal file
37
vendor/github.com/go-kit/kit/transport/grpc/README.md
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# grpc
|
||||
|
||||
[gRPC](http://www.grpc.io/) is an excellent, modern IDL and transport for microservices.
|
||||
If you're starting a greenfield project, Go kit strongly recommends gRPC as your default transport.
|
||||
And using gRPC and Go kit together is very simple.
|
||||
|
||||
First, define your service using protobuf3.
|
||||
This is explained [in gRPC documentation](http://www.grpc.io/docs/#defining-a-service).
|
||||
See [add.proto](https://github.com/go-kit/kit/blob/ec8b02591ee873433565a1ae9d317353412d1d27/examples/addsvc/pb/add.proto) for an example.
|
||||
Make sure the proto definition matches your service's Go kit (interface) definition.
|
||||
|
||||
Next, get the protoc compiler.
|
||||
Unfortunately, this needs to be done from source.
|
||||
Fortunately, it's pretty straightforward.
|
||||
|
||||
```
|
||||
brew install autoconf automake libtool
|
||||
git clone https://github.com/google/protobuf
|
||||
cd protobuf
|
||||
./autogen.sh ; ./configure ; make ; make install
|
||||
```
|
||||
|
||||
Then, compile your service definition, from .proto to .go.
|
||||
|
||||
```
|
||||
protoc add.proto --go_out=plugins=grpc:.
|
||||
```
|
||||
|
||||
Finally, write a tiny binding from your service definition to the gRPC definition.
|
||||
It's a simple conversion from one domain to another.
|
||||
See [grpc_binding.go](https://github.com/go-kit/kit/blob/ec8b02591ee873433565a1ae9d317353412d1d27/examples/addsvc/grpc_binding.go) for an example.
|
||||
|
||||
That's it!
|
||||
The gRPC binding can be bound to a listener and serve normal gRPC requests.
|
||||
And within your service, you can use standard Go kit components and idioms.
|
||||
See [addsvc](https://github.com/go-kit/kit/tree/master/examples/addsvc) for a complete working example with gRPC support.
|
||||
And remember: Go kit services can support multiple transports simultaneously.
|
||||
50
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/client.go
generated
vendored
Normal file
50
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/client.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
grpctransport "github.com/go-kit/kit/transport/grpc"
|
||||
"github.com/go-kit/kit/transport/grpc/_grpc_test/pb"
|
||||
)
|
||||
|
||||
type clientBinding struct {
|
||||
test endpoint.Endpoint
|
||||
}
|
||||
|
||||
func (c *clientBinding) Test(ctx context.Context, a string, b int64) (context.Context, string, error) {
|
||||
response, err := c.test(ctx, TestRequest{A: a, B: b})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
r := response.(*TestResponse)
|
||||
return r.Ctx, r.V, nil
|
||||
}
|
||||
|
||||
func NewClient(cc *grpc.ClientConn) Service {
|
||||
return &clientBinding{
|
||||
test: grpctransport.NewClient(
|
||||
cc,
|
||||
"pb.Test",
|
||||
"Test",
|
||||
encodeRequest,
|
||||
decodeResponse,
|
||||
&pb.TestResponse{},
|
||||
grpctransport.ClientBefore(
|
||||
injectCorrelationID,
|
||||
),
|
||||
grpctransport.ClientBefore(
|
||||
displayClientRequestHeaders,
|
||||
),
|
||||
grpctransport.ClientAfter(
|
||||
displayClientResponseHeaders,
|
||||
displayClientResponseTrailers,
|
||||
),
|
||||
grpctransport.ClientAfter(
|
||||
extractConsumedCorrelationID,
|
||||
),
|
||||
).Endpoint(),
|
||||
}
|
||||
}
|
||||
141
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/context_metadata.go
generated
vendored
Normal file
141
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/context_metadata.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
type metaContext string
|
||||
|
||||
const (
|
||||
correlationID metaContext = "correlation-id"
|
||||
responseHDR metaContext = "my-response-header"
|
||||
responseTRLR metaContext = "my-response-trailer"
|
||||
correlationIDTRLR metaContext = "correlation-id-consumed"
|
||||
)
|
||||
|
||||
/* client before functions */
|
||||
|
||||
func injectCorrelationID(ctx context.Context, md *metadata.MD) context.Context {
|
||||
if hdr, ok := ctx.Value(correlationID).(string); ok {
|
||||
fmt.Printf("\tClient found correlationID %q in context, set metadata header\n", hdr)
|
||||
(*md)[string(correlationID)] = append((*md)[string(correlationID)], hdr)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func displayClientRequestHeaders(ctx context.Context, md *metadata.MD) context.Context {
|
||||
if len(*md) > 0 {
|
||||
fmt.Println("\tClient >> Request Headers:")
|
||||
for key, val := range *md {
|
||||
fmt.Printf("\t\t%s: %s\n", key, val[len(val)-1])
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
/* server before functions */
|
||||
|
||||
func extractCorrelationID(ctx context.Context, md metadata.MD) context.Context {
|
||||
if hdr, ok := md[string(correlationID)]; ok {
|
||||
cID := hdr[len(hdr)-1]
|
||||
ctx = context.WithValue(ctx, correlationID, cID)
|
||||
fmt.Printf("\tServer received correlationID %q in metadata header, set context\n", cID)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func displayServerRequestHeaders(ctx context.Context, md metadata.MD) context.Context {
|
||||
if len(md) > 0 {
|
||||
fmt.Println("\tServer << Request Headers:")
|
||||
for key, val := range md {
|
||||
fmt.Printf("\t\t%s: %s\n", key, val[len(val)-1])
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
/* server after functions */
|
||||
|
||||
func injectResponseHeader(ctx context.Context, md *metadata.MD, _ *metadata.MD) context.Context {
|
||||
*md = metadata.Join(*md, metadata.Pairs(string(responseHDR), "has-a-value"))
|
||||
return ctx
|
||||
}
|
||||
|
||||
func displayServerResponseHeaders(ctx context.Context, md *metadata.MD, _ *metadata.MD) context.Context {
|
||||
if len(*md) > 0 {
|
||||
fmt.Println("\tServer >> Response Headers:")
|
||||
for key, val := range *md {
|
||||
fmt.Printf("\t\t%s: %s\n", key, val[len(val)-1])
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func injectResponseTrailer(ctx context.Context, _ *metadata.MD, md *metadata.MD) context.Context {
|
||||
*md = metadata.Join(*md, metadata.Pairs(string(responseTRLR), "has-a-value-too"))
|
||||
return ctx
|
||||
}
|
||||
|
||||
func injectConsumedCorrelationID(ctx context.Context, _ *metadata.MD, md *metadata.MD) context.Context {
|
||||
if hdr, ok := ctx.Value(correlationID).(string); ok {
|
||||
fmt.Printf("\tServer found correlationID %q in context, set consumed trailer\n", hdr)
|
||||
*md = metadata.Join(*md, metadata.Pairs(string(correlationIDTRLR), hdr))
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func displayServerResponseTrailers(ctx context.Context, _ *metadata.MD, md *metadata.MD) context.Context {
|
||||
if len(*md) > 0 {
|
||||
fmt.Println("\tServer >> Response Trailers:")
|
||||
for key, val := range *md {
|
||||
fmt.Printf("\t\t%s: %s\n", key, val[len(val)-1])
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
/* client after functions */
|
||||
|
||||
func displayClientResponseHeaders(ctx context.Context, md metadata.MD, _ metadata.MD) context.Context {
|
||||
if len(md) > 0 {
|
||||
fmt.Println("\tClient << Response Headers:")
|
||||
for key, val := range md {
|
||||
fmt.Printf("\t\t%s: %s\n", key, val[len(val)-1])
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func displayClientResponseTrailers(ctx context.Context, _ metadata.MD, md metadata.MD) context.Context {
|
||||
if len(md) > 0 {
|
||||
fmt.Println("\tClient << Response Trailers:")
|
||||
for key, val := range md {
|
||||
fmt.Printf("\t\t%s: %s\n", key, val[len(val)-1])
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func extractConsumedCorrelationID(ctx context.Context, _ metadata.MD, md metadata.MD) context.Context {
|
||||
if hdr, ok := md[string(correlationIDTRLR)]; ok {
|
||||
fmt.Printf("\tClient received consumed correlationID %q in metadata trailer, set context\n", hdr[len(hdr)-1])
|
||||
ctx = context.WithValue(ctx, correlationIDTRLR, hdr[len(hdr)-1])
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
/* CorrelationID context handlers */
|
||||
|
||||
func SetCorrelationID(ctx context.Context, v string) context.Context {
|
||||
return context.WithValue(ctx, correlationID, v)
|
||||
}
|
||||
|
||||
func GetConsumedCorrelationID(ctx context.Context) string {
|
||||
if trlr, ok := ctx.Value(correlationIDTRLR).(string); ok {
|
||||
return trlr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
3
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/pb/generate.go
generated
vendored
Normal file
3
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/pb/generate.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
package pb
|
||||
|
||||
//go:generate protoc test.proto --go_out=plugins=grpc:.
|
||||
167
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/pb/test.pb.go
generated
vendored
Normal file
167
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/pb/test.pb.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: test.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package pb is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
test.proto
|
||||
|
||||
It has these top-level messages:
|
||||
TestRequest
|
||||
TestResponse
|
||||
*/
|
||||
package pb
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type TestRequest struct {
|
||||
A string `protobuf:"bytes,1,opt,name=a" json:"a,omitempty"`
|
||||
B int64 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"`
|
||||
}
|
||||
|
||||
func (m *TestRequest) Reset() { *m = TestRequest{} }
|
||||
func (m *TestRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*TestRequest) ProtoMessage() {}
|
||||
func (*TestRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *TestRequest) GetA() string {
|
||||
if m != nil {
|
||||
return m.A
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *TestRequest) GetB() int64 {
|
||||
if m != nil {
|
||||
return m.B
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type TestResponse struct {
|
||||
V string `protobuf:"bytes,1,opt,name=v" json:"v,omitempty"`
|
||||
}
|
||||
|
||||
func (m *TestResponse) Reset() { *m = TestResponse{} }
|
||||
func (m *TestResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*TestResponse) ProtoMessage() {}
|
||||
func (*TestResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *TestResponse) GetV() string {
|
||||
if m != nil {
|
||||
return m.V
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*TestRequest)(nil), "pb.TestRequest")
|
||||
proto.RegisterType((*TestResponse)(nil), "pb.TestResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Test service
|
||||
|
||||
type TestClient interface {
|
||||
Test(ctx context.Context, in *TestRequest, opts ...grpc.CallOption) (*TestResponse, error)
|
||||
}
|
||||
|
||||
type testClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewTestClient(cc *grpc.ClientConn) TestClient {
|
||||
return &testClient{cc}
|
||||
}
|
||||
|
||||
func (c *testClient) Test(ctx context.Context, in *TestRequest, opts ...grpc.CallOption) (*TestResponse, error) {
|
||||
out := new(TestResponse)
|
||||
err := grpc.Invoke(ctx, "/pb.Test/Test", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Test service
|
||||
|
||||
type TestServer interface {
|
||||
Test(context.Context, *TestRequest) (*TestResponse, error)
|
||||
}
|
||||
|
||||
func RegisterTestServer(s *grpc.Server, srv TestServer) {
|
||||
s.RegisterService(&_Test_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Test_Test_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TestRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServer).Test(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/pb.Test/Test",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServer).Test(ctx, req.(*TestRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Test_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "pb.Test",
|
||||
HandlerType: (*TestServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Test",
|
||||
Handler: _Test_Test_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("test.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 129 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e,
|
||||
0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe4, 0xe2, 0x0e, 0x49,
|
||||
0x2d, 0x2e, 0x09, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94, 0x60,
|
||||
0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x14, 0x18, 0x35, 0x98,
|
||||
0x83, 0x18, 0x93, 0x94, 0x64, 0xb8, 0x78, 0x20, 0x4a, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x41,
|
||||
0xb2, 0x65, 0x30, 0xb5, 0x65, 0x46, 0xc6, 0x5c, 0x2c, 0x20, 0x59, 0x21, 0x6d, 0x28, 0xcd, 0xaf,
|
||||
0x57, 0x90, 0xa4, 0x87, 0x64, 0xb4, 0x94, 0x00, 0x42, 0x00, 0x62, 0x80, 0x12, 0x43, 0x12, 0x1b,
|
||||
0xd8, 0x21, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0xfc, 0xd8, 0xf1, 0x96, 0x00, 0x00,
|
||||
0x00,
|
||||
}
|
||||
16
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/pb/test.proto
generated
vendored
Normal file
16
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/pb/test.proto
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package pb;
|
||||
|
||||
service Test {
|
||||
rpc Test (TestRequest) returns (TestResponse) {}
|
||||
}
|
||||
|
||||
message TestRequest {
|
||||
string a = 1;
|
||||
int64 b = 2;
|
||||
}
|
||||
|
||||
message TestResponse {
|
||||
string v = 1;
|
||||
}
|
||||
27
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/request_response.go
generated
vendored
Normal file
27
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/request_response.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-kit/kit/transport/grpc/_grpc_test/pb"
|
||||
)
|
||||
|
||||
func encodeRequest(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
r := req.(TestRequest)
|
||||
return &pb.TestRequest{A: r.A, B: r.B}, nil
|
||||
}
|
||||
|
||||
func decodeRequest(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
r := req.(*pb.TestRequest)
|
||||
return TestRequest{A: r.A, B: r.B}, nil
|
||||
}
|
||||
|
||||
func encodeResponse(ctx context.Context, resp interface{}) (interface{}, error) {
|
||||
r := resp.(*TestResponse)
|
||||
return &pb.TestResponse{V: r.V}, nil
|
||||
}
|
||||
|
||||
func decodeResponse(ctx context.Context, resp interface{}) (interface{}, error) {
|
||||
r := resp.(*pb.TestResponse)
|
||||
return &TestResponse{V: r.V, Ctx: ctx}, nil
|
||||
}
|
||||
70
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/server.go
generated
vendored
Normal file
70
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/server.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
oldcontext "golang.org/x/net/context"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
grpctransport "github.com/go-kit/kit/transport/grpc"
|
||||
"github.com/go-kit/kit/transport/grpc/_grpc_test/pb"
|
||||
)
|
||||
|
||||
type service struct{}
|
||||
|
||||
func (service) Test(ctx context.Context, a string, b int64) (context.Context, string, error) {
|
||||
return nil, fmt.Sprintf("%s = %d", a, b), nil
|
||||
}
|
||||
|
||||
func NewService() Service {
|
||||
return service{}
|
||||
}
|
||||
|
||||
func makeTestEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(TestRequest)
|
||||
newCtx, v, err := svc.Test(ctx, req.A, req.B)
|
||||
return &TestResponse{
|
||||
V: v,
|
||||
Ctx: newCtx,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
|
||||
type serverBinding struct {
|
||||
test grpctransport.Handler
|
||||
}
|
||||
|
||||
func (b *serverBinding) Test(ctx oldcontext.Context, req *pb.TestRequest) (*pb.TestResponse, error) {
|
||||
_, response, err := b.test.ServeGRPC(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.(*pb.TestResponse), nil
|
||||
}
|
||||
|
||||
func NewBinding(svc Service) *serverBinding {
|
||||
return &serverBinding{
|
||||
test: grpctransport.NewServer(
|
||||
makeTestEndpoint(svc),
|
||||
decodeRequest,
|
||||
encodeResponse,
|
||||
grpctransport.ServerBefore(
|
||||
extractCorrelationID,
|
||||
),
|
||||
grpctransport.ServerBefore(
|
||||
displayServerRequestHeaders,
|
||||
),
|
||||
grpctransport.ServerAfter(
|
||||
injectResponseHeader,
|
||||
injectResponseTrailer,
|
||||
injectConsumedCorrelationID,
|
||||
),
|
||||
grpctransport.ServerAfter(
|
||||
displayServerResponseHeaders,
|
||||
displayServerResponseTrailers,
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
17
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/service.go
generated
vendored
Normal file
17
vendor/github.com/go-kit/kit/transport/grpc/_grpc_test/service.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package test
|
||||
|
||||
import "context"
|
||||
|
||||
type Service interface {
|
||||
Test(ctx context.Context, a string, b int64) (context.Context, string, error)
|
||||
}
|
||||
|
||||
type TestRequest struct {
|
||||
A string
|
||||
B int64
|
||||
}
|
||||
|
||||
type TestResponse struct {
|
||||
Ctx context.Context
|
||||
V string
|
||||
}
|
||||
119
vendor/github.com/go-kit/kit/transport/grpc/client.go
generated
vendored
Normal file
119
vendor/github.com/go-kit/kit/transport/grpc/client.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
// Client wraps a gRPC connection and provides a method that implements
|
||||
// endpoint.Endpoint.
|
||||
type Client struct {
|
||||
client *grpc.ClientConn
|
||||
serviceName string
|
||||
method string
|
||||
enc EncodeRequestFunc
|
||||
dec DecodeResponseFunc
|
||||
grpcReply reflect.Type
|
||||
before []ClientRequestFunc
|
||||
after []ClientResponseFunc
|
||||
}
|
||||
|
||||
// NewClient constructs a usable Client for a single remote endpoint.
|
||||
// Pass an zero-value protobuf message of the RPC response type as
|
||||
// the grpcReply argument.
|
||||
func NewClient(
|
||||
cc *grpc.ClientConn,
|
||||
serviceName string,
|
||||
method string,
|
||||
enc EncodeRequestFunc,
|
||||
dec DecodeResponseFunc,
|
||||
grpcReply interface{},
|
||||
options ...ClientOption,
|
||||
) *Client {
|
||||
if strings.IndexByte(serviceName, '.') == -1 {
|
||||
serviceName = "pb." + serviceName
|
||||
}
|
||||
c := &Client{
|
||||
client: cc,
|
||||
method: fmt.Sprintf("/%s/%s", serviceName, method),
|
||||
enc: enc,
|
||||
dec: dec,
|
||||
// We are using reflect.Indirect here to allow both reply structs and
|
||||
// pointers to these reply structs. New consumers of the client should
|
||||
// use structs directly, while existing consumers will not break if they
|
||||
// remain to use pointers to structs.
|
||||
grpcReply: reflect.TypeOf(
|
||||
reflect.Indirect(
|
||||
reflect.ValueOf(grpcReply),
|
||||
).Interface(),
|
||||
),
|
||||
before: []ClientRequestFunc{},
|
||||
after: []ClientResponseFunc{},
|
||||
}
|
||||
for _, option := range options {
|
||||
option(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// ClientOption sets an optional parameter for clients.
|
||||
type ClientOption func(*Client)
|
||||
|
||||
// ClientBefore sets the RequestFuncs that are applied to the outgoing gRPC
|
||||
// request before it's invoked.
|
||||
func ClientBefore(before ...ClientRequestFunc) ClientOption {
|
||||
return func(c *Client) { c.before = append(c.before, before...) }
|
||||
}
|
||||
|
||||
// ClientAfter sets the ClientResponseFuncs that are applied to the incoming
|
||||
// gRPC response prior to it being decoded. This is useful for obtaining
|
||||
// response metadata and adding onto the context prior to decoding.
|
||||
func ClientAfter(after ...ClientResponseFunc) ClientOption {
|
||||
return func(c *Client) { c.after = append(c.after, after...) }
|
||||
}
|
||||
|
||||
// Endpoint returns a usable endpoint that will invoke the gRPC specified by the
|
||||
// client.
|
||||
func (c Client) Endpoint() endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
req, err := c.enc(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
md := &metadata.MD{}
|
||||
for _, f := range c.before {
|
||||
ctx = f(ctx, md)
|
||||
}
|
||||
ctx = metadata.NewContext(ctx, *md)
|
||||
|
||||
var header, trailer metadata.MD
|
||||
grpcReply := reflect.New(c.grpcReply).Interface()
|
||||
if err = grpc.Invoke(
|
||||
ctx, c.method, req, grpcReply, c.client,
|
||||
grpc.Header(&header), grpc.Trailer(&trailer),
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, f := range c.after {
|
||||
ctx = f(ctx, header, trailer)
|
||||
}
|
||||
|
||||
response, err := c.dec(ctx, grpcReply)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
59
vendor/github.com/go-kit/kit/transport/grpc/client_test.go
generated
vendored
Normal file
59
vendor/github.com/go-kit/kit/transport/grpc/client_test.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package grpc_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
test "github.com/go-kit/kit/transport/grpc/_grpc_test"
|
||||
"github.com/go-kit/kit/transport/grpc/_grpc_test/pb"
|
||||
)
|
||||
|
||||
const (
|
||||
hostPort string = "localhost:8002"
|
||||
)
|
||||
|
||||
func TestGRPCClient(t *testing.T) {
|
||||
var (
|
||||
server = grpc.NewServer()
|
||||
service = test.NewService()
|
||||
)
|
||||
|
||||
sc, err := net.Listen("tcp", hostPort)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to listen: %+v", err)
|
||||
}
|
||||
defer server.GracefulStop()
|
||||
|
||||
go func() {
|
||||
pb.RegisterTestServer(server, test.NewBinding(service))
|
||||
_ = server.Serve(sc)
|
||||
}()
|
||||
|
||||
cc, err := grpc.Dial(hostPort, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to Dial: %+v", err)
|
||||
}
|
||||
|
||||
client := test.NewClient(cc)
|
||||
|
||||
var (
|
||||
a = "the answer to life the universe and everything"
|
||||
b = int64(42)
|
||||
cID = "request-1"
|
||||
ctx = test.SetCorrelationID(context.Background(), cID)
|
||||
)
|
||||
|
||||
responseCTX, v, err := client.Test(ctx, a, b)
|
||||
|
||||
if want, have := fmt.Sprintf("%s = %d", a, b), v; want != have {
|
||||
t.Fatalf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
if want, have := cID, test.GetConsumedCorrelationID(responseCTX); want != have {
|
||||
t.Fatalf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
2
vendor/github.com/go-kit/kit/transport/grpc/doc.go
generated
vendored
Normal file
2
vendor/github.com/go-kit/kit/transport/grpc/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package grpc provides a gRPC binding for endpoints.
|
||||
package grpc
|
||||
29
vendor/github.com/go-kit/kit/transport/grpc/encode_decode.go
generated
vendored
Normal file
29
vendor/github.com/go-kit/kit/transport/grpc/encode_decode.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// DecodeRequestFunc extracts a user-domain request object from a gRPC request.
|
||||
// It's designed to be used in gRPC servers, for server-side endpoints. One
|
||||
// straightforward DecodeRequestFunc could be something that decodes from the
|
||||
// gRPC request message to the concrete request type.
|
||||
type DecodeRequestFunc func(context.Context, interface{}) (request interface{}, err error)
|
||||
|
||||
// EncodeRequestFunc encodes the passed request object into the gRPC request
|
||||
// object. It's designed to be used in gRPC clients, for client-side endpoints.
|
||||
// One straightforward EncodeRequestFunc could something that encodes the object
|
||||
// directly to the gRPC request message.
|
||||
type EncodeRequestFunc func(context.Context, interface{}) (request interface{}, err error)
|
||||
|
||||
// EncodeResponseFunc encodes the passed response object to the gRPC response
|
||||
// message. It's designed to be used in gRPC servers, for server-side endpoints.
|
||||
// One straightforward EncodeResponseFunc could be something that encodes the
|
||||
// object directly to the gRPC response message.
|
||||
type EncodeResponseFunc func(context.Context, interface{}) (response interface{}, err error)
|
||||
|
||||
// DecodeResponseFunc extracts a user-domain response object from a gRPC
|
||||
// response object. It's designed to be used in gRPC clients, for client-side
|
||||
// endpoints. One straightforward DecodeResponseFunc could be something that
|
||||
// decodes from the gRPC response message to the concrete response type.
|
||||
type DecodeResponseFunc func(context.Context, interface{}) (response interface{}, err error)
|
||||
76
vendor/github.com/go-kit/kit/transport/grpc/request_response_funcs.go
generated
vendored
Normal file
76
vendor/github.com/go-kit/kit/transport/grpc/request_response_funcs.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
binHdrSuffix = "-bin"
|
||||
)
|
||||
|
||||
// ClientRequestFunc may take information from context and use it to construct
|
||||
// metadata headers to be transported to the server. ClientRequestFuncs are
|
||||
// executed after creating the request but prior to sending the gRPC request to
|
||||
// the server.
|
||||
type ClientRequestFunc func(context.Context, *metadata.MD) context.Context
|
||||
|
||||
// ServerRequestFunc may take information from the received metadata header and
|
||||
// use it to place items in the request scoped context. ServerRequestFuncs are
|
||||
// executed prior to invoking the endpoint.
|
||||
type ServerRequestFunc func(context.Context, metadata.MD) context.Context
|
||||
|
||||
// ServerResponseFunc may take information from a request context and use it to
|
||||
// manipulate the gRPC response metadata headers and trailers. ResponseFuncs are
|
||||
// only executed in servers, after invoking the endpoint but prior to writing a
|
||||
// response.
|
||||
type ServerResponseFunc func(ctx context.Context, header *metadata.MD, trailer *metadata.MD) context.Context
|
||||
|
||||
// ClientResponseFunc may take information from a gRPC metadata header and/or
|
||||
// trailer and make the responses available for consumption. ClientResponseFuncs
|
||||
// are only executed in clients, after a request has been made, but prior to it
|
||||
// being decoded.
|
||||
type ClientResponseFunc func(ctx context.Context, header metadata.MD, trailer metadata.MD) context.Context
|
||||
|
||||
// SetRequestHeader returns a ClientRequestFunc that sets the specified metadata
|
||||
// key-value pair.
|
||||
func SetRequestHeader(key, val string) ClientRequestFunc {
|
||||
return func(ctx context.Context, md *metadata.MD) context.Context {
|
||||
key, val := EncodeKeyValue(key, val)
|
||||
(*md)[key] = append((*md)[key], val)
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
|
||||
// SetResponseHeader returns a ResponseFunc that sets the specified metadata
|
||||
// key-value pair.
|
||||
func SetResponseHeader(key, val string) ServerResponseFunc {
|
||||
return func(ctx context.Context, md *metadata.MD, _ *metadata.MD) context.Context {
|
||||
key, val := EncodeKeyValue(key, val)
|
||||
(*md)[key] = append((*md)[key], val)
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
|
||||
// SetResponseTrailer returns a ResponseFunc that sets the specified metadata
|
||||
// key-value pair.
|
||||
func SetResponseTrailer(key, val string) ServerResponseFunc {
|
||||
return func(ctx context.Context, _ *metadata.MD, md *metadata.MD) context.Context {
|
||||
key, val := EncodeKeyValue(key, val)
|
||||
(*md)[key] = append((*md)[key], val)
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeKeyValue sanitizes a key-value pair for use in gRPC metadata headers.
|
||||
func EncodeKeyValue(key, val string) (string, string) {
|
||||
key = strings.ToLower(key)
|
||||
if strings.HasSuffix(key, binHdrSuffix) {
|
||||
v := base64.StdEncoding.EncodeToString([]byte(val))
|
||||
val = string(v)
|
||||
}
|
||||
return key, val
|
||||
}
|
||||
123
vendor/github.com/go-kit/kit/transport/grpc/server.go
generated
vendored
Normal file
123
vendor/github.com/go-kit/kit/transport/grpc/server.go
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
oldcontext "golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
)
|
||||
|
||||
// Handler which should be called from the gRPC binding of the service
|
||||
// implementation. The incoming request parameter, and returned response
|
||||
// parameter, are both gRPC types, not user-domain.
|
||||
type Handler interface {
|
||||
ServeGRPC(ctx oldcontext.Context, request interface{}) (oldcontext.Context, interface{}, error)
|
||||
}
|
||||
|
||||
// Server wraps an endpoint and implements grpc.Handler.
|
||||
type Server struct {
|
||||
e endpoint.Endpoint
|
||||
dec DecodeRequestFunc
|
||||
enc EncodeResponseFunc
|
||||
before []ServerRequestFunc
|
||||
after []ServerResponseFunc
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
// NewServer constructs a new server, which implements wraps the provided
|
||||
// endpoint and implements the Handler interface. Consumers should write
|
||||
// bindings that adapt the concrete gRPC methods from their compiled protobuf
|
||||
// definitions to individual handlers. Request and response objects are from the
|
||||
// caller business domain, not gRPC request and reply types.
|
||||
func NewServer(
|
||||
e endpoint.Endpoint,
|
||||
dec DecodeRequestFunc,
|
||||
enc EncodeResponseFunc,
|
||||
options ...ServerOption,
|
||||
) *Server {
|
||||
s := &Server{
|
||||
e: e,
|
||||
dec: dec,
|
||||
enc: enc,
|
||||
logger: log.NewNopLogger(),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ServerOption sets an optional parameter for servers.
|
||||
type ServerOption func(*Server)
|
||||
|
||||
// ServerBefore functions are executed on the HTTP request object before the
|
||||
// request is decoded.
|
||||
func ServerBefore(before ...ServerRequestFunc) ServerOption {
|
||||
return func(s *Server) { s.before = append(s.before, before...) }
|
||||
}
|
||||
|
||||
// ServerAfter functions are executed on the HTTP response writer after the
|
||||
// endpoint is invoked, but before anything is written to the client.
|
||||
func ServerAfter(after ...ServerResponseFunc) ServerOption {
|
||||
return func(s *Server) { s.after = append(s.after, after...) }
|
||||
}
|
||||
|
||||
// ServerErrorLogger is used to log non-terminal errors. By default, no errors
|
||||
// are logged.
|
||||
func ServerErrorLogger(logger log.Logger) ServerOption {
|
||||
return func(s *Server) { s.logger = logger }
|
||||
}
|
||||
|
||||
// ServeGRPC implements the Handler interface.
|
||||
func (s Server) ServeGRPC(ctx oldcontext.Context, req interface{}) (oldcontext.Context, interface{}, error) {
|
||||
// Retrieve gRPC metadata.
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.MD{}
|
||||
}
|
||||
|
||||
for _, f := range s.before {
|
||||
ctx = f(ctx, md)
|
||||
}
|
||||
|
||||
request, err := s.dec(ctx, req)
|
||||
if err != nil {
|
||||
s.logger.Log("err", err)
|
||||
return ctx, nil, err
|
||||
}
|
||||
|
||||
response, err := s.e(ctx, request)
|
||||
if err != nil {
|
||||
s.logger.Log("err", err)
|
||||
return ctx, nil, err
|
||||
}
|
||||
|
||||
var mdHeader, mdTrailer metadata.MD
|
||||
for _, f := range s.after {
|
||||
ctx = f(ctx, &mdHeader, &mdTrailer)
|
||||
}
|
||||
|
||||
grpcResp, err := s.enc(ctx, response)
|
||||
if err != nil {
|
||||
s.logger.Log("err", err)
|
||||
return ctx, nil, err
|
||||
}
|
||||
|
||||
if len(mdHeader) > 0 {
|
||||
if err = grpc.SendHeader(ctx, mdHeader); err != nil {
|
||||
s.logger.Log("err", err)
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(mdTrailer) > 0 {
|
||||
if err = grpc.SetTrailer(ctx, mdTrailer); err != nil {
|
||||
s.logger.Log("err", err)
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, grpcResp, nil
|
||||
}
|
||||
150
vendor/github.com/go-kit/kit/transport/http/client.go
generated
vendored
Normal file
150
vendor/github.com/go-kit/kit/transport/http/client.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
// Client wraps a URL and provides a method that implements endpoint.Endpoint.
|
||||
type Client struct {
|
||||
client *http.Client
|
||||
method string
|
||||
tgt *url.URL
|
||||
enc EncodeRequestFunc
|
||||
dec DecodeResponseFunc
|
||||
before []RequestFunc
|
||||
after []ClientResponseFunc
|
||||
bufferedStream bool
|
||||
}
|
||||
|
||||
// NewClient constructs a usable Client for a single remote method.
|
||||
func NewClient(
|
||||
method string,
|
||||
tgt *url.URL,
|
||||
enc EncodeRequestFunc,
|
||||
dec DecodeResponseFunc,
|
||||
options ...ClientOption,
|
||||
) *Client {
|
||||
c := &Client{
|
||||
client: http.DefaultClient,
|
||||
method: method,
|
||||
tgt: tgt,
|
||||
enc: enc,
|
||||
dec: dec,
|
||||
before: []RequestFunc{},
|
||||
after: []ClientResponseFunc{},
|
||||
bufferedStream: false,
|
||||
}
|
||||
for _, option := range options {
|
||||
option(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// ClientOption sets an optional parameter for clients.
|
||||
type ClientOption func(*Client)
|
||||
|
||||
// SetClient sets the underlying HTTP client used for requests.
|
||||
// By default, http.DefaultClient is used.
|
||||
func SetClient(client *http.Client) ClientOption {
|
||||
return func(c *Client) { c.client = client }
|
||||
}
|
||||
|
||||
// ClientBefore sets the RequestFuncs that are applied to the outgoing HTTP
|
||||
// request before it's invoked.
|
||||
func ClientBefore(before ...RequestFunc) ClientOption {
|
||||
return func(c *Client) { c.before = append(c.before, before...) }
|
||||
}
|
||||
|
||||
// ClientAfter sets the ClientResponseFuncs applied to the incoming HTTP
|
||||
// request prior to it being decoded. This is useful for obtaining anything off
|
||||
// of the response and adding onto the context prior to decoding.
|
||||
func ClientAfter(after ...ClientResponseFunc) ClientOption {
|
||||
return func(c *Client) { c.after = append(c.after, after...) }
|
||||
}
|
||||
|
||||
// BufferedStream sets whether the Response.Body is left open, allowing it
|
||||
// to be read from later. Useful for transporting a file as a buffered stream.
|
||||
func BufferedStream(buffered bool) ClientOption {
|
||||
return func(c *Client) { c.bufferedStream = buffered }
|
||||
}
|
||||
|
||||
// Endpoint returns a usable endpoint that invokes the remote endpoint.
|
||||
func (c Client) Endpoint() endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequest(c.method, c.tgt.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = c.enc(ctx, req, request); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, f := range c.before {
|
||||
ctx = f(ctx, req)
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, c.client, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !c.bufferedStream {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
for _, f := range c.after {
|
||||
ctx = f(ctx, resp)
|
||||
}
|
||||
|
||||
response, err := c.dec(ctx, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeJSONRequest is an EncodeRequestFunc that serializes the request as a
|
||||
// JSON object to the Request body. Many JSON-over-HTTP services can use it as
|
||||
// a sensible default. If the request implements Headerer, the provided headers
|
||||
// will be applied to the request.
|
||||
func EncodeJSONRequest(c context.Context, r *http.Request, request interface{}) error {
|
||||
r.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||
if headerer, ok := request.(Headerer); ok {
|
||||
for k := range headerer.Headers() {
|
||||
r.Header.Set(k, headerer.Headers().Get(k))
|
||||
}
|
||||
}
|
||||
var b bytes.Buffer
|
||||
r.Body = ioutil.NopCloser(&b)
|
||||
return json.NewEncoder(&b).Encode(request)
|
||||
}
|
||||
|
||||
// EncodeXMLRequest is an EncodeRequestFunc that serializes the request as a
|
||||
// XML object to the Request body. If the request implements Headerer,
|
||||
// the provided headers will be applied to the request.
|
||||
func EncodeXMLRequest(c context.Context, r *http.Request, request interface{}) error {
|
||||
r.Header.Set("Content-Type", "text/xml; charset=utf-8")
|
||||
if headerer, ok := request.(Headerer); ok {
|
||||
for k := range headerer.Headers() {
|
||||
r.Header.Set(k, headerer.Headers().Get(k))
|
||||
}
|
||||
}
|
||||
var b bytes.Buffer
|
||||
r.Body = ioutil.NopCloser(&b)
|
||||
return xml.NewEncoder(&b).Encode(request)
|
||||
}
|
||||
217
vendor/github.com/go-kit/kit/transport/http/client_test.go
generated
vendored
Normal file
217
vendor/github.com/go-kit/kit/transport/http/client_test.go
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
type TestResponse struct {
|
||||
Body io.ReadCloser
|
||||
String string
|
||||
}
|
||||
|
||||
func TestHTTPClient(t *testing.T) {
|
||||
var (
|
||||
testbody = "testbody"
|
||||
encode = func(context.Context, *http.Request, interface{}) error { return nil }
|
||||
decode = func(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
buffer := make([]byte, len(testbody))
|
||||
r.Body.Read(buffer)
|
||||
return TestResponse{r.Body, string(buffer)}, nil
|
||||
}
|
||||
headers = make(chan string, 1)
|
||||
headerKey = "X-Foo"
|
||||
headerVal = "abcde"
|
||||
afterHeaderKey = "X-The-Dude"
|
||||
afterHeaderVal = "Abides"
|
||||
afterVal = ""
|
||||
afterFunc = func(ctx context.Context, r *http.Response) context.Context {
|
||||
afterVal = r.Header.Get(afterHeaderKey)
|
||||
return ctx
|
||||
}
|
||||
)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
headers <- r.Header.Get(headerKey)
|
||||
w.Header().Set(afterHeaderKey, afterHeaderVal)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(testbody))
|
||||
}))
|
||||
|
||||
client := httptransport.NewClient(
|
||||
"GET",
|
||||
mustParse(server.URL),
|
||||
encode,
|
||||
decode,
|
||||
httptransport.ClientBefore(httptransport.SetRequestHeader(headerKey, headerVal)),
|
||||
httptransport.ClientAfter(afterFunc),
|
||||
)
|
||||
|
||||
res, err := client.Endpoint()(context.Background(), struct{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var have string
|
||||
select {
|
||||
case have = <-headers:
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Fatalf("timeout waiting for %s", headerKey)
|
||||
}
|
||||
// Check that Request Header was successfully received
|
||||
if want := headerVal; want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
// Check that Response header set from server was received in SetClientAfter
|
||||
if want, have := afterVal, afterHeaderVal; want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
// Check that the response was successfully decoded
|
||||
response, ok := res.(TestResponse)
|
||||
if !ok {
|
||||
t.Fatal("response should be TestResponse")
|
||||
}
|
||||
if want, have := testbody, response.String; want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
// Check that response body was closed
|
||||
b := make([]byte, 1)
|
||||
_, err = response.Body.Read(b)
|
||||
if err == nil {
|
||||
t.Fatal("wanted error, got none")
|
||||
}
|
||||
if doNotWant, have := io.EOF, err; doNotWant == have {
|
||||
t.Errorf("do not want %q, have %q", doNotWant, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPClientBufferedStream(t *testing.T) {
|
||||
var (
|
||||
testbody = "testbody"
|
||||
encode = func(context.Context, *http.Request, interface{}) error { return nil }
|
||||
decode = func(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
return TestResponse{r.Body, ""}, nil
|
||||
}
|
||||
)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(testbody))
|
||||
}))
|
||||
|
||||
client := httptransport.NewClient(
|
||||
"GET",
|
||||
mustParse(server.URL),
|
||||
encode,
|
||||
decode,
|
||||
httptransport.BufferedStream(true),
|
||||
)
|
||||
|
||||
res, err := client.Endpoint()(context.Background(), struct{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Check that the response was successfully decoded
|
||||
response, ok := res.(TestResponse)
|
||||
if !ok {
|
||||
t.Fatal("response should be TestResponse")
|
||||
}
|
||||
|
||||
// Check that response body was NOT closed
|
||||
b := make([]byte, len(testbody))
|
||||
_, err = response.Body.Read(b)
|
||||
if want, have := io.EOF, err; have != want {
|
||||
t.Fatalf("want %q, have %q", want, have)
|
||||
}
|
||||
if want, have := testbody, string(b); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeJSONRequest(t *testing.T) {
|
||||
var header http.Header
|
||||
var body string
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatal(err)
|
||||
}
|
||||
header = r.Header
|
||||
body = string(b)
|
||||
}))
|
||||
|
||||
defer server.Close()
|
||||
|
||||
serverURL, err := url.Parse(server.URL)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client := httptransport.NewClient(
|
||||
"POST",
|
||||
serverURL,
|
||||
httptransport.EncodeJSONRequest,
|
||||
func(context.Context, *http.Response) (interface{}, error) { return nil, nil },
|
||||
).Endpoint()
|
||||
|
||||
for _, test := range []struct {
|
||||
value interface{}
|
||||
body string
|
||||
}{
|
||||
{nil, "null\n"},
|
||||
{12, "12\n"},
|
||||
{1.2, "1.2\n"},
|
||||
{true, "true\n"},
|
||||
{"test", "\"test\"\n"},
|
||||
{enhancedRequest{Foo: "foo"}, "{\"foo\":\"foo\"}\n"},
|
||||
} {
|
||||
if _, err := client(context.Background(), test.value); err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if body != test.body {
|
||||
t.Errorf("%v: actual %#v, expected %#v", test.value, body, test.body)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := client(context.Background(), enhancedRequest{Foo: "foo"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, ok := header["X-Edward"]; !ok {
|
||||
t.Fatalf("X-Edward value: actual %v, expected %v", nil, []string{"Snowden"})
|
||||
}
|
||||
|
||||
if v := header.Get("X-Edward"); v != "Snowden" {
|
||||
t.Errorf("X-Edward string: actual %v, expected %v", v, "Snowden")
|
||||
}
|
||||
}
|
||||
|
||||
func mustParse(s string) *url.URL {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
type enhancedRequest struct {
|
||||
Foo string `json:"foo"`
|
||||
}
|
||||
|
||||
func (e enhancedRequest) Headers() http.Header { return http.Header{"X-Edward": []string{"Snowden"}} }
|
||||
2
vendor/github.com/go-kit/kit/transport/http/doc.go
generated
vendored
Normal file
2
vendor/github.com/go-kit/kit/transport/http/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package http provides a general purpose HTTP binding for endpoints.
|
||||
package http
|
||||
30
vendor/github.com/go-kit/kit/transport/http/encode_decode.go
generated
vendored
Normal file
30
vendor/github.com/go-kit/kit/transport/http/encode_decode.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// DecodeRequestFunc extracts a user-domain request object from an HTTP
|
||||
// request object. It's designed to be used in HTTP servers, for server-side
|
||||
// endpoints. One straightforward DecodeRequestFunc could be something that
|
||||
// JSON decodes from the request body to the concrete response type.
|
||||
type DecodeRequestFunc func(context.Context, *http.Request) (request interface{}, err error)
|
||||
|
||||
// EncodeRequestFunc encodes the passed request object into the HTTP request
|
||||
// object. It's designed to be used in HTTP clients, for client-side
|
||||
// endpoints. One straightforward EncodeRequestFunc could something that JSON
|
||||
// encodes the object directly to the request body.
|
||||
type EncodeRequestFunc func(context.Context, *http.Request, interface{}) error
|
||||
|
||||
// EncodeResponseFunc encodes the passed response object to the HTTP response
|
||||
// writer. It's designed to be used in HTTP servers, for server-side
|
||||
// endpoints. One straightforward EncodeResponseFunc could be something that
|
||||
// JSON encodes the object directly to the response body.
|
||||
type EncodeResponseFunc func(context.Context, http.ResponseWriter, interface{}) error
|
||||
|
||||
// DecodeResponseFunc extracts a user-domain response object from an HTTP
|
||||
// response object. It's designed to be used in HTTP clients, for client-side
|
||||
// endpoints. One straightforward DecodeResponseFunc could be something that
|
||||
// JSON decodes from the response body to the concrete response type.
|
||||
type DecodeResponseFunc func(context.Context, *http.Response) (response interface{}, err error)
|
||||
36
vendor/github.com/go-kit/kit/transport/http/example_test.go
generated
vendored
Normal file
36
vendor/github.com/go-kit/kit/transport/http/example_test.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
func ExamplePopulateRequestContext() {
|
||||
handler := NewServer(
|
||||
func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
fmt.Println("Method", ctx.Value(ContextKeyRequestMethod).(string))
|
||||
fmt.Println("RequestPath", ctx.Value(ContextKeyRequestPath).(string))
|
||||
fmt.Println("RequestURI", ctx.Value(ContextKeyRequestURI).(string))
|
||||
fmt.Println("X-Request-ID", ctx.Value(ContextKeyRequestXRequestID).(string))
|
||||
return struct{}{}, nil
|
||||
},
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, http.ResponseWriter, interface{}) error { return nil },
|
||||
ServerBefore(PopulateRequestContext),
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
req, _ := http.NewRequest("PATCH", fmt.Sprintf("%s/search?q=sympatico", server.URL), nil)
|
||||
req.Header.Set("X-Request-Id", "a1b2c3d4e5")
|
||||
http.DefaultClient.Do(req)
|
||||
|
||||
// Output:
|
||||
// Method PATCH
|
||||
// RequestPath /search
|
||||
// RequestURI /search?q=sympatico
|
||||
// X-Request-ID a1b2c3d4e5
|
||||
}
|
||||
128
vendor/github.com/go-kit/kit/transport/http/request_response_funcs.go
generated
vendored
Normal file
128
vendor/github.com/go-kit/kit/transport/http/request_response_funcs.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// RequestFunc may take information from an HTTP request and put it into a
|
||||
// request context. In Servers, RequestFuncs are executed prior to invoking the
|
||||
// endpoint. In Clients, RequestFuncs are executed after creating the request
|
||||
// but prior to invoking the HTTP client.
|
||||
type RequestFunc func(context.Context, *http.Request) context.Context
|
||||
|
||||
// ServerResponseFunc may take information from a request context and use it to
|
||||
// manipulate a ResponseWriter. ServerResponseFuncs are only executed in
|
||||
// servers, after invoking the endpoint but prior to writing a response.
|
||||
type ServerResponseFunc func(context.Context, http.ResponseWriter) context.Context
|
||||
|
||||
// ClientResponseFunc may take information from an HTTP request and make the
|
||||
// response available for consumption. ClientResponseFuncs are only executed in
|
||||
// clients, after a request has been made, but prior to it being decoded.
|
||||
type ClientResponseFunc func(context.Context, *http.Response) context.Context
|
||||
|
||||
// SetContentType returns a ServerResponseFunc that sets the Content-Type header
|
||||
// to the provided value.
|
||||
func SetContentType(contentType string) ServerResponseFunc {
|
||||
return SetResponseHeader("Content-Type", contentType)
|
||||
}
|
||||
|
||||
// SetResponseHeader returns a ServerResponseFunc that sets the given header.
|
||||
func SetResponseHeader(key, val string) ServerResponseFunc {
|
||||
return func(ctx context.Context, w http.ResponseWriter) context.Context {
|
||||
w.Header().Set(key, val)
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
|
||||
// SetRequestHeader returns a RequestFunc that sets the given header.
|
||||
func SetRequestHeader(key, val string) RequestFunc {
|
||||
return func(ctx context.Context, r *http.Request) context.Context {
|
||||
r.Header.Set(key, val)
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
|
||||
// PopulateRequestContext is a RequestFunc that populates several values into
|
||||
// the context from the HTTP request. Those values may be extracted using the
|
||||
// corresponding ContextKey type in this package.
|
||||
func PopulateRequestContext(ctx context.Context, r *http.Request) context.Context {
|
||||
for k, v := range map[contextKey]string{
|
||||
ContextKeyRequestMethod: r.Method,
|
||||
ContextKeyRequestURI: r.RequestURI,
|
||||
ContextKeyRequestPath: r.URL.Path,
|
||||
ContextKeyRequestProto: r.Proto,
|
||||
ContextKeyRequestHost: r.Host,
|
||||
ContextKeyRequestRemoteAddr: r.RemoteAddr,
|
||||
ContextKeyRequestXForwardedFor: r.Header.Get("X-Forwarded-For"),
|
||||
ContextKeyRequestXForwardedProto: r.Header.Get("X-Forwarded-Proto"),
|
||||
ContextKeyRequestAuthorization: r.Header.Get("Authorization"),
|
||||
ContextKeyRequestReferer: r.Header.Get("Referer"),
|
||||
ContextKeyRequestUserAgent: r.Header.Get("User-Agent"),
|
||||
ContextKeyRequestXRequestID: r.Header.Get("X-Request-Id"),
|
||||
} {
|
||||
ctx = context.WithValue(ctx, k, v)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
type contextKey int
|
||||
|
||||
const (
|
||||
// ContextKeyRequestMethod is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Method.
|
||||
ContextKeyRequestMethod contextKey = iota
|
||||
|
||||
// ContextKeyRequestURI is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.RequestURI.
|
||||
ContextKeyRequestURI
|
||||
|
||||
// ContextKeyRequestPath is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.URL.Path.
|
||||
ContextKeyRequestPath
|
||||
|
||||
// ContextKeyRequestProto is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Proto.
|
||||
ContextKeyRequestProto
|
||||
|
||||
// ContextKeyRequestHost is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Host.
|
||||
ContextKeyRequestHost
|
||||
|
||||
// ContextKeyRequestRemoteAddr is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.RemoteAddr.
|
||||
ContextKeyRequestRemoteAddr
|
||||
|
||||
// ContextKeyRequestXForwardedFor is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Header.Get("X-Forwarded-For").
|
||||
ContextKeyRequestXForwardedFor
|
||||
|
||||
// ContextKeyRequestXForwardedProto is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Header.Get("X-Forwarded-Proto").
|
||||
ContextKeyRequestXForwardedProto
|
||||
|
||||
// ContextKeyRequestAuthorization is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Header.Get("Authorization").
|
||||
ContextKeyRequestAuthorization
|
||||
|
||||
// ContextKeyRequestReferer is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Header.Get("Referer").
|
||||
ContextKeyRequestReferer
|
||||
|
||||
// ContextKeyRequestUserAgent is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Header.Get("User-Agent").
|
||||
ContextKeyRequestUserAgent
|
||||
|
||||
// ContextKeyRequestXRequestID is populated in the context by
|
||||
// PopulateRequestContext. Its value is r.Header.Get("X-Request-Id").
|
||||
ContextKeyRequestXRequestID
|
||||
|
||||
// ContextKeyResponseHeaders is populated in the context whenever a
|
||||
// ServerFinalizerFunc is specified. Its value is of type http.Header, and
|
||||
// is captured only once the entire response has been written.
|
||||
ContextKeyResponseHeaders
|
||||
|
||||
// ContextKeyResponseSize is populated in the context whenever a
|
||||
// ServerFinalizerFunc is specified. Its value is of type int64.
|
||||
ContextKeyResponseSize
|
||||
)
|
||||
30
vendor/github.com/go-kit/kit/transport/http/request_response_funcs_test.go
generated
vendored
Normal file
30
vendor/github.com/go-kit/kit/transport/http/request_response_funcs_test.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
func TestSetHeader(t *testing.T) {
|
||||
const (
|
||||
key = "X-Foo"
|
||||
val = "12345"
|
||||
)
|
||||
r := httptest.NewRecorder()
|
||||
httptransport.SetResponseHeader(key, val)(context.Background(), r)
|
||||
if want, have := val, r.Header().Get(key); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetContentType(t *testing.T) {
|
||||
const contentType = "application/json"
|
||||
r := httptest.NewRecorder()
|
||||
httptransport.SetContentType(contentType)(context.Background(), r)
|
||||
if want, have := contentType, r.Header().Get("Content-Type"); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
221
vendor/github.com/go-kit/kit/transport/http/server.go
generated
vendored
Normal file
221
vendor/github.com/go-kit/kit/transport/http/server.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
)
|
||||
|
||||
// Server wraps an endpoint and implements http.Handler.
|
||||
type Server struct {
|
||||
e endpoint.Endpoint
|
||||
dec DecodeRequestFunc
|
||||
enc EncodeResponseFunc
|
||||
before []RequestFunc
|
||||
after []ServerResponseFunc
|
||||
errorEncoder ErrorEncoder
|
||||
finalizer ServerFinalizerFunc
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
// NewServer constructs a new server, which implements http.Server and wraps
|
||||
// the provided endpoint.
|
||||
func NewServer(
|
||||
e endpoint.Endpoint,
|
||||
dec DecodeRequestFunc,
|
||||
enc EncodeResponseFunc,
|
||||
options ...ServerOption,
|
||||
) *Server {
|
||||
s := &Server{
|
||||
e: e,
|
||||
dec: dec,
|
||||
enc: enc,
|
||||
errorEncoder: DefaultErrorEncoder,
|
||||
logger: log.NewNopLogger(),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ServerOption sets an optional parameter for servers.
|
||||
type ServerOption func(*Server)
|
||||
|
||||
// ServerBefore functions are executed on the HTTP request object before the
|
||||
// request is decoded.
|
||||
func ServerBefore(before ...RequestFunc) ServerOption {
|
||||
return func(s *Server) { s.before = append(s.before, before...) }
|
||||
}
|
||||
|
||||
// ServerAfter functions are executed on the HTTP response writer after the
|
||||
// endpoint is invoked, but before anything is written to the client.
|
||||
func ServerAfter(after ...ServerResponseFunc) ServerOption {
|
||||
return func(s *Server) { s.after = append(s.after, after...) }
|
||||
}
|
||||
|
||||
// ServerErrorEncoder is used to encode errors to the http.ResponseWriter
|
||||
// whenever they're encountered in the processing of a request. Clients can
|
||||
// use this to provide custom error formatting and response codes. By default,
|
||||
// errors will be written with the DefaultErrorEncoder.
|
||||
func ServerErrorEncoder(ee ErrorEncoder) ServerOption {
|
||||
return func(s *Server) { s.errorEncoder = ee }
|
||||
}
|
||||
|
||||
// ServerErrorLogger is used to log non-terminal errors. By default, no errors
|
||||
// are logged. This is intended as a diagnostic measure. Finer-grained control
|
||||
// of error handling, including logging in more detail, should be performed in a
|
||||
// custom ServerErrorEncoder or ServerFinalizer, both of which have access to
|
||||
// the context.
|
||||
func ServerErrorLogger(logger log.Logger) ServerOption {
|
||||
return func(s *Server) { s.logger = logger }
|
||||
}
|
||||
|
||||
// ServerFinalizer is executed at the end of every HTTP request.
|
||||
// By default, no finalizer is registered.
|
||||
func ServerFinalizer(f ServerFinalizerFunc) ServerOption {
|
||||
return func(s *Server) { s.finalizer = f }
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler.
|
||||
func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
if s.finalizer != nil {
|
||||
iw := &interceptingWriter{w, http.StatusOK, 0}
|
||||
defer func() {
|
||||
ctx = context.WithValue(ctx, ContextKeyResponseHeaders, iw.Header())
|
||||
ctx = context.WithValue(ctx, ContextKeyResponseSize, iw.written)
|
||||
s.finalizer(ctx, iw.code, r)
|
||||
}()
|
||||
w = iw
|
||||
}
|
||||
|
||||
for _, f := range s.before {
|
||||
ctx = f(ctx, r)
|
||||
}
|
||||
|
||||
request, err := s.dec(ctx, r)
|
||||
if err != nil {
|
||||
s.logger.Log("err", err)
|
||||
s.errorEncoder(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
response, err := s.e(ctx, request)
|
||||
if err != nil {
|
||||
s.logger.Log("err", err)
|
||||
s.errorEncoder(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
for _, f := range s.after {
|
||||
ctx = f(ctx, w)
|
||||
}
|
||||
|
||||
if err := s.enc(ctx, w, response); err != nil {
|
||||
s.logger.Log("err", err)
|
||||
s.errorEncoder(ctx, err, w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorEncoder is responsible for encoding an error to the ResponseWriter.
|
||||
// Users are encouraged to use custom ErrorEncoders to encode HTTP errors to
|
||||
// their clients, and will likely want to pass and check for their own error
|
||||
// types. See the example shipping/handling service.
|
||||
type ErrorEncoder func(ctx context.Context, err error, w http.ResponseWriter)
|
||||
|
||||
// ServerFinalizerFunc can be used to perform work at the end of an HTTP
|
||||
// request, after the response has been written to the client. The principal
|
||||
// intended use is for request logging. In addition to the response code
|
||||
// provided in the function signature, additional response parameters are
|
||||
// provided in the context under keys with the ContextKeyResponse prefix.
|
||||
type ServerFinalizerFunc func(ctx context.Context, code int, r *http.Request)
|
||||
|
||||
// EncodeJSONResponse is a EncodeResponseFunc that serializes the response as a
|
||||
// JSON object to the ResponseWriter. Many JSON-over-HTTP services can use it as
|
||||
// a sensible default. If the response implements Headerer, the provided headers
|
||||
// will be applied to the response. If the response implements StatusCoder, the
|
||||
// provided StatusCode will be used instead of 200.
|
||||
func EncodeJSONResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if headerer, ok := response.(Headerer); ok {
|
||||
for k := range headerer.Headers() {
|
||||
w.Header().Set(k, headerer.Headers().Get(k))
|
||||
}
|
||||
}
|
||||
code := http.StatusOK
|
||||
if sc, ok := response.(StatusCoder); ok {
|
||||
code = sc.StatusCode()
|
||||
}
|
||||
w.WriteHeader(code)
|
||||
if code == http.StatusNoContent {
|
||||
return nil
|
||||
}
|
||||
return json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
|
||||
// DefaultErrorEncoder writes the error to the ResponseWriter, by default a
|
||||
// content type of text/plain, a body of the plain text of the error, and a
|
||||
// status code of 500. If the error implements Headerer, the provided headers
|
||||
// will be applied to the response. If the error implements json.Marshaler, and
|
||||
// the marshaling succeeds, a content type of application/json and the JSON
|
||||
// encoded form of the error will be used. If the error implements StatusCoder,
|
||||
// the provided StatusCode will be used instead of 500.
|
||||
func DefaultErrorEncoder(_ context.Context, err error, w http.ResponseWriter) {
|
||||
contentType, body := "text/plain; charset=utf-8", []byte(err.Error())
|
||||
if marshaler, ok := err.(json.Marshaler); ok {
|
||||
if jsonBody, marshalErr := marshaler.MarshalJSON(); marshalErr == nil {
|
||||
contentType, body = "application/json; charset=utf-8", jsonBody
|
||||
}
|
||||
}
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if headerer, ok := err.(Headerer); ok {
|
||||
for k := range headerer.Headers() {
|
||||
w.Header().Set(k, headerer.Headers().Get(k))
|
||||
}
|
||||
}
|
||||
code := http.StatusInternalServerError
|
||||
if sc, ok := err.(StatusCoder); ok {
|
||||
code = sc.StatusCode()
|
||||
}
|
||||
w.WriteHeader(code)
|
||||
w.Write(body)
|
||||
}
|
||||
|
||||
// StatusCoder is checked by DefaultErrorEncoder. If an error value implements
|
||||
// StatusCoder, the StatusCode will be used when encoding the error. By default,
|
||||
// StatusInternalServerError (500) is used.
|
||||
type StatusCoder interface {
|
||||
StatusCode() int
|
||||
}
|
||||
|
||||
// Headerer is checked by DefaultErrorEncoder. If an error value implements
|
||||
// Headerer, the provided headers will be applied to the response writer, after
|
||||
// the Content-Type is set.
|
||||
type Headerer interface {
|
||||
Headers() http.Header
|
||||
}
|
||||
|
||||
type interceptingWriter struct {
|
||||
http.ResponseWriter
|
||||
code int
|
||||
written int64
|
||||
}
|
||||
|
||||
// WriteHeader may not be explicitly called, so care must be taken to
|
||||
// initialize w.code to its default value of http.StatusOK.
|
||||
func (w *interceptingWriter) WriteHeader(code int) {
|
||||
w.code = code
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
func (w *interceptingWriter) Write(p []byte) (int, error) {
|
||||
n, err := w.ResponseWriter.Write(p)
|
||||
w.written += int64(n)
|
||||
return n, err
|
||||
}
|
||||
349
vendor/github.com/go-kit/kit/transport/http/server_test.go
generated
vendored
Normal file
349
vendor/github.com/go-kit/kit/transport/http/server_test.go
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
func TestServerBadDecode(t *testing.T) {
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, errors.New("dang") },
|
||||
func(context.Context, http.ResponseWriter, interface{}) error { return nil },
|
||||
)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
resp, _ := http.Get(server.URL)
|
||||
if want, have := http.StatusInternalServerError, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerBadEndpoint(t *testing.T) {
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errors.New("dang") },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, http.ResponseWriter, interface{}) error { return nil },
|
||||
)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
resp, _ := http.Get(server.URL)
|
||||
if want, have := http.StatusInternalServerError, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerBadEncode(t *testing.T) {
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, http.ResponseWriter, interface{}) error { return errors.New("dang") },
|
||||
)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
resp, _ := http.Get(server.URL)
|
||||
if want, have := http.StatusInternalServerError, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerErrorEncoder(t *testing.T) {
|
||||
errTeapot := errors.New("teapot")
|
||||
code := func(err error) int {
|
||||
if err == errTeapot {
|
||||
return http.StatusTeapot
|
||||
}
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errTeapot },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, http.ResponseWriter, interface{}) error { return nil },
|
||||
httptransport.ServerErrorEncoder(func(_ context.Context, err error, w http.ResponseWriter) { w.WriteHeader(code(err)) }),
|
||||
)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
resp, _ := http.Get(server.URL)
|
||||
if want, have := http.StatusTeapot, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerHappyPath(t *testing.T) {
|
||||
step, response := testServer(t)
|
||||
step()
|
||||
resp := <-response
|
||||
defer resp.Body.Close()
|
||||
buf, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := http.StatusOK, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d (%s)", want, have, buf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleServerBefore(t *testing.T) {
|
||||
var (
|
||||
headerKey = "X-Henlo-Lizer"
|
||||
headerVal = "Helllo you stinky lizard"
|
||||
statusCode = http.StatusTeapot
|
||||
responseBody = "go eat a fly ugly\n"
|
||||
done = make(chan struct{})
|
||||
)
|
||||
handler := httptransport.NewServer(
|
||||
endpoint.Nop,
|
||||
func(context.Context, *http.Request) (interface{}, error) {
|
||||
return struct{}{}, nil
|
||||
},
|
||||
func(_ context.Context, w http.ResponseWriter, _ interface{}) error {
|
||||
w.Header().Set(headerKey, headerVal)
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write([]byte(responseBody))
|
||||
return nil
|
||||
},
|
||||
httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context {
|
||||
ctx = context.WithValue(ctx, "one", 1)
|
||||
|
||||
return ctx
|
||||
}),
|
||||
httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context {
|
||||
if _, ok := ctx.Value("one").(int); !ok {
|
||||
t.Error("Value was not set properly when multiple ServerBefores are used")
|
||||
}
|
||||
|
||||
close(done)
|
||||
return ctx
|
||||
}),
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
go http.Get(server.URL)
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("timeout waiting for finalizer")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleServerAfter(t *testing.T) {
|
||||
var (
|
||||
headerKey = "X-Henlo-Lizer"
|
||||
headerVal = "Helllo you stinky lizard"
|
||||
statusCode = http.StatusTeapot
|
||||
responseBody = "go eat a fly ugly\n"
|
||||
done = make(chan struct{})
|
||||
)
|
||||
handler := httptransport.NewServer(
|
||||
endpoint.Nop,
|
||||
func(context.Context, *http.Request) (interface{}, error) {
|
||||
return struct{}{}, nil
|
||||
},
|
||||
func(_ context.Context, w http.ResponseWriter, _ interface{}) error {
|
||||
w.Header().Set(headerKey, headerVal)
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write([]byte(responseBody))
|
||||
return nil
|
||||
},
|
||||
httptransport.ServerAfter(func(ctx context.Context, w http.ResponseWriter) context.Context {
|
||||
ctx = context.WithValue(ctx, "one", 1)
|
||||
|
||||
return ctx
|
||||
}),
|
||||
httptransport.ServerAfter(func(ctx context.Context, w http.ResponseWriter) context.Context {
|
||||
if _, ok := ctx.Value("one").(int); !ok {
|
||||
t.Error("Value was not set properly when multiple ServerAfters are used")
|
||||
}
|
||||
|
||||
close(done)
|
||||
return ctx
|
||||
}),
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
go http.Get(server.URL)
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("timeout waiting for finalizer")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerFinalizer(t *testing.T) {
|
||||
var (
|
||||
headerKey = "X-Henlo-Lizer"
|
||||
headerVal = "Helllo you stinky lizard"
|
||||
statusCode = http.StatusTeapot
|
||||
responseBody = "go eat a fly ugly\n"
|
||||
done = make(chan struct{})
|
||||
)
|
||||
handler := httptransport.NewServer(
|
||||
endpoint.Nop,
|
||||
func(context.Context, *http.Request) (interface{}, error) {
|
||||
return struct{}{}, nil
|
||||
},
|
||||
func(_ context.Context, w http.ResponseWriter, _ interface{}) error {
|
||||
w.Header().Set(headerKey, headerVal)
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write([]byte(responseBody))
|
||||
return nil
|
||||
},
|
||||
httptransport.ServerFinalizer(func(ctx context.Context, code int, _ *http.Request) {
|
||||
if want, have := statusCode, code; want != have {
|
||||
t.Errorf("StatusCode: want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
responseHeader := ctx.Value(httptransport.ContextKeyResponseHeaders).(http.Header)
|
||||
if want, have := headerVal, responseHeader.Get(headerKey); want != have {
|
||||
t.Errorf("%s: want %q, have %q", headerKey, want, have)
|
||||
}
|
||||
|
||||
responseSize := ctx.Value(httptransport.ContextKeyResponseSize).(int64)
|
||||
if want, have := int64(len(responseBody)), responseSize; want != have {
|
||||
t.Errorf("response size: want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
close(done)
|
||||
}),
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
go http.Get(server.URL)
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("timeout waiting for finalizer")
|
||||
}
|
||||
}
|
||||
|
||||
type enhancedResponse struct {
|
||||
Foo string `json:"foo"`
|
||||
}
|
||||
|
||||
func (e enhancedResponse) StatusCode() int { return http.StatusPaymentRequired }
|
||||
func (e enhancedResponse) Headers() http.Header { return http.Header{"X-Edward": []string{"Snowden"}} }
|
||||
|
||||
func TestEncodeJSONResponse(t *testing.T) {
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return enhancedResponse{Foo: "bar"}, nil },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
httptransport.EncodeJSONResponse,
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, err := http.Get(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if want, have := http.StatusPaymentRequired, resp.StatusCode; want != have {
|
||||
t.Errorf("StatusCode: want %d, have %d", want, have)
|
||||
}
|
||||
if want, have := "Snowden", resp.Header.Get("X-Edward"); want != have {
|
||||
t.Errorf("X-Edward: want %q, have %q", want, have)
|
||||
}
|
||||
buf, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := `{"foo":"bar"}`, strings.TrimSpace(string(buf)); want != have {
|
||||
t.Errorf("Body: want %s, have %s", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
type noContentResponse struct{}
|
||||
|
||||
func (e noContentResponse) StatusCode() int { return http.StatusNoContent }
|
||||
|
||||
func TestEncodeNoContent(t *testing.T) {
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return noContentResponse{}, nil },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
httptransport.EncodeJSONResponse,
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, err := http.Get(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if want, have := http.StatusNoContent, resp.StatusCode; want != have {
|
||||
t.Errorf("StatusCode: want %d, have %d", want, have)
|
||||
}
|
||||
buf, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := 0, len(buf); want != have {
|
||||
t.Errorf("Body: want no content, have %d bytes", have)
|
||||
}
|
||||
}
|
||||
|
||||
type enhancedError struct{}
|
||||
|
||||
func (e enhancedError) Error() string { return "enhanced error" }
|
||||
func (e enhancedError) StatusCode() int { return http.StatusTeapot }
|
||||
func (e enhancedError) MarshalJSON() ([]byte, error) { return []byte(`{"err":"enhanced"}`), nil }
|
||||
func (e enhancedError) Headers() http.Header { return http.Header{"X-Enhanced": []string{"1"}} }
|
||||
|
||||
func TestEnhancedError(t *testing.T) {
|
||||
handler := httptransport.NewServer(
|
||||
func(context.Context, interface{}) (interface{}, error) { return nil, enhancedError{} },
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
func(_ context.Context, w http.ResponseWriter, _ interface{}) error { return nil },
|
||||
)
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, err := http.Get(server.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if want, have := http.StatusTeapot, resp.StatusCode; want != have {
|
||||
t.Errorf("StatusCode: want %d, have %d", want, have)
|
||||
}
|
||||
if want, have := "1", resp.Header.Get("X-Enhanced"); want != have {
|
||||
t.Errorf("X-Enhanced: want %q, have %q", want, have)
|
||||
}
|
||||
buf, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := `{"err":"enhanced"}`, strings.TrimSpace(string(buf)); want != have {
|
||||
t.Errorf("Body: want %s, have %s", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func testServer(t *testing.T) (step func(), resp <-chan *http.Response) {
|
||||
var (
|
||||
stepch = make(chan bool)
|
||||
endpoint = func(context.Context, interface{}) (interface{}, error) { <-stepch; return struct{}{}, nil }
|
||||
response = make(chan *http.Response)
|
||||
handler = httptransport.NewServer(
|
||||
endpoint,
|
||||
func(context.Context, *http.Request) (interface{}, error) { return struct{}{}, nil },
|
||||
func(context.Context, http.ResponseWriter, interface{}) error { return nil },
|
||||
httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context { return ctx }),
|
||||
httptransport.ServerAfter(func(ctx context.Context, w http.ResponseWriter) context.Context { return ctx }),
|
||||
)
|
||||
)
|
||||
go func() {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
resp, err := http.Get(server.URL)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
response <- resp
|
||||
}()
|
||||
return func() { stepch <- true }, response
|
||||
}
|
||||
4
vendor/github.com/go-kit/kit/transport/httprp/doc.go
generated
vendored
Normal file
4
vendor/github.com/go-kit/kit/transport/httprp/doc.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
// Package httprp provides an HTTP reverse-proxy transport. HTTP handlers that
|
||||
// need to proxy requests to another HTTP service can do so with this package by
|
||||
// specifying the URL to forward the request to.
|
||||
package httprp
|
||||
57
vendor/github.com/go-kit/kit/transport/httprp/server.go
generated
vendored
Normal file
57
vendor/github.com/go-kit/kit/transport/httprp/server.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package httprp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// RequestFunc may take information from an HTTP request and put it into a
|
||||
// request context. BeforeFuncs are executed prior to invoking the
|
||||
// endpoint.
|
||||
type RequestFunc func(context.Context, *http.Request) context.Context
|
||||
|
||||
// Server is a proxying request handler.
|
||||
type Server struct {
|
||||
proxy http.Handler
|
||||
before []RequestFunc
|
||||
errorEncoder func(w http.ResponseWriter, err error)
|
||||
}
|
||||
|
||||
// NewServer constructs a new server that implements http.Server and will proxy
|
||||
// requests to the given base URL using its scheme, host, and base path.
|
||||
// If the target's path is "/base" and the incoming request was for "/dir",
|
||||
// the target request will be for /base/dir.
|
||||
func NewServer(
|
||||
baseURL *url.URL,
|
||||
options ...ServerOption,
|
||||
) *Server {
|
||||
s := &Server{
|
||||
proxy: httputil.NewSingleHostReverseProxy(baseURL),
|
||||
}
|
||||
for _, option := range options {
|
||||
option(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ServerOption sets an optional parameter for servers.
|
||||
type ServerOption func(*Server)
|
||||
|
||||
// ServerBefore functions are executed on the HTTP request object before the
|
||||
// request is decoded.
|
||||
func ServerBefore(before ...RequestFunc) ServerOption {
|
||||
return func(s *Server) { s.before = append(s.before, before...) }
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler.
|
||||
func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
for _, f := range s.before {
|
||||
ctx = f(ctx, r)
|
||||
}
|
||||
|
||||
s.proxy.ServeHTTP(w, r)
|
||||
}
|
||||
158
vendor/github.com/go-kit/kit/transport/httprp/server_test.go
generated
vendored
Normal file
158
vendor/github.com/go-kit/kit/transport/httprp/server_test.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
package httprp_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
httptransport "github.com/go-kit/kit/transport/httprp"
|
||||
)
|
||||
|
||||
func TestServerHappyPathSingleServer(t *testing.T) {
|
||||
originServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("hey"))
|
||||
}))
|
||||
defer originServer.Close()
|
||||
originURL, _ := url.Parse(originServer.URL)
|
||||
|
||||
handler := httptransport.NewServer(
|
||||
originURL,
|
||||
)
|
||||
proxyServer := httptest.NewServer(handler)
|
||||
defer proxyServer.Close()
|
||||
|
||||
resp, _ := http.Get(proxyServer.URL)
|
||||
if want, have := http.StatusOK, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
responseBody, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := "hey", string(responseBody); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerHappyPathSingleServerWithServerOptions(t *testing.T) {
|
||||
const (
|
||||
headerKey = "X-TEST-HEADER"
|
||||
headerVal = "go-kit-proxy"
|
||||
)
|
||||
|
||||
originServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if want, have := headerVal, r.Header.Get(headerKey); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("hey"))
|
||||
}))
|
||||
defer originServer.Close()
|
||||
originURL, _ := url.Parse(originServer.URL)
|
||||
|
||||
handler := httptransport.NewServer(
|
||||
originURL,
|
||||
httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context {
|
||||
r.Header.Add(headerKey, headerVal)
|
||||
return ctx
|
||||
}),
|
||||
)
|
||||
proxyServer := httptest.NewServer(handler)
|
||||
defer proxyServer.Close()
|
||||
|
||||
resp, _ := http.Get(proxyServer.URL)
|
||||
if want, have := http.StatusOK, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
responseBody, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := "hey", string(responseBody); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerOriginServerNotFoundResponse(t *testing.T) {
|
||||
originServer := httptest.NewServer(http.NotFoundHandler())
|
||||
defer originServer.Close()
|
||||
originURL, _ := url.Parse(originServer.URL)
|
||||
|
||||
handler := httptransport.NewServer(
|
||||
originURL,
|
||||
)
|
||||
proxyServer := httptest.NewServer(handler)
|
||||
defer proxyServer.Close()
|
||||
|
||||
resp, _ := http.Get(proxyServer.URL)
|
||||
if want, have := http.StatusNotFound, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerOriginServerUnreachable(t *testing.T) {
|
||||
// create a server, then promptly shut it down
|
||||
originServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
originURL, _ := url.Parse(originServer.URL)
|
||||
originServer.Close()
|
||||
|
||||
handler := httptransport.NewServer(
|
||||
originURL,
|
||||
)
|
||||
proxyServer := httptest.NewServer(handler)
|
||||
defer proxyServer.Close()
|
||||
|
||||
resp, _ := http.Get(proxyServer.URL)
|
||||
switch resp.StatusCode {
|
||||
case http.StatusBadGateway: // go1.7 and beyond
|
||||
break
|
||||
case http.StatusInternalServerError: // to go1.7
|
||||
break
|
||||
default:
|
||||
t.Errorf("want %d or %d, have %d", http.StatusBadGateway, http.StatusInternalServerError, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleServerBefore(t *testing.T) {
|
||||
const (
|
||||
headerKey = "X-TEST-HEADER"
|
||||
headerVal = "go-kit-proxy"
|
||||
)
|
||||
|
||||
originServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if want, have := headerVal, r.Header.Get(headerKey); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("hey"))
|
||||
}))
|
||||
defer originServer.Close()
|
||||
originURL, _ := url.Parse(originServer.URL)
|
||||
|
||||
handler := httptransport.NewServer(
|
||||
originURL,
|
||||
httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context {
|
||||
r.Header.Add(headerKey, headerVal)
|
||||
return ctx
|
||||
}),
|
||||
httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context {
|
||||
return ctx
|
||||
}),
|
||||
)
|
||||
proxyServer := httptest.NewServer(handler)
|
||||
defer proxyServer.Close()
|
||||
|
||||
resp, _ := http.Get(proxyServer.URL)
|
||||
if want, have := http.StatusOK, resp.StatusCode; want != have {
|
||||
t.Errorf("want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
responseBody, _ := ioutil.ReadAll(resp.Body)
|
||||
if want, have := "hey", string(responseBody); want != have {
|
||||
t.Errorf("want %q, have %q", want, have)
|
||||
}
|
||||
}
|
||||
14
vendor/github.com/go-kit/kit/transport/netrpc/README.md
generated
vendored
Normal file
14
vendor/github.com/go-kit/kit/transport/netrpc/README.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# net/rpc
|
||||
|
||||
[net/rpc](https://golang.org/pkg/net/rpc) is an RPC transport that's part of the Go standard library.
|
||||
It's a simple and fast transport that's appropriate when all of your services are written in Go.
|
||||
|
||||
Using net/rpc with Go kit is very simple.
|
||||
Just write a simple binding from your service definition to the net/rpc definition.
|
||||
See [netrpc_binding.go](https://github.com/go-kit/kit/blob/ec8b02591ee873433565a1ae9d317353412d1d27/examples/addsvc/netrpc_binding.go) for an example.
|
||||
|
||||
That's it!
|
||||
The net/rpc binding can be registered to a name, and bound to an HTTP handler, the same as any other net/rpc endpoint.
|
||||
And within your service, you can use standard Go kit components and idioms.
|
||||
See [addsvc](https://github.com/go-kit/kit/tree/master/examples/addsvc) for a complete working example with net/rpc support.
|
||||
And remember: Go kit services can support multiple transports simultaneously.
|
||||
32
vendor/github.com/go-kit/kit/transport/thrift/README.md
generated
vendored
Normal file
32
vendor/github.com/go-kit/kit/transport/thrift/README.md
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# Thrift
|
||||
|
||||
[Thrift](https://thrift.apache.org/) is a large IDL and transport package from Apache, popularized by Facebook.
|
||||
Thrift is well-supported in Go kit, for organizations that already have significant Thrift investment.
|
||||
And using Thrift with Go kit is very simple.
|
||||
|
||||
First, define your service in the Thrift IDL.
|
||||
The [Thrift IDL documentation](https://thrift.apache.org/docs/idl) provides more details.
|
||||
See [add.thrift](https://github.com/go-kit/kit/blob/ec8b02591ee873433565a1ae9d317353412d1d27/examples/addsvc/_thrift/add.thrift) for an example.
|
||||
Make sure the Thrift definition matches your service's Go kit (interface) definition.
|
||||
|
||||
Next, [download Thrift](https://thrift.apache.org/download) and [install the compiler](https://thrift.apache.org/docs/install/).
|
||||
On a Mac, you may be able to `brew install thrift`.
|
||||
|
||||
Then, compile your service definition, from .thrift to .go.
|
||||
You'll probably want to specify the package_prefix option to the --gen go flag.
|
||||
See [THRIFT-3021](https://issues.apache.org/jira/browse/THRIFT-3021) for more details.
|
||||
|
||||
```
|
||||
thrift -r --gen go:package_prefix=github.com/my-org/my-repo/thrift/gen-go/ add.thrift
|
||||
```
|
||||
|
||||
Finally, write a tiny binding from your service definition to the Thrift definition.
|
||||
It's a straightforward conversion from one domain to the other.
|
||||
See [thrift_binding.go](https://github.com/go-kit/kit/blob/ec8b02591ee873433565a1ae9d317353412d1d27/examples/addsvc/thrift_binding.go) for an example.
|
||||
|
||||
That's it!
|
||||
The Thrift binding can be bound to a listener and serve normal Thrift requests.
|
||||
And within your service, you can use standard Go kit components and idioms.
|
||||
Unfortunately, setting up a Thrift listener is rather laborious and nonidiomatic in Go.
|
||||
Fortunately, [addsvc](https://github.com/go-kit/kit/tree/master/examples/addsvc) is a complete working example with Thrift support.
|
||||
And remember: Go kit services can support multiple transports simultaneously.
|
||||
Reference in New Issue
Block a user