diff --git a/clientcompat/internal/clientcompat/clientcompat.twirp.go b/clientcompat/internal/clientcompat/clientcompat.twirp.go index 9ac493be..508898f1 100644 --- a/clientcompat/internal/clientcompat/clientcompat.twirp.go +++ b/clientcompat/internal/clientcompat/clientcompat.twirp.go @@ -43,36 +43,39 @@ type CompatService interface { // ============================= type compatServiceProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [2]string } // NewCompatServiceProtobufClient creates a Protobuf client that implements the CompatService interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewCompatServiceProtobufClient(addr string, client HTTPClient) CompatService { + prefix := urlBase(addr) + CompatServicePathPrefix + urls := [2]string{ + prefix + "Method", + prefix + "NoopMethod", + } if httpClient, ok := client.(*http.Client); ok { return &compatServiceProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &compatServiceProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *compatServiceProtobufClient) Method(ctx context.Context, in *Req) (*Resp, error) { - url := c.urlBase + CompatServicePathPrefix + "Method" out := new(Resp) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } func (c *compatServiceProtobufClient) NoopMethod(ctx context.Context, in *Empty) (*Empty, error) { - url := c.urlBase + CompatServicePathPrefix + "NoopMethod" out := new(Empty) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[1], in, out) return out, err } @@ -81,36 +84,39 @@ func (c *compatServiceProtobufClient) NoopMethod(ctx context.Context, in *Empty) // ========================= type compatServiceJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [2]string } // NewCompatServiceJSONClient creates a JSON client that implements the CompatService interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewCompatServiceJSONClient(addr string, client HTTPClient) CompatService { + prefix := urlBase(addr) + CompatServicePathPrefix + urls := [2]string{ + prefix + "Method", + prefix + "NoopMethod", + } if httpClient, ok := client.(*http.Client); ok { return &compatServiceJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &compatServiceJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *compatServiceJSONClient) Method(ctx context.Context, in *Req) (*Resp, error) { - url := c.urlBase + CompatServicePathPrefix + "Method" out := new(Resp) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } func (c *compatServiceJSONClient) NoopMethod(ctx context.Context, in *Empty) (*Empty, error) { - url := c.urlBase + CompatServicePathPrefix + "NoopMethod" out := new(Empty) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[1], in, out) return out, err } diff --git a/example/service.twirp.go b/example/service.twirp.go index 87258a2e..3fbfd6e5 100644 --- a/example/service.twirp.go +++ b/example/service.twirp.go @@ -43,29 +43,32 @@ type Haberdasher interface { // =========================== type haberdasherProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewHaberdasherProtobufClient creates a Protobuf client that implements the Haberdasher interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewHaberdasherProtobufClient(addr string, client HTTPClient) Haberdasher { + prefix := urlBase(addr) + HaberdasherPathPrefix + urls := [1]string{ + prefix + "MakeHat", + } if httpClient, ok := client.(*http.Client); ok { return &haberdasherProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &haberdasherProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *haberdasherProtobufClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { - url := c.urlBase + HaberdasherPathPrefix + "MakeHat" out := new(Hat) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -74,29 +77,32 @@ func (c *haberdasherProtobufClient) MakeHat(ctx context.Context, in *Size) (*Hat // ======================= type haberdasherJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewHaberdasherJSONClient creates a JSON client that implements the Haberdasher interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewHaberdasherJSONClient(addr string, client HTTPClient) Haberdasher { + prefix := urlBase(addr) + HaberdasherPathPrefix + urls := [1]string{ + prefix + "MakeHat", + } if httpClient, ok := client.(*http.Client); ok { return &haberdasherJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &haberdasherJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *haberdasherJSONClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { - url := c.urlBase + HaberdasherPathPrefix + "MakeHat" out := new(Hat) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/gogo_compat/service.twirp.go b/internal/twirptest/gogo_compat/service.twirp.go index ed83ffdf..b9cde54e 100644 --- a/internal/twirptest/gogo_compat/service.twirp.go +++ b/internal/twirptest/gogo_compat/service.twirp.go @@ -45,29 +45,32 @@ type Svc interface { // =================== type svcProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvcProtobufClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -76,29 +79,32 @@ func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { // =============== type svcJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvcJSONClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/importable/importable.twirp.go b/internal/twirptest/importable/importable.twirp.go index b9976456..2484f77f 100644 --- a/internal/twirptest/importable/importable.twirp.go +++ b/internal/twirptest/importable/importable.twirp.go @@ -44,29 +44,32 @@ type Svc interface { // =================== type svcProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvcProtobufClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -75,29 +78,32 @@ func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { // =============== type svcJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvcJSONClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/importer/importer.twirp.go b/internal/twirptest/importer/importer.twirp.go index 7f79eb1f..9fdeb407 100644 --- a/internal/twirptest/importer/importer.twirp.go +++ b/internal/twirptest/importer/importer.twirp.go @@ -46,29 +46,32 @@ type Svc2 interface { // ==================== type svc2ProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvc2ProtobufClient creates a Protobuf client that implements the Svc2 interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvc2ProtobufClient(addr string, client HTTPClient) Svc2 { + prefix := urlBase(addr) + Svc2PathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svc2ProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svc2ProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svc2ProtobufClient) Send(ctx context.Context, in *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { - url := c.urlBase + Svc2PathPrefix + "Send" out := new(twirp_internal_twirptest_importable.Msg) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -77,29 +80,32 @@ func (c *svc2ProtobufClient) Send(ctx context.Context, in *twirp_internal_twirpt // ================ type svc2JSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvc2JSONClient creates a JSON client that implements the Svc2 interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvc2JSONClient(addr string, client HTTPClient) Svc2 { + prefix := urlBase(addr) + Svc2PathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svc2JSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svc2JSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svc2JSONClient) Send(ctx context.Context, in *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { - url := c.urlBase + Svc2PathPrefix + "Send" out := new(twirp_internal_twirptest_importable.Msg) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/multiple/multiple1.twirp.go b/internal/twirptest/multiple/multiple1.twirp.go index e64a4968..bcc6a72a 100644 --- a/internal/twirptest/multiple/multiple1.twirp.go +++ b/internal/twirptest/multiple/multiple1.twirp.go @@ -45,29 +45,32 @@ type Svc1 interface { // ==================== type svc1ProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvc1ProtobufClient creates a Protobuf client that implements the Svc1 interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvc1ProtobufClient(addr string, client HTTPClient) Svc1 { + prefix := urlBase(addr) + Svc1PathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svc1ProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svc1ProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svc1ProtobufClient) Send(ctx context.Context, in *Msg1) (*Msg1, error) { - url := c.urlBase + Svc1PathPrefix + "Send" out := new(Msg1) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -76,29 +79,32 @@ func (c *svc1ProtobufClient) Send(ctx context.Context, in *Msg1) (*Msg1, error) // ================ type svc1JSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvc1JSONClient creates a JSON client that implements the Svc1 interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvc1JSONClient(addr string, client HTTPClient) Svc1 { + prefix := urlBase(addr) + Svc1PathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svc1JSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svc1JSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svc1JSONClient) Send(ctx context.Context, in *Msg1) (*Msg1, error) { - url := c.urlBase + Svc1PathPrefix + "Send" out := new(Msg1) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/multiple/multiple2.twirp.go b/internal/twirptest/multiple/multiple2.twirp.go index ad992f49..66ee7e3e 100644 --- a/internal/twirptest/multiple/multiple2.twirp.go +++ b/internal/twirptest/multiple/multiple2.twirp.go @@ -30,36 +30,39 @@ type Svc2 interface { // ==================== type svc2ProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [2]string } // NewSvc2ProtobufClient creates a Protobuf client that implements the Svc2 interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvc2ProtobufClient(addr string, client HTTPClient) Svc2 { + prefix := urlBase(addr) + Svc2PathPrefix + urls := [2]string{ + prefix + "Send", + prefix + "SamePackageProtoImport", + } if httpClient, ok := client.(*http.Client); ok { return &svc2ProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svc2ProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svc2ProtobufClient) Send(ctx context.Context, in *Msg2) (*Msg2, error) { - url := c.urlBase + Svc2PathPrefix + "Send" out := new(Msg2) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } func (c *svc2ProtobufClient) SamePackageProtoImport(ctx context.Context, in *Msg1) (*Msg1, error) { - url := c.urlBase + Svc2PathPrefix + "SamePackageProtoImport" out := new(Msg1) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[1], in, out) return out, err } @@ -68,36 +71,39 @@ func (c *svc2ProtobufClient) SamePackageProtoImport(ctx context.Context, in *Msg // ================ type svc2JSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [2]string } // NewSvc2JSONClient creates a JSON client that implements the Svc2 interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvc2JSONClient(addr string, client HTTPClient) Svc2 { + prefix := urlBase(addr) + Svc2PathPrefix + urls := [2]string{ + prefix + "Send", + prefix + "SamePackageProtoImport", + } if httpClient, ok := client.(*http.Client); ok { return &svc2JSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svc2JSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svc2JSONClient) Send(ctx context.Context, in *Msg2) (*Msg2, error) { - url := c.urlBase + Svc2PathPrefix + "Send" out := new(Msg2) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } func (c *svc2JSONClient) SamePackageProtoImport(ctx context.Context, in *Msg1) (*Msg1, error) { - url := c.urlBase + Svc2PathPrefix + "SamePackageProtoImport" out := new(Msg1) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[1], in, out) return out, err } diff --git a/internal/twirptest/no_package_name/no_package_name.twirp.go b/internal/twirptest/no_package_name/no_package_name.twirp.go index 08c9a4fe..4b70f603 100644 --- a/internal/twirptest/no_package_name/no_package_name.twirp.go +++ b/internal/twirptest/no_package_name/no_package_name.twirp.go @@ -41,29 +41,32 @@ type Svc interface { // =================== type svcProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvcProtobufClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -72,29 +75,32 @@ func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { // =============== type svcJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvcJSONClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/no_package_name_importer/no_package_name_importer.twirp.go b/internal/twirptest/no_package_name_importer/no_package_name_importer.twirp.go index 86638174..347bf52e 100644 --- a/internal/twirptest/no_package_name_importer/no_package_name_importer.twirp.go +++ b/internal/twirptest/no_package_name_importer/no_package_name_importer.twirp.go @@ -43,23 +43,32 @@ type Svc2 interface { // ==================== type svc2ProtobufClient struct { - urlBase string - client *http.Client + client HTTPClient + urls [1]string } // NewSvc2ProtobufClient creates a Protobuf client that implements the Svc2 interface. // It communicates using protobuf messages and can be configured with a custom http.Client. -func NewSvc2ProtobufClient(addr string, client *http.Client) Svc2 { +func NewSvc2ProtobufClient(addr string, client HTTPClient) Svc2 { + prefix := urlBase(addr) + Svc2PathPrefix + urls := [1]string{ + prefix + "Method", + } + if httpClient, ok := client.(*http.Client); ok { + return &svc2ProtobufClient{ + client: withoutRedirects(httpClient), + urls: urls, + } + } return &svc2ProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(client), + client: client, + urls: urls, } } func (c *svc2ProtobufClient) Method(ctx context.Context, in *no_package_name.Msg) (*no_package_name.Msg, error) { - url := c.urlBase + Svc2PathPrefix + "Method" out := new(no_package_name.Msg) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -68,23 +77,32 @@ func (c *svc2ProtobufClient) Method(ctx context.Context, in *no_package_name.Msg // ================ type svc2JSONClient struct { - urlBase string - client *http.Client + client HTTPClient + urls [1]string } // NewSvc2JSONClient creates a JSON client that implements the Svc2 interface. // It communicates using JSON requests and responses instead of protobuf messages. -func NewSvc2JSONClient(addr string, client *http.Client) Svc2 { +func NewSvc2JSONClient(addr string, client HTTPClient) Svc2 { + prefix := urlBase(addr) + Svc2PathPrefix + urls := [1]string{ + prefix + "Method", + } + if httpClient, ok := client.(*http.Client); ok { + return &svc2JSONClient{ + client: withoutRedirects(httpClient), + urls: urls, + } + } return &svc2JSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(client), + client: client, + urls: urls, } } func (c *svc2JSONClient) Method(ctx context.Context, in *no_package_name.Msg) (*no_package_name.Msg, error) { - url := c.urlBase + Svc2PathPrefix + "Method" out := new(no_package_name.Msg) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -294,6 +312,18 @@ func (s *svc2Server) ProtocGenTwirpVersion() string { // Utils // ===== +// HTTPClient is the interface used by generated clients to send HTTP requests. +// It is fulfilled by *(net/http).Client, which is sufficient for most users. +// Users can provide their own implementation for special retry policies. +// +// HTTPClient implementations should not follow redirects. Redirects are +// automatically disabled if *(net/http).Client is passed to client +// constructors. See the withoutRedirects function in this file for more +// details. +type HTTPClient interface { + Do(req *http.Request) (*http.Response, error) +} + // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. @@ -559,7 +589,7 @@ func withoutRedirects(in *http.Client) *http.Client { } // doProtoRequest is common code to make a request to the remote twirp service. -func doProtoRequest(ctx context.Context, client *http.Client, url string, in, out proto.Message) error { +func doProtoRequest(ctx context.Context, client HTTPClient, url string, in, out proto.Message) error { var err error reqBodyBytes, err := proto.Marshal(in) if err != nil { @@ -602,7 +632,7 @@ func doProtoRequest(ctx context.Context, client *http.Client, url string, in, ou } // doJSONRequest is common code to make a request to the remote twirp service. -func doJSONRequest(ctx context.Context, client *http.Client, url string, in, out proto.Message) error { +func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out proto.Message) error { var err error reqBody := bytes.NewBuffer(nil) marshaler := &jsonpb.Marshaler{OrigName: true} diff --git a/internal/twirptest/proto/proto.twirp.go b/internal/twirptest/proto/proto.twirp.go index 7f645748..b60e29d6 100644 --- a/internal/twirptest/proto/proto.twirp.go +++ b/internal/twirptest/proto/proto.twirp.go @@ -44,29 +44,32 @@ type Svc interface { // =================== type svcProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewSvcProtobufClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -75,29 +78,32 @@ func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { // =============== type svcJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewSvcJSONClient(addr string, client HTTPClient) Svc { + prefix := urlBase(addr) + SvcPathPrefix + urls := [1]string{ + prefix + "Send", + } if httpClient, ok := client.(*http.Client); ok { return &svcJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &svcJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { - url := c.urlBase + SvcPathPrefix + "Send" out := new(Msg) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/internal/twirptest/service.twirp.go b/internal/twirptest/service.twirp.go index a1ecda1a..455daaa5 100644 --- a/internal/twirptest/service.twirp.go +++ b/internal/twirptest/service.twirp.go @@ -43,29 +43,32 @@ type Haberdasher interface { // =========================== type haberdasherProtobufClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewHaberdasherProtobufClient creates a Protobuf client that implements the Haberdasher interface. // It communicates using protobuf messages and can be configured with a custom http.Client. func NewHaberdasherProtobufClient(addr string, client HTTPClient) Haberdasher { + prefix := urlBase(addr) + HaberdasherPathPrefix + urls := [1]string{ + prefix + "MakeHat", + } if httpClient, ok := client.(*http.Client); ok { return &haberdasherProtobufClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &haberdasherProtobufClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *haberdasherProtobufClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { - url := c.urlBase + HaberdasherPathPrefix + "MakeHat" out := new(Hat) - err := doProtoRequest(ctx, c.client, url, in, out) + err := doProtoRequest(ctx, c.client, c.urls[0], in, out) return out, err } @@ -74,29 +77,32 @@ func (c *haberdasherProtobufClient) MakeHat(ctx context.Context, in *Size) (*Hat // ======================= type haberdasherJSONClient struct { - urlBase string - client HTTPClient + client HTTPClient + urls [1]string } // NewHaberdasherJSONClient creates a JSON client that implements the Haberdasher interface. // It communicates using JSON requests and responses instead of protobuf messages. func NewHaberdasherJSONClient(addr string, client HTTPClient) Haberdasher { + prefix := urlBase(addr) + HaberdasherPathPrefix + urls := [1]string{ + prefix + "MakeHat", + } if httpClient, ok := client.(*http.Client); ok { return &haberdasherJSONClient{ - urlBase: urlBase(addr), - client: withoutRedirects(httpClient), + client: withoutRedirects(httpClient), + urls: urls, } } return &haberdasherJSONClient{ - urlBase: urlBase(addr), - client: client, + client: client, + urls: urls, } } func (c *haberdasherJSONClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { - url := c.urlBase + HaberdasherPathPrefix + "MakeHat" out := new(Hat) - err := doJSONRequest(ctx, c.client, url, in, out) + err := doJSONRequest(ctx, c.client, c.urls[0], in, out) return out, err } diff --git a/protoc-gen-twirp/generator.go b/protoc-gen-twirp/generator.go index b6a5f030..b39f2e39 100644 --- a/protoc-gen-twirp/generator.go +++ b/protoc-gen-twirp/generator.go @@ -775,36 +775,42 @@ func (t *twirp) generateJSONClient(file *descriptor.FileDescriptorProto, service structName := unexported(servName) + "JSONClient" newJSONClientFunc := "New" + servName + "JSONClient" + methCnt := strconv.Itoa(len(service.Method)) t.P(`type `, structName, ` struct {`) - t.P(` urlBase string`) t.P(` client HTTPClient`) + t.P(` urls [`, methCnt, `]string`) t.P(`}`) t.P() t.P(`// `, newJSONClientFunc, ` creates a JSON client that implements the `, servName, ` interface.`) t.P(`// It communicates using JSON requests and responses instead of protobuf messages.`) t.P(`func `, newJSONClientFunc, `(addr string, client HTTPClient) `, servName, ` {`) + t.P(` prefix := urlBase(addr) + `, pathPrefixConst) + t.P(` urls := [`, methCnt, `]string{`) + for _, method := range service.Method { + t.P(` prefix + "`, methodName(method), `",`) + } + t.P(` }`) t.P(` if httpClient, ok := client.(*`, t.pkgs["http"], `.Client); ok {`) t.P(` return &`, structName, `{`) - t.P(` urlBase: urlBase(addr),`) - t.P(` client: withoutRedirects(httpClient),`) + t.P(` client: withoutRedirects(httpClient),`) + t.P(` urls: urls,`) t.P(` }`) t.P(` }`) t.P(` return &`, structName, `{`) - t.P(` urlBase: urlBase(addr),`) - t.P(` client: client,`) + t.P(` client: client,`) + t.P(` urls: urls,`) t.P(` }`) t.P(`}`) t.P() - for _, method := range service.Method { + for i, method := range service.Method { methName := methodName(method) inputType := t.goTypeName(method.GetInputType()) outputType := t.goTypeName(method.GetOutputType()) t.P(`func (c *`, structName, `) `, methName, `(ctx `, t.pkgs["context"], `.Context, in *`, inputType, `) (*`, outputType, `, error) {`) - t.P(` url := c.urlBase + `, pathPrefixConst, ` + "`, methName, `"`) t.P(` out := new(`, outputType, `)`) - t.P(` err := doJSONRequest(ctx, c.client, url, in, out)`) + t.P(` err := doJSONRequest(ctx, c.client, c.urls[`, strconv.Itoa(i), `], in, out)`) t.P(` return out, err`) t.P(`}`) t.P() @@ -817,36 +823,42 @@ func (t *twirp) generateProtobufClient(file *descriptor.FileDescriptorProto, ser structName := unexported(servName) + "ProtobufClient" newProtobufClientFunc := "New" + servName + "ProtobufClient" + methCnt := strconv.Itoa(len(service.Method)) t.P(`type `, structName, ` struct {`) - t.P(` urlBase string`) t.P(` client HTTPClient`) + t.P(` urls [`, methCnt, `]string`) t.P(`}`) t.P() t.P(`// `, newProtobufClientFunc, ` creates a Protobuf client that implements the `, servName, ` interface.`) t.P(`// It communicates using protobuf messages and can be configured with a custom http.Client.`) t.P(`func `, newProtobufClientFunc, `(addr string, client HTTPClient) `, servName, ` {`) + t.P(` prefix := urlBase(addr) + `, pathPrefixConst) + t.P(` urls := [`, methCnt, `]string{`) + for _, method := range service.Method { + t.P(` prefix + "`, methodName(method), `",`) + } + t.P(` }`) t.P(` if httpClient, ok := client.(*`, t.pkgs["http"], `.Client); ok {`) t.P(` return &`, structName, `{`) - t.P(` urlBase: urlBase(addr),`) - t.P(` client: withoutRedirects(httpClient),`) + t.P(` client: withoutRedirects(httpClient),`) + t.P(` urls: urls,`) t.P(` }`) t.P(` }`) t.P(` return &`, structName, `{`) - t.P(` urlBase: urlBase(addr),`) - t.P(` client: client,`) + t.P(` client: client,`) + t.P(` urls: urls,`) t.P(` }`) t.P(`}`) t.P() - for _, method := range service.Method { + for i, method := range service.Method { methName := methodName(method) inputType := t.goTypeName(method.GetInputType()) outputType := t.goTypeName(method.GetOutputType()) t.P(`func (c *`, structName, `) `, methName, `(ctx `, t.pkgs["context"], `.Context, in *`, inputType, `) (*`, outputType, `, error) {`) - t.P(` url := c.urlBase + `, pathPrefixConst, ` + "`, methName, `"`) t.P(` out := new(`, outputType, `)`) - t.P(` err := doProtoRequest(ctx, c.client, url, in, out)`) + t.P(` err := doProtoRequest(ctx, c.client, c.urls[`, strconv.Itoa(i), `], in, out)`) t.P(` return out, err`) t.P(`}`) t.P()