yarpc / yarpc-go

@@ -96,6 +96,28 @@
Loading
96 96
	return nil
97 97
}
98 98
99 +
// Serve starts the HTTP server up in the background on the given
100 +
// listener and returns immediately.
101 +
//
102 +
// An error is returned if the server failed to start up, if the server was
103 +
// already listening, or if the server was stopped with Stop().
104 +
func (h *HTTPServer) Serve(lis net.Listener) error {
105 +
	if h.stopped.Load() {
106 +
		return errServerStopped
107 +
	}
108 +
109 +
	h.lock.Lock()
110 +
	defer h.lock.Unlock()
111 +
112 +
	if h.listener != nil {
113 +
		return errAlreadyListening
114 +
	}
115 +
116 +
	h.listener = lis
117 +
	go h.serve(h.listener)
118 +
	return nil
119 +
}
120 +
99 121
func (h *HTTPServer) serve(listener net.Listener) {
100 122
	// Serve always returns a non-nil error. For us, it's an error only if
101 123
	// we didn't call Stop().

@@ -22,6 +22,8 @@
Loading
22 22
23 23
import (
24 24
	"context"
25 +
	"crypto/tls"
26 +
	"errors"
25 27
	"net"
26 28
	"net/http"
27 29
	"strings"
@@ -29,9 +31,11 @@
Loading
29 31
30 32
	"github.com/opentracing/opentracing-go"
31 33
	"go.uber.org/yarpc/api/transport"
34 +
	yarpctls "go.uber.org/yarpc/api/transport/tls"
32 35
	"go.uber.org/yarpc/api/x/introspection"
33 36
	intnet "go.uber.org/yarpc/internal/net"
34 37
	"go.uber.org/yarpc/pkg/lifecycle"
38 +
	"go.uber.org/yarpc/transport/internal/tlsmux"
35 39
	"go.uber.org/yarpc/yarpcerrors"
36 40
	"go.uber.org/zap"
37 41
)
@@ -103,6 +107,23 @@
Loading
103 107
	}
104 108
}
105 109
110 +
// InboundTLSConfiguration returns an InboundOption that provides the TLS
111 +
// confiugration used for setting up TLS inbound.
112 +
func InboundTLSConfiguration(tlsConfig *tls.Config) InboundOption {
113 +
	return func(i *Inbound) {
114 +
		i.tlsConfig = tlsConfig
115 +
	}
116 +
}
117 +
118 +
// InboundTLSMode returns an InboundOption that sets inbound TLS mode.
119 +
// It must be noted that TLS configuration must be passed separately using inbound
120 +
// option InboundTLSConfiguration.
121 +
func InboundTLSMode(mode yarpctls.Mode) InboundOption {
122 +
	return func(i *Inbound) {
123 +
		i.tlsMode = mode
124 +
	}
125 +
}
126 +
106 127
// NewInbound builds a new HTTP inbound that listens on the given address and
107 128
// sharing this transport.
108 129
func (t *Transport) NewInbound(addr string, opts ...InboundOption) *Inbound {
@@ -141,6 +162,9 @@
Loading
141 162
142 163
	// should only be false in testing
143 164
	bothResponseError bool
165 +
166 +
	tlsConfig *tls.Config
167 +
	tlsMode   yarpctls.Mode
144 168
}
145 169
146 170
// Tracer configures a tracer on this inbound.
@@ -201,7 +225,34 @@
Loading
201 225
		Addr:    i.addr,
202 226
		Handler: httpHandler,
203 227
	})
