Skip to content

Commit

Permalink
Update forwarding API
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlAmko committed Sep 26, 2023
1 parent f71bef1 commit 789d87c
Show file tree
Hide file tree
Showing 25 changed files with 637 additions and 292 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.5.0

- Added new forwarding API. See `[Session].ListenAndForward` and `[Session].ListenAndServeHTTP`.
- Deprecates `WithHTTPServer` and `WithHTTPHandler`. Use `[Session].ListenAndServeHTTP` instead.

## 1.4.0

- Switch to `connect.ngrok-agent.com:443` as the default server address
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.4.1
1.5.0
12 changes: 12 additions & 0 deletions config/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,21 @@ type commonOpts struct {
ForwardsTo string
}

type CommonOptionsFunc func(cfg *commonOpts)

type CommonOption interface {
ApplyCommon(cfg *commonOpts)
}

func (of CommonOptionsFunc) ApplyCommon(cfg *commonOpts) {
of(cfg)
}

func (cfg *commonOpts) getForwardsTo() string {
if cfg.ForwardsTo == "" {
return defaultForwardsTo()
}
return cfg.ForwardsTo
}

func (cfg commonOpts) tunnelOptions() {}
58 changes: 8 additions & 50 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package config

import (
"net/http"
"reflect"
"testing"

Expand All @@ -20,14 +19,6 @@ func assertSlice[T any](opts []any) []T {
return out
}

func handlerPtr(h http.Handler) *http.Handler {
return &h
}

func serverPtr(srv *http.Server) **http.Server {
return &srv
}

func labelPtr(labels map[string]*string) *map[string]*string {
return &labels
}
Expand Down Expand Up @@ -55,16 +46,14 @@ func (m matchBindExtra) RequireMatches(t *testing.T, actual proto.BindExtra) {
}

type testCase[T tunnelConfigPrivate, O any] struct {
name string
opts Tunnel
expectForwardsTo *string
expectProto *string
expectExtra *matchBindExtra
expectLabels *map[string]*string
expectHTTPServer **http.Server
expectHTTPHandler *http.Handler
expectOpts func(t *testing.T, opts *O)
expectNilOpts bool
name string
opts Tunnel
expectForwardsTo *string
expectProto *string
expectExtra *matchBindExtra
expectLabels *map[string]*string
expectOpts func(t *testing.T, opts *O)
expectNilOpts bool
}

type testCases[T tunnelConfigPrivate, O any] []testCase[T, O]
Expand Down Expand Up @@ -101,37 +90,6 @@ func (tc testCase[T, O]) Run(t *testing.T) {
require.Truef(t, ok, "Opts has the type %v", reflect.TypeOf((*O)(nil)))
tc.expectOpts(t, opts)
}

if tc.expectHTTPServer != nil {
withHTTPServer, ok := tc.opts.(interface {
HTTPServer() *http.Server
})
if *tc.expectHTTPServer != nil {
require.True(t, ok, "opts should have the HTTPServer method")
actual := withHTTPServer.HTTPServer()
require.Equal(t, *tc.expectHTTPServer, actual)
} else if ok {
require.Nil(t, withHTTPServer.HTTPServer())
}
}

if tc.expectHTTPHandler != nil {
withHTTPServer, ok := tc.opts.(interface {
HTTPServer() *http.Server
})
if *tc.expectHTTPHandler != nil {
require.True(t, ok, "opts should have the HTTPServer method")
actualServer := withHTTPServer.HTTPServer()
require.NotNil(t, actualServer)
actual := actualServer.Handler
require.Equal(t, *tc.expectHTTPHandler, actual)
} else if ok {
actualServer := withHTTPServer.HTTPServer()
if actualServer != nil {
require.Nil(t, actualServer.Handler)
}
}
}
})
}

Expand Down
21 changes: 10 additions & 11 deletions config/forwards_to.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,32 @@ import (
"path/filepath"
)

type forwardsToOption string

