From 767078168a50c656a4f33c6ca42cb71e5a2e4660 Mon Sep 17 00:00:00 2001 From: John Beisley Date: Sat, 26 Mar 2022 18:17:39 +0000 Subject: [PATCH] Clean up SOAP client API. --- v2alpha/soap/client/client.go | 42 ++++++++++++++++++++++-------- v2alpha/soap/client/client_test.go | 4 +-- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/v2alpha/soap/client/client.go b/v2alpha/soap/client/client.go index 8d4ea22..5f0be74 100644 --- a/v2alpha/soap/client/client.go +++ b/v2alpha/soap/client/client.go @@ -55,18 +55,32 @@ func New(endpointURL string, opts ...Option) *Client { } } -// PerformAction makes a SOAP request, with the given action values to provide -// arguments (`args`) and capture the `reply` into. If `client` is nil, then -// http.DefaultClient is used. +// PerformAction makes a SOAP request, with the given `argsIn` as input +// arguments, and `argsOut` to capture the output arguments into. +// `serviceType` is the SOAP service type URN, `actionName` is the action to +// call. +// +// This is a convenience for calling `c.Do` without creating `*Action` values. func (c *Client) PerformAction( + ctx context.Context, serviceType, actionName string, + argsIn, argsOut any, +) error { + actionIn := envelope.NewSendAction(serviceType, actionName, argsIn) + actionOut := &envelope.Action{Args: argsOut} + return c.Do(ctx, actionIn, actionOut) +} + +// PerformAction makes a SOAP request, with the given action values to provide +// arguments (`args`) and capture the `reply` into. +func (c *Client) Do( ctx context.Context, - args, reply *envelope.Action, + actionIn, actionOut *envelope.Action, ) error { req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpointURL, nil) if err != nil { return err } - if err := SetRequestAction(req, args); err != nil { + if err := SetRequestAction(req, actionIn); err != nil { return err } @@ -81,15 +95,18 @@ func (c *Client) PerformAction( resp.Status, resp.StatusCode) } - return ParseResponseAction(resp, reply) + return ParseResponseAction(resp, actionOut) } // SetRequestAction updates fields in `req` with the given SOAP action. // Specifically it sets Body, ContentLength, Method, and the SOAPACTION and // CONTENT-TYPE headers. -func SetRequestAction(req *http.Request, args *envelope.Action) error { +func SetRequestAction( + req *http.Request, + actionIn *envelope.Action, +) error { buf := &bytes.Buffer{} - err := envelope.Write(buf, args) + err := envelope.Write(buf, actionIn) if err != nil { return fmt.Errorf("encoding envelope: %w", err) } @@ -98,7 +115,7 @@ func SetRequestAction(req *http.Request, args *envelope.Action) error { req.ContentLength = int64(buf.Len()) req.Method = http.MethodPost req.Header["SOAPACTION"] = []string{fmt.Sprintf( - `"%s#%s"`, args.XMLName.Space, args.XMLName.Local)} + `"%s#%s"`, actionIn.XMLName.Space, actionIn.XMLName.Local)} req.Header["CONTENT-TYPE"] = []string{`text/xml; charset="utf-8"`} return nil @@ -107,7 +124,10 @@ func SetRequestAction(req *http.Request, args *envelope.Action) error { // ParseResponse extracts a parsed action from an HTTP response. // The caller is responsible for calling resp.Body.Close(), but this function // will consume the entire response body. -func ParseResponseAction(resp *http.Response, reply *envelope.Action) error { +func ParseResponseAction( + resp *http.Response, + actionOut *envelope.Action, +) error { if resp.Body == nil { return errors.New("missing response body") } @@ -117,7 +137,7 @@ func ParseResponseAction(resp *http.Response, reply *envelope.Action) error { return fmt.Errorf("reading response body: %w", err) } - if err := envelope.Read(buf, reply); err != nil { + if err := envelope.Read(buf, actionOut); err != nil { if _, ok := err.(*envelope.Fault); ok { // Parsed cleanly, got SOAP fault. return err diff --git a/v2alpha/soap/client/client_test.go b/v2alpha/soap/client/client_test.go index 69a0a2b..1810c80 100644 --- a/v2alpha/soap/client/client_test.go +++ b/v2alpha/soap/client/client_test.go @@ -76,7 +76,7 @@ func (fss *fakeSoapServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } -func TestPerformAction(t *testing.T) { +func TestDo(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) t.Cleanup(cancel) @@ -101,7 +101,7 @@ func TestPerformAction(t *testing.T) { reply := &ActionReply{} replyAction := &envelope.Action{Args: reply} - if err := c.PerformAction(ctx, reqAction, replyAction); err != nil { + if err := c.Do(ctx, reqAction, replyAction); err != nil { t.Errorf("got error: %v, want success", err) } else { if got, want := reply.Greeting, "Hello, World!"; got != want {