204 -
	if err := i.server.ListenAndServe(); err != nil {
228 +
229 +
	addr := i.addr
230 +
	if addr == "" {
231 +
		addr = ":http"
232 +
	}
233 +
234 +
	listener, err := net.Listen("tcp", addr)
235 +
	if err != nil {
236 +
		return err
237 +
	}
238 +
239 +
	if i.tlsMode != yarpctls.Disabled {
240 +
		if i.tlsConfig == nil {
241 +
			return errors.New("HTTP TLS enabled but configuration not provided")
242 +
		}
243 +
244 +
		listener = tlsmux.NewListener(tlsmux.Config{
245 +
			Listener:      listener,
246 +
			TLSConfig:     i.tlsConfig,
247 +
			ServiceName:   i.transport.serviceName,
248 +
			TransportName: TransportName,
249 +
			Meter:         i.transport.meter,
250 +
			Logger:        i.logger,
251 +
			Mode:          i.tlsMode,
252 +
		})
253 +
	}
254 +
255 +
	if err := i.server.Serve(listener); err != nil {
205 256
		return err
206 257
	}
207 258

@@ -25,6 +25,7 @@
Loading
25 25
	"time"
26 26
27 27
	"go.uber.org/yarpc/api/transport"
28 +
	yarpctls "go.uber.org/yarpc/api/transport/tls"
28 29
	"go.uber.org/yarpc/peer/hostport"
29 30
	"go.uber.org/yarpc/yarpcconfig"
30 31
)
@@ -116,6 +117,9 @@
Loading
116 117
		opt(&options)
117 118
	}
118 119
120 +
	if options.serviceName == "" {
121 +
		options.serviceName = k.ServiceName()
122 +
	}
119 123
	if tc.KeepAlive > 0 {
120 124
		options.keepAlive = tc.KeepAlive
121 125
	}
@@ -167,13 +171,25 @@
Loading
167 171
	GrabHeaders []string `config:"grabHeaders"`
168 172
	// The maximum amount of time to wait for the inbound to shutdown.
169 173
	ShutdownTimeout *time.Duration `config:"shutdownTimeout"`
174 +
	// TLS configuration of the inbound.
175 +
	TLSConfig TLSConfig `config:"tls"`
176 +
}
177 +
178 +
// TLSConfig specifies the TLS configuration of the HTTP inbound.
179 +
type TLSConfig struct {
180 +
	// Mode when set to Permissive or Enforced enables TLS inbound and
181 +
	// TLS configuration must be passed as an inbound option.
182 +
	Mode yarpctls.Mode `config:"mode,interpolate"`
170 183
}
171 184
172 185
func (ts *transportSpec) buildInbound(ic *InboundConfig, t transport.Transport, k *yarpcconfig.Kit) (transport.Inbound, error) {
173 186
	if ic.Address == "" {
174 187
		return nil, fmt.Errorf("inbound address is required")
175 188
	}
176 -
	inboundOptions := ts.InboundOptions
189 +
190 +
	// TLS mode provided in the inbound options takes higher precedence than
191 +
	// the TLS mode passed in YAML config.
192 +
	inboundOptions := append([]InboundOption{InboundTLSMode(ic.TLSConfig.Mode)}, ts.InboundOptions...)
177 193
	if len(ic.GrabHeaders) > 0 {
178 194
		inboundOptions = append(inboundOptions, GrabHeaders(ic.GrabHeaders...))
179 195
	}

@@ -42,10 +42,12 @@
Loading
42 42
	// defensive programming
43 43
	// these are copied from grpc-go but we set them explicitly here
44 44
	// in case these change in grpc-go so that yarpc stays consistent
45 -
	defaultServerMaxRecvMsgSize = 1024 * 1024 * 4
46 45
	defaultServerMaxSendMsgSize = math.MaxInt32
47 -
	defaultClientMaxRecvMsgSize = 1024 * 1024 * 4
48 46
	defaultClientMaxSendMsgSize = math.MaxInt32
47 +
	// Overriding default server and client maximum request and response
48 +
	// receive sizes to 64MB.
49 +
	defaultServerMaxRecvMsgSize = 1024 * 1024 * 64
50 +
	defaultClientMaxRecvMsgSize = 1024 * 1024 * 64
49 51
)
50 52
51 53
// Option is an interface shared by TransportOption, InboundOption, and OutboundOption

@@ -29,6 +29,7 @@
Loading
29 29
	"time"
30 30
31 31
	"github.com/opentracing/opentracing-go"
32 +
	"go.uber.org/net/metrics"
32 33
	backoffapi "go.uber.org/yarpc/api/backoff"
33 34
	"go.uber.org/yarpc/api/peer"
34 35
	"go.uber.org/yarpc/api/transport"
@@ -53,6 +54,8 @@
Loading
53 54
	tracer                opentracing.Tracer
54 55
	buildClient           func(*transportOptions) *http.Client
55 56
	logger                *zap.Logger
