Skip to content

Commit

Permalink
Rename the XML encoded http.ErrorResponse (#3398)
Browse files Browse the repository at this point in the history
* Rename the XML encoded http.ErrorResponse

* Fix lint errors

---------

Co-authored-by: Raphael Simon <[email protected]>
  • Loading branch information
tchssk and raphael authored Oct 21, 2023
1 parent 61861f6 commit d3789bd
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
45 changes: 45 additions & 0 deletions http/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ package http
import (
"bytes"
"context"
"encoding/xml"
"errors"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"

goa "goa.design/goa/v3/pkg"
)

var (
Expand Down Expand Up @@ -104,6 +109,46 @@ func TestResponseEncoder(t *testing.T) {
}
}

func TestResponseEncoder_Encode_ErrorResponse(t *testing.T) {
var (
serviceError = goa.NewServiceError(errors.New("foo"), "foo", false, false, false)
defaultXMLName = ErrorResponseXMLName
backwardCompatibleXMLName = xml.Name{Local: "ErrorResponse"} // Compatible with v3.13.2 and earlier.
)

cases := []struct {
acceptType string
xmlName xml.Name
encoded string
}{
{"application/json", defaultXMLName, fmt.Sprintf(`{"name":"foo","id":"%s","message":"foo","temporary":false,"timeout":false,"fault":false}`, serviceError.ID)},
{"application/json", backwardCompatibleXMLName, fmt.Sprintf(`{"name":"foo","id":"%s","message":"foo","temporary":false,"timeout":false,"fault":false}`, serviceError.ID)},
{"application/xml", defaultXMLName, fmt.Sprintf(`<error><name>foo</name><id>%s</id><message>foo</message><temporary>false</temporary><timeout>false</timeout><fault>false</fault></error>`, serviceError.ID)},
{"application/xml", backwardCompatibleXMLName, fmt.Sprintf(`<ErrorResponse><name>foo</name><id>%s</id><message>foo</message><temporary>false</temporary><timeout>false</timeout><fault>false</fault></ErrorResponse>`, serviceError.ID)},
}

for _, c := range cases {
name := c.acceptType
if c.xmlName.Local != "" {
name += "/" + c.xmlName.Local
}
t.Run(name, func(t *testing.T) {
ctx := context.Background()
ctx = context.WithValue(ctx, AcceptTypeKey, c.acceptType)
w := httptest.NewRecorder()
ErrorResponseXMLName = c.xmlName
encoder := ResponseEncoder(ctx, w)
if err := encoder.Encode(NewErrorResponse(ctx, serviceError)); err != nil {
t.Error(err)
}
body := strings.TrimSpace(w.Body.String())
if body != c.encoded {
t.Errorf("got %s, expected %s", body, c.encoded)
}
})
}
}

func TestResponseDecoder(t *testing.T) {
cases := []struct {
contentType string
Expand Down
26 changes: 26 additions & 0 deletions http/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package http

import (
"context"
"encoding/xml"
"net/http"

goa "goa.design/goa/v3/pkg"
Expand Down Expand Up @@ -35,6 +36,11 @@ type (
}
)

var (
// ErrorResponseXMLName is the XML name used for ErrorResponse.
ErrorResponseXMLName = xml.Name{Local: "error"}
)

// NewErrorResponse creates a HTTP response from the given error.
func NewErrorResponse(ctx context.Context, err error) Statuser {
if gerr, ok := err.(*goa.ServiceError); ok {
Expand All @@ -50,6 +56,26 @@ func NewErrorResponse(ctx context.Context, err error) Statuser {
return NewErrorResponse(ctx, goa.Fault(err.Error()))
}

func (resp *ErrorResponse) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
return e.Encode(struct {
XMLName xml.Name
Name string `xml:"name"`
ID string `xml:"id"`
Message string `xml:"message"`
Temporary bool `xml:"temporary"`
Timeout bool `xml:"timeout"`
Fault bool `xml:"fault"`
}{
XMLName: ErrorResponseXMLName,
Name: resp.Name,
ID: resp.ID,
Message: resp.Message,
Temporary: resp.Temporary,
Timeout: resp.Timeout,
Fault: resp.Fault,
})
}

// StatusCode implements a heuristic that computes a HTTP response status code
// appropriate for the timeout, temporary and fault characteristics of the
// error. This method is used by the generated server code when the error is not
Expand Down

0 comments on commit d3789bd

Please sign in to comment.