// WithForwardsTo sets the ForwardsTo string for this tunnel.
// This can be veiwed via the API or dashboard.
func WithForwardsTo(meta string) interface {
HTTPEndpointOption
LabeledTunnelOption
TCPEndpointOption
TLSEndpointOption
} {
func WithForwardsTo(meta string) Options {
return forwardsToOption(meta)
}

type forwardsToOption string
func (fwd forwardsToOption) ApplyCommon(cfg *commonOpts) {
cfg.ForwardsTo = string(fwd)
}

func (fwd forwardsToOption) ApplyHTTP(cfg *httpOptions) {
cfg.commonOpts.ForwardsTo = string(fwd)
fwd.ApplyCommon(&cfg.commonOpts)
}

func (fwd forwardsToOption) ApplyTCP(cfg *tcpOptions) {
cfg.commonOpts.ForwardsTo = string(fwd)
fwd.ApplyCommon(&cfg.commonOpts)
}

func (fwd forwardsToOption) ApplyTLS(cfg *tlsOptions) {
cfg.commonOpts.ForwardsTo = string(fwd)
fwd.ApplyCommon(&cfg.commonOpts)
}

func (fwd forwardsToOption) ApplyLabeled(cfg *labeledOptions) {
cfg.commonOpts.ForwardsTo = string(fwd)
fwd.ApplyCommon(&cfg.commonOpts)
}

func defaultForwardsTo() string {
Expand Down
10 changes: 8 additions & 2 deletions config/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type httpOptions struct {

// If non-nil, start a goroutine which runs this http server
// accepting connections from the http tunnel
// Deprecated: Pass HTTP server refs via session.ListenAndServeHTTP instead.
httpServer *http.Server

// Certificates to use for client authentication at the ngrok edge.
Expand Down Expand Up @@ -121,22 +122,27 @@ func (cfg *httpOptions) toProtoConfig() *proto.HTTPEndpoint {
return opts
}

func (cfg httpOptions) tunnelOptions() {}

func (cfg httpOptions) ForwardsTo() string {
return cfg.commonOpts.getForwardsTo()
}

func (cfg httpOptions) WithForwardsTo(hostname string) {
cfg.commonOpts.ForwardsTo = hostname
}

func (cfg httpOptions) Extra() proto.BindExtra {
return proto.BindExtra{
Metadata: cfg.Metadata,
}
}

func (cfg httpOptions) Proto() string {
if cfg.Scheme == "" {
return string(SchemeHTTPS)
}
return string(cfg.Scheme)
}

func (cfg httpOptions) Opts() any {
return cfg.toProtoConfig()
}
Expand Down
28 changes: 16 additions & 12 deletions config/http_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ type httpServerOption struct {
Server *http.Server
}

type Options interface {
HTTPEndpointOption
TLSEndpointOption
TCPEndpointOption
LabeledTunnelOption
CommonOption
}

func (opt *httpServerOption) ApplyCommon(cfg *commonOpts) {

}

func (opt *httpServerOption) ApplyHTTP(cfg *httpOptions) {
cfg.httpServer = opt.Server
}
Expand All @@ -26,22 +38,14 @@ func (opt *httpServerOption) ApplyLabeled(cfg *labeledOptions) {

// WithHTTPHandler adds the provided credentials to the list of basic
// authentication credentials.
func WithHTTPHandler(h http.Handler) interface {
HTTPEndpointOption
TLSEndpointOption
TCPEndpointOption
LabeledTunnelOption
} {
// Deprecated: Use session.ListenAndServeHTTP instead.
func WithHTTPHandler(h http.Handler) Options {
return WithHTTPServer(&http.Server{Handler: h})
}

// WithHTTPServer adds the provided credentials to the list of basic
// authentication credentials.
func WithHTTPServer(srv *http.Server) interface {
HTTPEndpointOption
TLSEndpointOption
TCPEndpointOption
LabeledTunnelOption
} {
// Deprecated: Use session.ListenAndServeHTTP instead.
func WithHTTPServer(srv *http.Server) Options {
return &httpServerOption{Server: srv}
}
50 changes: 0 additions & 50 deletions config/http_handler_test.go

This file was deleted.

11 changes: 9 additions & 2 deletions config/labeled.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type labeledOptions struct {
labels map[string]string

// An HTTP Server to run traffic on
// Deprecated: Pass HTTP server refs via session.ListenAndServeHTTP instead.
httpServer *http.Server
}

Expand All @@ -48,22 +49,28 @@ func WithLabel(label, value string) LabeledTunnelOption {
})
}

func (cfg labeledOptions) tunnelOptions() {}

func (cfg labeledOptions) ForwardsTo() string {
return cfg.commonOpts.getForwardsTo()
}

func (cfg labeledOptions) WithForwardsTo(hostname string) {
cfg.commonOpts.ForwardsTo = hostname
}

func (cfg labeledOptions) Extra() proto.BindExtra {
return proto.BindExtra{
Metadata: cfg.Metadata,
}
}

func (cfg labeledOptions) Proto() string {
return ""
}

func (cfg labeledOptions) Opts() any {
return nil
}

func (cfg labeledOptions) Labels() map[string]string {
return cfg.labels
}
Expand Down
11 changes: 9 additions & 2 deletions config/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type tcpOptions struct {
// The TCP address to request for this edge.
RemoteAddr string
// An HTTP Server to run traffic on
// Deprecated: Pass HTTP server refs via session.ListenAndServeHTTP instead.
httpServer *http.Server
}

Expand All @@ -50,22 +51,28 @@ func (cfg *tcpOptions) toProtoConfig() *proto.TCPEndpoint {
}
}

func (cfg tcpOptions) tunnelOptions() {}

func (cfg tcpOptions) ForwardsTo() string {
return cfg.commonOpts.getForwardsTo()
}

func (cfg tcpOptions) WithForwardsTo(hostname string) {
cfg.commonOpts.ForwardsTo = hostname
}

func (cfg tcpOptions) Extra() proto.BindExtra {
return proto.BindExtra{
Metadata: cfg.Metadata,
}
}

func (cfg tcpOptions) Proto() string {
return "tcp"
}

func (cfg tcpOptions) Opts() any {
return cfg.toProtoConfig()
}

func (cfg tcpOptions) Labels() map[string]string {
return nil
}
Expand Down
Loading

0 comments on commit 789d87c

Please sign in to comment.