57 +
	meter                 *metrics.Scope
58 +
	serviceName           string
56 59
}
57 60
58 61
var defaultTransportOptions = transportOptions{
@@ -216,6 +219,23 @@
Loading
216 219
	}
217 220
}
218 221
222 +
// Meter sets a meter to use for internal transport metrics.
223 +
//
224 +
// The default is to not emit any metrics.
225 +
func Meter(meter *metrics.Scope) TransportOption {
226 +
	return func(options *transportOptions) {
227 +
		options.meter = meter
228 +
	}
229 +
}
230 +
231 +
// ServiceName sets the name of the service used in transport logging
232 +
// and metrics.
233 +
func ServiceName(name string) TransportOption {
234 +
	return func(options *transportOptions) {
235 +
		options.serviceName = name
236 +
	}
237 +
}
238 +
219 239
// Hidden option to override the buildHTTPClient function. This is used only
220 240
// for testing.
221 241
func buildClient(f func(*transportOptions) *http.Client) TransportOption {
@@ -248,6 +268,8 @@
Loading
248 268
		peers:               make(map[string]*httpPeer),
249 269
		tracer:              o.tracer,
250 270
		logger:              logger,
271 +
		meter:               o.meter,
272 +
		serviceName:         o.serviceName,
251 273
	}
252 274
}
253 275
@@ -293,8 +315,10 @@
Loading
293 315
	innocenceWindow     time.Duration
294 316
	jitter              func(int64) int64
295 317
296 -
	tracer opentracing.Tracer
297 -
	logger *zap.Logger
318 +
	tracer      opentracing.Tracer
319 +
	logger      *zap.Logger
320 +
	meter       *metrics.Scope
321 +
	serviceName string
298 322
}
299 323
300 324
var _ transport.Transport = (*Transport)(nil)
Files Coverage
api 97.20%
compressor 92.86%
encoding 80.36%
internal 84.83%
peer 87.41%
pkg 95.27%
transport 89.90%
x/debug 92.31%
yarpcconfig 92.76%
yarpcerrors 98.96%
call.go 100.00%
config.go 80.56%
dispatcher.go 96.23%
dispatcher_introspection.go 85.71%
dispatcher_startup.go 91.07%
errors.go 100.00%
header.go 100.00%
inject.go 96.55%
middleware.go 100.00%
router.go 96.00%
serialize/serialize.go 76.47%
Project Totals (254 files) 87.72%
1
codecov:
2
  branch: dev
3
coverage:
4
  range: 50...90
5
  status:
6
    project:
7
      default:
8
        enabled: yes
9
        target: 80%
10
    patch:
11
      default:
12
        enabled: yes
13
        target: 80%
14
# This list is generated using scripts/generate-cover-ignore.sh
15
# All packages with .nocover files in them MUST be listed here
16
ignore:
17
 - /api/transport/tls/
18
 - /encoding/protobuf/internal/testpb/
19
 - /encoding/thrift/internal/
20
 - /encoding/thrift/internal/observabilitytest/test/
21
 - /encoding/thrift/internal/observabilitytest/test/testserviceclient/
22
 - /encoding/thrift/internal/observabilitytest/test/testservicefx/
23
 - /encoding/thrift/internal/observabilitytest/test/testserviceserver/
24
 - /encoding/thrift/internal/observabilitytest/test/testservicetest/
25
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/NOSERVICES/
26
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/
27
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/readonlystoreclient/
28
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/readonlystorefx/
29
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/readonlystoreserver/
30
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/readonlystoretest/
31
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/storeclient/
32
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/storefx/
33
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/storeserver/
34
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/atomic/storetest/
35
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/
36
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/baseserviceclient/
37
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/baseservicefx/
38
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/baseserviceserver/
39
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/baseservicetest/
40
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/emptyserviceclient/
41
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/emptyservicefx/
42
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/emptyserviceserver/
43
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/emptyservicetest/
44
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendemptyclient/
45
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendemptyfx/
46
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendemptyserver/
47
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendemptytest/
48
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendonlyclient/
49
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendonlyfx/
50
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendonlyserver/
51
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/common/extendonlytest/
52
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/
53
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/barclient/
54
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/barfx/
55
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/barserver/
56
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/bartest/
57
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/fooclient/
58
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/foofx/
59
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/fooserver/
60
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/footest/
61
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/nameclient/
62
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/namefx/
63
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/nameserver/
64
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/extends/nametest/
65
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/weather/
66
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/weather/weatherclient/
67
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/weather/weatherfx/
68
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/weather/weatherserver/
69
 - /encoding/thrift/thriftrw-plugin-yarpc/internal/tests/weather/weathertest/
