Commit ebf9ba23 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'jv-friendly-error-page' into 'master'

Add friendly development error page for 502

See merge request gitlab-org/gitlab-workhorse!453
parents 6425eb4d a53f27c6
......@@ -3,8 +3,10 @@ package badgateway
import (
"bytes"
"fmt"
"html/template"
"io/ioutil"
"net/http"
"strings"
"time"
"gitlab.com/gitlab-org/labkit/log"
......@@ -46,11 +48,6 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
fields,
)
message := "GitLab is not responding"
if t.developmentMode {
message = err.Error()
}
injectedResponse := &http.Response{
StatusCode: http.StatusBadGateway,
Status: http.StatusText(http.StatusBadGateway),
......@@ -61,9 +58,58 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
Proto: r.Proto,
Header: make(http.Header),
Trailer: make(http.Header),
Body: ioutil.NopCloser(bytes.NewBufferString(message)),
}
injectedResponse.Header.Set("Content-Type", "text/plain")
message := "GitLab is not responding"
contentType := "text/plain"
if t.developmentMode {
message, contentType = developmentModeResponse(err)
}
injectedResponse.Body = ioutil.NopCloser(strings.NewReader(message))
injectedResponse.Header.Set("Content-Type", contentType)
return injectedResponse, nil
}
func developmentModeResponse(err error) (body string, contentType string) {
data := TemplateData{
Time: time.Now().Format("15:04:05"),
Error: err.Error(),
ReloadSeconds: 5,
}
buf := &bytes.Buffer{}
if err := developmentErrorTemplate.Execute(buf, data); err != nil {
return data.Error, "text/plain"
}
return buf.String(), "text/html"
}
type TemplateData struct {
Time string
Error string
ReloadSeconds int
}
var developmentErrorTemplate = template.Must(template.New("error502").Parse(`
<html>
<head>
<title>502: GitLab is not responding</title>
<script>
window.setTimeout(function() { location.reload() }, {{.ReloadSeconds}} * 1000)
</script>
</head>
<body>
<h1>502</h1>
<p>GitLab is not responding. The error was:</p>
<pre>{{.Error}}</pre>
<p>If you just started GDK it can take 30-60 seconds before GitLab has finished booting. This page will automatically reload every {{.ReloadSeconds}} seconds.</p>
<footer>Generated by gitlab-workhorse running in development mode at {{.Time}}.</footer>
</body>
</html>
`))
package badgateway
import (
"errors"
"io/ioutil"
"net/http"
"testing"
"github.com/stretchr/testify/require"
)
type roundtrip502 struct{}
func (roundtrip502) RoundTrip(*http.Request) (*http.Response, error) {
return nil, errors.New("something went wrong")
}
func TestErrorPage502(t *testing.T) {
tests := []struct {
name string
devMode bool
contentType string
responseSnippet string
}{
{
name: "production mode",
contentType: "text/plain",
responseSnippet: "GitLab is not responding",
},
{
name: "development mode",
devMode: true,
contentType: "text/html",
responseSnippet: "This page will automatically reload",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
req, err := http.NewRequest("GET", "/", nil)
require.NoError(t, err, "build request")
rt := NewRoundTripper(tc.devMode, roundtrip502{})
response, err := rt.RoundTrip(req)
require.NoError(t, err, "perform roundtrip")
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.Equal(t, tc.contentType, response.Header.Get("content-type"), "content type")
require.Equal(t, 502, response.StatusCode, "response status")
require.Contains(t, string(body), tc.responseSnippet)
})
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment