-
Notifications
You must be signed in to change notification settings - Fork 662
Commit
* Remove uppercasing monitoring subjects * Remove error from RequestHandler signature
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,17 +22,19 @@ import ( | |
) | ||
|
||
type ( | ||
// Request represents service request available in the service handler. | ||
// It exposes methods to respond to the request, as well as | ||
// getting the request data and headers. | ||
Request struct { | ||
*nats.Msg | ||
msg *nats.Msg | ||
respondError error | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
derekcollison
Member
|
||
} | ||
|
||
// RequestHandler is a function used as a Handler for a service. | ||
// It takes a request, which contains the data (payload and headers) of the request, | ||
// as well as exposes methods to respond to the request. | ||
// | ||
// RequestHandler returns an error - if returned, the request will be accounted form in stats (in num_requests), | ||
// and last_error will be set with the value. | ||
RequestHandler func(*Request) error | ||
RequestHandler func(*Request) | ||
|
||
// Headers is a wrapper around [*nats.Header] | ||
Headers nats.Header | ||
) | ||
|
||
var ( | ||
|
@@ -41,27 +43,37 @@ var ( | |
ErrArgRequired = errors.New("argument required") | ||
) | ||
|
||
func (r *Request) Respond(response []byte) error { | ||
if err := r.Msg.Respond(response); err != nil { | ||
return fmt.Errorf("%w: %s", ErrRespond, err) | ||
// RespondOpt is a | ||
type RespondOpt func(*nats.Msg) | ||
|
||
func (r *Request) Respond(response []byte, opts ...RespondOpt) error { | ||
respMsg := &nats.Msg{ | ||
Data: response, | ||
} | ||
for _, opt := range opts { | ||
opt(respMsg) | ||
} | ||
|
||
if err := r.msg.RespondMsg(respMsg); err != nil { | ||
r.respondError = fmt.Errorf("%w: %s", ErrRespond, err) | ||
return r.respondError | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (r *Request) RespondJSON(response interface{}) error { | ||
func (r *Request) RespondJSON(response interface{}, opts ...RespondOpt) error { | ||
resp, err := json.Marshal(response) | ||
if err != nil { | ||
return ErrMarshalResponse | ||
} | ||
|
||
return r.Respond(resp) | ||
return r.Respond(resp, opts...) | ||
} | ||
|
||
// Error prepares and publishes error response from a handler. | ||
// A response error should be set containing an error code and description. | ||
// Optionally, data can be set as response payload. | ||
func (r *Request) Error(code, description string, data []byte) error { | ||
func (r *Request) Error(code, description string, data []byte, opts ...RespondOpt) error { | ||
if code == "" { | ||
return fmt.Errorf("%w: error code", ErrArgRequired) | ||
} | ||
|
@@ -74,6 +86,47 @@ func (r *Request) Error(code, description string, data []byte) error { | |
ErrorCodeHeader: []string{code}, | ||
}, | ||
} | ||
for _, opt := range opts { | ||
opt(response) | ||
} | ||
|
||
response.Data = data | ||
return r.RespondMsg(response) | ||
if err := r.msg.RespondMsg(response); err != nil { | ||
r.respondError = err | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func WithHeaders(headers Headers) RespondOpt { | ||
return func(m *nats.Msg) { | ||
if m.Header == nil { | ||
m.Header = nats.Header(headers) | ||
return | ||
} | ||
|
||
for k, v := range headers { | ||
m.Header[k] = v | ||
} | ||
} | ||
} | ||
|
||
func (r *Request) Data() []byte { | ||
return r.msg.Data | ||
} | ||
|
||
func (r *Request) Headers() Headers { | ||
return Headers(r.msg.Header) | ||
} | ||
|
||
// Get gets the first value associated with the given key. | ||
// It is case-sensitive. | ||
func (h Headers) Get(key string) string { | ||
return nats.Header(h).Get(key) | ||
} | ||
|
||
// Values returns all values associated with the given key. | ||
// It is case-sensitive. | ||
func (h Headers) Values(key string) []string { | ||
return nats.Header(h).Values(key) | ||
} |
This makes it quite impossible to write tests for handlers. The handler takes
*Request
, not an interface, and the Request struct has only unexported members meaning I cannot set values on the struct for testing.Request
also has no setters for the msg. I also cant find some creator like aNewRequest()
that could be used to setmsg
.So there is no way out of this package to prepare a Request to test a handler.
I suggest implementing some tests in the
test
package here so these usage problems are surfaced early