|
3 | 3 | package revproxy |
4 | 4 |
|
5 | 5 | import ( |
| 6 | + "errors" |
6 | 7 | "fmt" |
| 8 | + "net/http" |
7 | 9 | "path" |
| 10 | + "strings" |
8 | 11 |
|
9 | 12 | "github.com/SwissDataScienceCenter/renku-gateway/internal/config" |
10 | 13 | "github.com/SwissDataScienceCenter/renku-gateway/internal/models" |
@@ -151,3 +154,56 @@ func NewServer(options ...RevproxyOption) (*Revproxy, error) { |
151 | 154 | } |
152 | 155 | return &server, nil |
153 | 156 | } |
| 157 | + |
| 158 | +// The same error content as the data services API |
| 159 | +const gwBaseErrorCode int = 6000 |
| 160 | + |
| 161 | +type errorContent struct { |
| 162 | + Code int `json:"code"` |
| 163 | + Message string `json:"message"` |
| 164 | + Detail string `json:"detail,omitempty"` |
| 165 | + TraceId string `json:"trace_id,omitempty"` |
| 166 | +} |
| 167 | + |
| 168 | +type errorResponse struct { |
| 169 | + Error errorContent `json:"error"` |
| 170 | +} |
| 171 | + |
| 172 | +// Adapted from https://echo.labstack.com/docs/error-handling |
| 173 | +func ErrorHandler(err error, c echo.Context) { |
| 174 | + if c.Response() != nil && c.Response().Committed { |
| 175 | + return // response has been already sent to the client by handler or some middleware |
| 176 | + } |
| 177 | + |
| 178 | + accept := c.Request().Header.Get("Accept") |
| 179 | + isHTML := strings.Contains(accept, echo.MIMETextHTML) |
| 180 | + |
| 181 | + // If the accept header is html then we fall back to the default handler (for now). |
| 182 | + // If the acceptt header is not html or is blank we return json |
| 183 | + if isHTML { |
| 184 | + c.Echo().DefaultHTTPErrorHandler(err, c) |
| 185 | + return |
| 186 | + } |
| 187 | + |
| 188 | + code := http.StatusInternalServerError |
| 189 | + message := err.Error() |
| 190 | + var he *echo.HTTPError |
| 191 | + if errors.As(err, &he) { // find error in an error chain that implements HTTPError |
| 192 | + if tmp := he.Code; tmp != 0 { |
| 193 | + code = tmp |
| 194 | + } |
| 195 | + if msg := fmt.Sprintf("%v", he.Message); len(msg) > 0 { |
| 196 | + message = msg |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | + var cErr error |
| 201 | + if c.Request().Method == http.MethodHead { |
| 202 | + cErr = c.NoContent(code) |
| 203 | + } else { |
| 204 | + cErr = c.JSON(code, errorResponse{Error: errorContent{Code: gwBaseErrorCode + code, Message: message}}) |
| 205 | + } |
| 206 | + if cErr != nil { |
| 207 | + c.Logger().Error("failed to send error page to client", "error", errors.Join(err, cErr)) |
| 208 | + } |
| 209 | +} |
0 commit comments