Skip to content

Commit d9f4dc7

Browse files
authored
Write response headers with SkipEncodeDecodeResponseBody using a custom writer (#3578)
* Write response headers with SkipEncodeDecodeResponseBody using a custom writer * Address linting issues
1 parent 2cadf50 commit d9f4dc7

File tree

8 files changed

+29
-22
lines changed

8 files changed

+29
-22
lines changed

cmd/goa/gen.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type Generator struct {
4444
}
4545

4646
// NewGenerator creates a Generator.
47-
func NewGenerator(cmd string, path, output string) *Generator {
47+
func NewGenerator(cmd, path, output string) *Generator {
4848
bin := "goa"
4949
if runtime.GOOS == "windows" {
5050
bin += ".exe"
@@ -247,7 +247,7 @@ func (g *Generator) runGoCmd(args ...string) error {
247247
out, err := c.CombinedOutput()
248248
if err != nil {
249249
if len(out) > 0 {
250-
return fmt.Errorf(string(out))
250+
return fmt.Errorf("%s", out)
251251
}
252252
return fmt.Errorf("failed to compile generator: %w", err)
253253
}

expr/grpc_endpoint_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ service "Service" gRPC endpoint "Method": field number 2 in attribute "key_dup_i
4747
}
4848
for name, c := range cases {
4949
t.Run(name, func(t *testing.T) {
50-
if c.Errors == nil || len(c.Errors) == 0 {
50+
if len(c.Errors) == 0 {
5151
expr.RunDSL(t, c.DSL)
5252
} else {
5353
var errs []error

expr/http_response.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,10 @@ func (r *HTTPResponseExpr) Validate(e *HTTPEndpointExpr) *eval.ValidationErrors
139139
// an explicit conflict with the content-type and response.
140140
if (r.ContentType == "text/html" || r.ContentType == "text/plain") && !e.SkipRequestBodyEncodeDecode {
141141
if e.MethodExpr.Result.Type != nil && e.MethodExpr.Result.Type != String && e.MethodExpr.Result.Type != Bytes && r.Body == nil {
142-
verr.Add(r, fmt.Sprintf("Result type must be String or Bytes when ContentType is '%s'", r.ContentType))
142+
verr.Add(r, "Result type must be String or Bytes when ContentType is '%s'", r.ContentType)
143143
}
144144
if r.Body != nil && r.Body.Type != String && r.Body.Type != Bytes {
145-
verr.Add(r, fmt.Sprintf("Result type must be String or Bytes when ContentType is '%s'", r.ContentType))
145+
verr.Add(r, "Result type must be String or Bytes when ContentType is '%s'", r.ContentType)
146146
}
147147
}
148148

grpc/error.go

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func NewErrorResponse(err error) *goapb.ErrorResponse {
4949
Fault: gerr.Fault,
5050
}
5151
}
52-
return NewErrorResponse(goa.Fault(err.Error()))
52+
return NewErrorResponse(goa.Fault("%s", err.Error()))
5353
}
5454

5555
// NewServiceError returns a goa ServiceError type for the given ErrorResponse
@@ -92,18 +92,15 @@ func EncodeError(err error) error {
9292
if errors.As(err, &gerr) {
9393
// goa service error type. Compute the status code from the service error
9494
// characteristics and create a new detailed gRPC status error.
95-
var code codes.Code
96-
{
97-
code = codes.Unknown
98-
if gerr.Fault {
99-
code = codes.Internal
100-
}
101-
if gerr.Timeout {
102-
code = codes.DeadlineExceeded
103-
}
104-
if gerr.Temporary {
105-
code = codes.Unavailable
106-
}
95+
code := codes.Unknown
96+
if gerr.Fault {
97+
code = codes.Internal
98+
}
99+
if gerr.Timeout {
100+
code = codes.DeadlineExceeded
101+
}
102+
if gerr.Temporary {
103+
code = codes.Unavailable
107104
}
108105
return NewStatusError(code, err, NewErrorResponse(err))
109106
}

http/codegen/templates/server_handler_init.go.tpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ func {{ .HandlerInit }}(
8585
o := res.(*{{ .ServicePkgName }}.{{ .Method.ResponseStruct }})
8686
defer o.Body.Close()
8787
if wt, ok := o.Body.(io.WriterTo); ok {
88+
{{- if not (or .Redirect (isWebSocketEndpoint .)) }}
89+
if err := encodeResponse(ctx, w, {{ if and .Method.SkipResponseBodyEncodeDecode .Result.Ref }}o.Result{{ else }}res{{ end }}); err != nil {
90+
errhandler(ctx, w, err)
91+
return
92+
}
93+
{{- end }}
8894
n, err := wt.WriteTo(w)
8995
if err != nil {
9096
if n == 0 {

http/codegen/testdata/handler_init_functions.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ func NewMethodSkipResponseBodyEncodeDecodeHandler(
272272
o := res.(*serviceskipresponsebodyencodedecode.MethodSkipResponseBodyEncodeDecodeResponseData)
273273
defer o.Body.Close()
274274
if wt, ok := o.Body.(io.WriterTo); ok {
275+
if err := encodeResponse(ctx, w, res); err != nil {
276+
errhandler(ctx, w, err)
277+
return
278+
}
275279
n, err := wt.WriteTo(w)
276280
if err != nil {
277281
if n == 0 {

http/error.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func NewErrorResponse(ctx context.Context, err error) Statuser {
5555
Fault: gerr.Fault,
5656
}
5757
}
58-
return NewErrorResponse(ctx, goa.Fault(err.Error()))
58+
return NewErrorResponse(ctx, goa.Fault("%s", err.Error()))
5959
}
6060

6161
func (resp *ErrorResponse) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {

pkg/error.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func MissingPayloadError() error {
116116
// DecodePayloadError is the error produced by the generated code when a request
117117
// body cannot be decoded successfully.
118118
func DecodePayloadError(msg string) error {
119-
return PermanentError("decode_payload", msg)
119+
return PermanentError("decode_payload", "%s", msg)
120120
}
121121

122122
// UnsupportedMediaTypeError is the error produced by the Goa decoder when the
@@ -162,15 +162,15 @@ func InvalidFormatError(name, target string, format Format, formatError error) e
162162
// InvalidPatternError is the error produced by the generated code when the
163163
// value of a payload field does not match the pattern validation defined in the
164164
// design.
165-
func InvalidPatternError(name, target string, pattern string) error {
165+
func InvalidPatternError(name, target, pattern string) error {
166166
return withField(name, PermanentError(
167167
InvalidPattern, "%s must match the regexp %q but got value %q", name, pattern, target))
168168
}
169169

170170
// InvalidRangeError is the error produced by the generated code when the value
171171
// of a payload field does not match the range validation defined in the design.
172172
// value may be an int or a float64.
173-
func InvalidRangeError(name string, target any, value any, min bool) error {
173+
func InvalidRangeError(name string, target, value any, min bool) error {
174174
comp := "greater or equal"
175175
if !min {
176176
comp = "lesser or equal"

0 commit comments

Comments
 (0)