mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +00:00
not give error if hashes are prefixed with 0x (#277)
* ethersphere/go-ethereum#182: - added a case error struct that contains information about certain error cases in which we would like to output more information to the client - added a validation method that iterates and adds the information that is stored in the error cases * PR Requested changes * Merge conflicts * linting
This commit is contained in:
parent
19f0c2de7f
commit
5b8a06bfde
5 changed files with 87 additions and 9 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -34,6 +34,9 @@ profile.cov
|
||||||
# IdeaIDE
|
# IdeaIDE
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode
|
||||||
|
|
||||||
# dashboard
|
# dashboard
|
||||||
/dashboard/assets/flow-typed
|
/dashboard/assets/flow-typed
|
||||||
/dashboard/assets/node_modules
|
/dashboard/assets/node_modules
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import (
|
||||||
|
|
||||||
//templateMap holds a mapping of an HTTP error code to a template
|
//templateMap holds a mapping of an HTTP error code to a template
|
||||||
var templateMap map[int]*template.Template
|
var templateMap map[int]*template.Template
|
||||||
|
var caseErrors []CaseError
|
||||||
|
|
||||||
//metrics variables
|
//metrics variables
|
||||||
var (
|
var (
|
||||||
|
|
@ -51,6 +52,13 @@ type ResponseParams struct {
|
||||||
Details template.HTML
|
Details template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//a custom error case struct that would be used to store validators and
|
||||||
|
//additional error info to display with client responses.
|
||||||
|
type CaseError struct {
|
||||||
|
Validator func(*Request) bool
|
||||||
|
Msg func(*Request) string
|
||||||
|
}
|
||||||
|
|
||||||
//we init the error handling right on boot time, so lookup and http response is fast
|
//we init the error handling right on boot time, so lookup and http response is fast
|
||||||
func init() {
|
func init() {
|
||||||
initErrHandling()
|
initErrHandling()
|
||||||
|
|
@ -74,6 +82,29 @@ func initErrHandling() {
|
||||||
//assign formatted HTML to the code
|
//assign formatted HTML to the code
|
||||||
templateMap[code] = template.Must(template.New(fmt.Sprintf("%d", code)).Parse(tname))
|
templateMap[code] = template.Must(template.New(fmt.Sprintf("%d", code)).Parse(tname))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caseErrors = []CaseError{
|
||||||
|
{
|
||||||
|
Validator: func(r *Request) bool { return r.uri != nil && r.uri.Addr != "" && strings.HasPrefix(r.uri.Addr, "0x") },
|
||||||
|
Msg: func(r *Request) string {
|
||||||
|
uriCopy := r.uri
|
||||||
|
uriCopy.Addr = strings.TrimPrefix(uriCopy.Addr, "0x")
|
||||||
|
return fmt.Sprintf(`The requested hash seems to be prefixed with '0x'. You will be redirected to the correct URL within 5 seconds.<br/>
|
||||||
|
Please click <a href='%[1]s'>here</a> if your browser does not redirect you.<script>setTimeout("location.href='%[1]s';",5000);</script>`, "/"+uriCopy.String())
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ValidateCaseErrors is a method that process the request object through certain validators
|
||||||
|
//that assert if certain conditions are met for further information to log as an error
|
||||||
|
func ValidateCaseErrors(r *Request) string {
|
||||||
|
for _, err := range caseErrors {
|
||||||
|
if err.Validator(r) {
|
||||||
|
return err.Msg(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
//ShowMultipeChoices is used when a user requests a resource in a manifest which results
|
//ShowMultipeChoices is used when a user requests a resource in a manifest which results
|
||||||
|
|
@ -111,7 +142,9 @@ func ShowMultipleChoices(w http.ResponseWriter, req *Request, list api.ManifestL
|
||||||
//The function just takes a string message which will be displayed in the error page.
|
//The function just takes a string message which will be displayed in the error page.
|
||||||
//The code is used to evaluate which template will be displayed
|
//The code is used to evaluate which template will be displayed
|
||||||
//(and return the correct HTTP status code)
|
//(and return the correct HTTP status code)
|
||||||
|
|
||||||
func Respond(w http.ResponseWriter, req *Request, msg string, code int) {
|
func Respond(w http.ResponseWriter, req *Request, msg string, code int) {
|
||||||
|
additionalMessage := ValidateCaseErrors(req)
|
||||||
switch code {
|
switch code {
|
||||||
case http.StatusInternalServerError:
|
case http.StatusInternalServerError:
|
||||||
log.Output(msg, log.LvlError, 3, "ruid", req.ruid, "code", code)
|
log.Output(msg, log.LvlError, 3, "ruid", req.ruid, "code", code)
|
||||||
|
|
@ -122,6 +155,7 @@ func Respond(w http.ResponseWriter, req *Request, msg string, code int) {
|
||||||
respond(w, &req.Request, &ResponseParams{
|
respond(w, &req.Request, &ResponseParams{
|
||||||
Code: code,
|
Code: code,
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
|
Details: template.HTML(additionalMessage),
|
||||||
Timestamp: time.Now().Format(time.RFC1123),
|
Timestamp: time.Now().Format(time.RFC1123),
|
||||||
template: getTemplate(code),
|
template: getTemplate(code),
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,11 @@ func GetGenericErrorPage() string {
|
||||||
{{.Msg}}
|
{{.Msg}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="value">
|
||||||
|
{{.Details}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="key">
|
<td class="key">
|
||||||
|
|
@ -342,6 +347,12 @@ func GetNotFoundErrorPage() string {
|
||||||
{{.Msg}}
|
{{.Msg}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="value">
|
||||||
|
{{.Details}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="key">
|
<td class="key">
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,13 @@ package http_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"golang.org/x/net/html"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/swarm/testutil"
|
"github.com/ethereum/go-ethereum/swarm/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -96,8 +97,37 @@ func Test500Page(t *testing.T) {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
respbody, err = ioutil.ReadAll(resp.Body)
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
if resp.StatusCode != 500 || !strings.Contains(string(respbody), "500") {
|
if resp.StatusCode != 404 {
|
||||||
t.Fatalf("Invalid Status Code received, expected 500, got %d", resp.StatusCode)
|
t.Fatalf("Invalid Status Code received, expected 404, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = html.Parse(strings.NewReader(string(respbody)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("HTML validation failed for error page returned!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func Test500PageWith0xHashPrefix(t *testing.T) {
|
||||||
|
srv := testutil.NewTestSwarmServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
var respbody []byte
|
||||||
|
|
||||||
|
url := srv.URL + "/bzz:/0xthisShouldFailWith500CodeAndAHelpfulMessage"
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Request failed: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 404 {
|
||||||
|
t.Fatalf("Invalid Status Code received, expected 404, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(string(respbody), "The requested hash seems to be prefixed with") {
|
||||||
|
t.Fatalf("Did not receive the expected error message")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = html.Parse(strings.NewReader(string(respbody)))
|
_, err = html.Parse(strings.NewReader(string(respbody)))
|
||||||
|
|
@ -127,8 +157,8 @@ func TestJsonResponse(t *testing.T) {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
respbody, err = ioutil.ReadAll(resp.Body)
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
if resp.StatusCode != 500 {
|
if resp.StatusCode != 404 {
|
||||||
t.Fatalf("Invalid Status Code received, expected 500, got %d", resp.StatusCode)
|
t.Fatalf("Invalid Status Code received, expected 404, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isJSON(string(respbody)) {
|
if !isJSON(string(respbody)) {
|
||||||
|
|
|
||||||
|
|
@ -474,7 +474,7 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getFail.Inc(1)
|
getFail.Inc(1)
|
||||||
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
|
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,7 +558,7 @@ func (s *Server) HandleGetFiles(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getFilesFail.Inc(1)
|
getFilesFail.Inc(1)
|
||||||
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
|
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -631,7 +631,7 @@ func (s *Server) HandleGetList(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getListFail.Inc(1)
|
getListFail.Inc(1)
|
||||||
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
|
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -735,7 +735,7 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getFileFail.Inc(1)
|
getFileFail.Inc(1)
|
||||||
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
|
Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue