Skip to content

Commit

Permalink
[TT-1681] Add default XML template (TykTechnologies#3510)
Browse files Browse the repository at this point in the history
## Description
https://tyktech.atlassian.net/browse/TT-1681


## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality)

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes that apply -->
<!-- If you're unsure about any of these, don't hesitate to ask; we're here to help! -->
- [ ] Make sure you are requesting to **pull a topic/feature/bugfix branch** (right side). If pulling from your own
      fork, don't request your `master`!
- [ ] Make sure you are making a pull request against the **`master` branch** (left side). Also, you should start
      *your branch* off *our latest `master`*.
- [ ] My change requires a change to the documentation.
  - [ ] If you've changed APIs, describe what needs to be updated in the documentation.
  - [ ] If new config option added, ensure that it can be set via ENV variable
- [ ] I have updated the documentation accordingly.
- [ ] Modules and vendor dependencies have been updated; run `go mod tidy && go mod vendor`
- [ ] When updating library version must provide reason/explanation for this update.
- [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed.
- [ ] Check your code additions will not fail linting checks:
  - [ ] `go fmt -s`
  - [ ] `go vet`
  • Loading branch information
buger authored Mar 31, 2021
1 parent d2f9f9a commit 086ab64
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 4 deletions.
19 changes: 17 additions & 2 deletions gateway/handler_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ type ErrorHandler struct {
BaseMiddleware
}

// TemplateExecutor is an interface used to switch between text/templates and html/template.
// It only switch to text/template (templatesRaw) when contentType is XML related
type TemplateExecutor interface {
Execute(wr io.Writer, data interface{}) error
}

// HandleError is the actual error handler and will store the error details in analytics if analytics processing is enabled.
func (e *ErrorHandler) HandleError(w http.ResponseWriter, r *http.Request, errMsg string, errCode int, writeResponse bool) {
defer e.Base().UpdateRequestSession(r)
Expand All @@ -120,7 +126,6 @@ func (e *ErrorHandler) HandleError(w http.ResponseWriter, r *http.Request, errMs
w.Header().Set(headers.ContentType, contentType)
response.Header = http.Header{}
response.Header.Set(headers.ContentType, contentType)

templateName := "error_" + strconv.Itoa(errCode) + "." + templateExtension

// Try to use an error template that matches the HTTP error code and the content type: 500.json, 400.xml, etc.
Expand Down Expand Up @@ -158,12 +163,22 @@ func (e *ErrorHandler) HandleError(w http.ResponseWriter, r *http.Request, errMs
if errMsg != errCustomBodyResponse.Error() {
w.WriteHeader(errCode)
response.StatusCode = errCode
var tmplExecutor TemplateExecutor
tmplExecutor = tmpl

apiError := APIError{template.HTML(template.JSEscapeString(errMsg))}
if contentType == headers.ApplicationXML || contentType == headers.TextXML {
apiError.Message = template.HTML(errMsg)

//we look up in the last defined templateName to obtain the template.
rawTmpl := templatesRaw.Lookup(templateName)
tmplExecutor = rawTmpl
}

var log bytes.Buffer

rsp := io.MultiWriter(w, &log)
tmpl.Execute(rsp, &apiError)
tmplExecutor.Execute(rsp, &apiError)
response.Body = ioutil.NopCloser(&log)
}
}
Expand Down
67 changes: 65 additions & 2 deletions gateway/handler_error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (

func TestHandleError_text_xml(t *testing.T) {
file := filepath.Join(config.Global().TemplatePath, "error_500.xml")
xml := `<error>
xml := `<?xml version = "1.0" encoding = "UTF-8"?>
<error>
<code>500</code>
<message>{{.Message}}</message>
</error>`
Expand All @@ -25,7 +26,7 @@ func TestHandleError_text_xml(t *testing.T) {
t.Fatal(err)
}
defer os.Remove(file)
expect := `
expect := `<?xml version = "1.0" encoding = "UTF-8"?>
<error>
<code>500</code>
<message>There was a problem proxying the request</message>
Expand Down Expand Up @@ -59,3 +60,65 @@ func TestHandleError_text_xml(t *testing.T) {
},
})
}

func TestHandleDefaultErrorXml(t *testing.T) {

expect := `<?xml version = "1.0" encoding = "UTF-8"?>
<error>There was a problem proxying the request</error>`
ts := StartTest()
defer ts.Close()

BuildAndLoadAPI(func(spec *APISpec) {
spec.Proxy.ListenPath = "/"
spec.Proxy.TargetURL = "http://localhost:66666"
})
ts.Run(t, test.TestCase{
Path: "/",
Code: http.StatusInternalServerError,
Headers: map[string]string{
headers.ContentType: headers.TextXML,
},
BodyMatchFunc: func(b []byte) bool {
return strings.TrimSpace(expect) == string(bytes.TrimSpace(b))
},
})

ts.Run(t, test.TestCase{
Path: "/",
Code: http.StatusInternalServerError,
Headers: map[string]string{
headers.ContentType: headers.TextXML + "; charset=UTF-8",
},
BodyMatchFunc: func(b []byte) bool {
return strings.TrimSpace(expect) == string(bytes.TrimSpace(b))
},
})
}

func TestHandleDefaultErrorJSON(t *testing.T) {

expect := `
{
"error": "There was a problem proxying the request"
}
`

ts := StartTest()
defer ts.Close()

BuildAndLoadAPI(func(spec *APISpec) {
spec.Proxy.ListenPath = "/"
spec.Proxy.TargetURL = "http://localhost:66666"
})
ts.Run(t, test.TestCase{
Path: "/",
Code: http.StatusInternalServerError,
Headers: map[string]string{
headers.ContentType: headers.ApplicationJSON,
},
BodyMatchFunc: func(b []byte) bool {
return strings.TrimSpace(expect) == string(bytes.TrimSpace(b))
},
})

}
3 changes: 3 additions & 0 deletions gateway/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"strconv"
"strings"
"sync"
textTemplate "text/template"
"time"

"github.com/TykTechnologies/again"
Expand Down Expand Up @@ -56,6 +57,7 @@ var (
pubSubLog = log.WithField("prefix", "pub-sub")
rawLog = logger.GetRaw()
templates *template.Template
templatesRaw *textTemplate.Template
analytics RedisAnalyticsHandler
GlobalEventsJSVM JSVM
memProfFile *os.File
Expand Down Expand Up @@ -224,6 +226,7 @@ func setupGlobals(ctx context.Context) {
// Load all the files that have the "error" prefix.
templatesDir := filepath.Join(config.Global().TemplatePath, "error*")
templates = template.Must(template.ParseGlob(templatesDir))
templatesRaw = textTemplate.Must(textTemplate.ParseGlob(templatesDir))

CoProcessInit()

Expand Down
2 changes: 2 additions & 0 deletions templates/error.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version = "1.0" encoding = "UTF-8"?>
<error>{{.Message}}</error>

0 comments on commit 086ab64

Please sign in to comment.