70
 - /internal/cover/
71
 - /internal/crossdock/crossdockpb/
72
 - /internal/crossdock/thrift/echo/
73
 - /internal/crossdock/thrift/echo/echoclient/
74
 - /internal/crossdock/thrift/echo/echofx/
75
 - /internal/crossdock/thrift/echo/echoserver/
76
 - /internal/crossdock/thrift/echo/echotest/
77
 - /internal/crossdock/thrift/gauntlet/
78
 - /internal/crossdock/thrift/gauntlet/secondserviceclient/
79
 - /internal/crossdock/thrift/gauntlet/secondservicefx/
80
 - /internal/crossdock/thrift/gauntlet/secondserviceserver/
81
 - /internal/crossdock/thrift/gauntlet/secondservicetest/
82
 - /internal/crossdock/thrift/gauntlet/thrifttestclient/
83
 - /internal/crossdock/thrift/gauntlet/thrifttestfx/
84
 - /internal/crossdock/thrift/gauntlet/thrifttestserver/
85
 - /internal/crossdock/thrift/gauntlet/thrifttesttest/
86
 - /internal/crossdock/thrift/gen-go/echo/
87
 - /internal/crossdock/thrift/gen-go/gauntlet_apache/
88
 - /internal/crossdock/thrift/gen-go/gauntlet_tchannel/
89
 - /internal/crossdock/thrift/oneway/
90
 - /internal/crossdock/thrift/oneway/onewayclient/
91
 - /internal/crossdock/thrift/oneway/onewayfx/
92
 - /internal/crossdock/thrift/oneway/onewayserver/
93
 - /internal/crossdock/thrift/oneway/onewaytest/
94
 - /internal/examples/json-keyvalue/client/
95
 - /internal/examples/json-keyvalue/server/
96
 - /internal/examples/protobuf/
97
 - /internal/examples/protobuf/example/
98
 - /internal/examples/protobuf/examplepb/
99
 - /internal/examples/protobuf/exampleutil/
100
 - /internal/examples/streaming/
101
 - /internal/examples/streaming/client/
102
 - /internal/examples/streaming/server/
103
 - /internal/examples/thrift-hello/hello/
104
 - /internal/examples/thrift-hello/hello/echo/
105
 - /internal/examples/thrift-hello/hello/echo/helloclient/
106
 - /internal/examples/thrift-hello/hello/echo/hellofx/
107
 - /internal/examples/thrift-hello/hello/echo/helloserver/
108
 - /internal/examples/thrift-hello/hello/echo/hellotest/
109
 - /internal/examples/thrift-keyvalue/keyvalue/client/
110
 - /internal/examples/thrift-keyvalue/keyvalue/kv/
111
 - /internal/examples/thrift-keyvalue/keyvalue/kv/keyvalueclient/
112
 - /internal/examples/thrift-keyvalue/keyvalue/kv/keyvaluefx/
113
 - /internal/examples/thrift-keyvalue/keyvalue/kv/keyvalueserver/
114
 - /internal/examples/thrift-keyvalue/keyvalue/kv/keyvaluetest/
115
 - /internal/examples/thrift-keyvalue/keyvalue/server/
116
 - /internal/examples/thrift-oneway/
117
 - /internal/examples/thrift-oneway/sink/
118
 - /internal/examples/thrift-oneway/sink/helloclient/
119
 - /internal/examples/thrift-oneway/sink/hellofx/
120
 - /internal/examples/thrift-oneway/sink/helloserver/
121
 - /internal/examples/thrift-oneway/sink/hellotest/
122
 - /internal/prototest/example/
123
 - /internal/prototest/examplepb/
124
 - /internal/prototest/exampleutil/
125
 - /internal/service-test/
126
 - /internal/testutils/
127
 - /serialize/internal/
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading