swarm/api/http: refactor ShowError and logging of HTTP requests

This commit is contained in:
Anton Evangelatov 2018-02-21 11:34:23 +01:00
parent a375d95143
commit a366b1a3df
3 changed files with 78 additions and 76 deletions

View file

@ -36,7 +36,7 @@ import (
var templateMap map[int]*template.Template var templateMap map[int]*template.Template
//parameters needed for formatting the correct HTML page //parameters needed for formatting the correct HTML page
type ErrorParams struct { type ResponseParams struct {
Msg string Msg string
Code int Code int
Timestamp string Timestamp string
@ -75,45 +75,44 @@ func initErrHandling() {
//For example, if the user requests bzz:/<hash>/read and that manifest contains entries //For example, if the user requests bzz:/<hash>/read and that manifest contains entries
//"readme.md" and "readinglist.txt", a HTML page is returned with this two links. //"readme.md" and "readinglist.txt", a HTML page is returned with this two links.
//This only applies if the manifest has no default entry //This only applies if the manifest has no default entry
func ShowMultipleChoices(w http.ResponseWriter, r *http.Request, list api.ManifestList) { func ShowMultipleChoices(w http.ResponseWriter, req *Request, list api.ManifestList) {
msg := "" msg := ""
if list.Entries == nil { if list.Entries == nil {
ShowError(w, r, "Internal Server Error", http.StatusInternalServerError) Respond(w, req, "Internal Server Error", http.StatusInternalServerError)
return return
} }
//make links relative //make links relative
//requestURI comes with the prefix of the ambiguous path, e.g. "read" for "readme.md" and "readinglist.txt" //requestURI comes with the prefix of the ambiguous path, e.g. "read" for "readme.md" and "readinglist.txt"
//to get clickable links, need to remove the ambiguous path, i.e. "read" //to get clickable links, need to remove the ambiguous path, i.e. "read"
idx := strings.LastIndex(r.RequestURI, "/") idx := strings.LastIndex(req.RequestURI, "/")
if idx == -1 { if idx == -1 {
ShowError(w, r, "Internal Server Error", http.StatusInternalServerError) Respond(w, req, "Internal Server Error", http.StatusInternalServerError)
return return
} }
//remove ambiguous part //remove ambiguous part
base := r.RequestURI[:idx+1] base := req.RequestURI[:idx+1]
for _, e := range list.Entries { for _, e := range list.Entries {
//create clickable link for each entry //create clickable link for each entry
msg += "<a href='" + base + e.Path + "'>" + e.Path + "</a><br/>" msg += "<a href='" + base + e.Path + "'>" + e.Path + "</a><br/>"
} }
respond(w, r, &ErrorParams{
Code: http.StatusMultipleChoices, Respond(w, req, msg, http.StatusMultipleChoices)
Details: template.HTML(msg),
Timestamp: time.Now().Format(time.RFC1123),
template: getTemplate(http.StatusMultipleChoices),
})
} }
//ShowError is used to show an HTML error page to a client. //Respond is used to show an HTML page to a client.
//If there is an `Accept` header of `application/json`, JSON will be returned instead //If there is an `Accept` header of `application/json`, JSON will be returned instead
//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 ShowError(w http.ResponseWriter, r *http.Request, msg string, code int) { func Respond(w http.ResponseWriter, req *Request, msg string, code int) {
if code == http.StatusInternalServerError { switch code {
//log.Error(msg) case http.StatusInternalServerError:
log.Output(msg, log.LvlError, 3) log.Output(msg, log.LvlError, 3, "ruid", req.ruid, "code", code)
default:
log.Output(msg, log.LvlDebug, 3, "ruid", req.ruid, "code", code)
} }
respond(w, r, &ErrorParams{
respond(w, &req.Request, &ResponseParams{
Code: code, Code: code,
Msg: msg, Msg: msg,
Timestamp: time.Now().Format(time.RFC1123), Timestamp: time.Now().Format(time.RFC1123),
@ -122,7 +121,7 @@ func ShowError(w http.ResponseWriter, r *http.Request, msg string, code int) {
} }
//evaluate if client accepts html or json response //evaluate if client accepts html or json response
func respond(w http.ResponseWriter, r *http.Request, params *ErrorParams) { func respond(w http.ResponseWriter, r *http.Request, params *ResponseParams) {
w.WriteHeader(params.Code) w.WriteHeader(params.Code)
if r.Header.Get("Accept") == "application/json" { if r.Header.Get("Accept") == "application/json" {
respondJson(w, params) respondJson(w, params)
@ -132,7 +131,7 @@ func respond(w http.ResponseWriter, r *http.Request, params *ErrorParams) {
} }
//return a HTML page //return a HTML page
func respondHtml(w http.ResponseWriter, params *ErrorParams) { func respondHtml(w http.ResponseWriter, params *ResponseParams) {
err := params.template.Execute(w, params) err := params.template.Execute(w, params)
if err != nil { if err != nil {
log.Error(err.Error()) log.Error(err.Error())
@ -140,7 +139,7 @@ func respondHtml(w http.ResponseWriter, params *ErrorParams) {
} }
//return JSON //return JSON
func respondJson(w http.ResponseWriter, params *ErrorParams) { func respondJson(w http.ResponseWriter, params *ResponseParams) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(params) json.NewEncoder(w).Encode(params)
} }

View file

@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/swarm/api" "github.com/ethereum/go-ethereum/swarm/api"
"github.com/ethereum/go-ethereum/swarm/storage" "github.com/ethereum/go-ethereum/swarm/storage"
"github.com/pborman/uuid"
"github.com/rs/cors" "github.com/rs/cors"
) )
@ -91,27 +92,28 @@ type Request struct {
http.Request http.Request
uri *api.URI uri *api.URI
ruid string // request unique id
} }
// HandlePostRaw handles a POST request to a raw bzz-raw:/ URI, stores the request // HandlePostRaw handles a POST request to a raw bzz-raw:/ URI, stores the request
// body in swarm and returns the resulting storage key as a text/plain response // body in swarm and returns the resulting storage key as a text/plain response
func (s *Server) HandlePostRaw(w http.ResponseWriter, r *Request) { func (s *Server) HandlePostRaw(w http.ResponseWriter, r *Request) {
if r.uri.Path != "" { if r.uri.Path != "" {
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, "raw POST request cannot contain a path"), http.StatusBadRequest) Respond(w, r, "raw POST request cannot contain a path", http.StatusBadRequest)
return return
} }
if r.Header.Get("Content-Length") == "" { if r.Header.Get("Content-Length") == "" {
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, "missing Content-Length header in request"), http.StatusBadRequest) Respond(w, r, "missing Content-Length header in request", http.StatusBadRequest)
return return
} }
key, _, err := s.api.Store(r.Body, r.ContentLength) key, _, err := s.api.Store(r.Body, r.ContentLength)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
log.Debug(fmt.Sprintf("content for %s stored", key.Log())) log.Debug(fmt.Sprintf("content for %s stored", key.Log()), "ruid", r.ruid)
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
@ -126,7 +128,7 @@ func (s *Server) HandlePostRaw(w http.ResponseWriter, r *Request) {
func (s *Server) HandlePostFiles(w http.ResponseWriter, r *Request) { func (s *Server) HandlePostFiles(w http.ResponseWriter, r *Request) {
contentType, params, err := mime.ParseMediaType(r.Header.Get("Content-Type")) contentType, params, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, err), http.StatusBadRequest) Respond(w, r, err.Error(), http.StatusBadRequest)
return return
} }
@ -134,13 +136,13 @@ func (s *Server) HandlePostFiles(w http.ResponseWriter, r *Request) {
if r.uri.Addr != "" { if r.uri.Addr != "" {
key, err = s.api.Resolve(r.uri) key, err = s.api.Resolve(r.uri)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
return return
} }
} else { } else {
key, err = s.api.NewManifest() key, err = s.api.NewManifest()
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
} }
@ -159,7 +161,7 @@ func (s *Server) HandlePostFiles(w http.ResponseWriter, r *Request) {
} }
}) })
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error creating manifest: %s", err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot create manifest: %s", err), http.StatusInternalServerError)
return return
} }
@ -279,16 +281,16 @@ func (s *Server) handleDirectUpload(req *Request, mw *api.ManifestWriter) error
func (s *Server) HandleDelete(w http.ResponseWriter, r *Request) { func (s *Server) HandleDelete(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 {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
return return
} }
newKey, err := s.updateManifest(key, func(mw *api.ManifestWriter) error { newKey, err := s.updateManifest(key, func(mw *api.ManifestWriter) error {
log.Debug(fmt.Sprintf("removing %s from manifest %s", r.uri.Path, key.Log())) log.Debug(fmt.Sprintf("removing %s from manifest %s", r.uri.Path, key.Log()), "ruid", r.ruid)
return mw.RemoveEntry(r.uri.Path) return mw.RemoveEntry(r.uri.Path)
}) })
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error updating manifest: %s", err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot update manifest: %s", err), http.StatusInternalServerError)
return return
} }
@ -302,19 +304,19 @@ func (s *Server) HandlePostResource(w http.ResponseWriter, r *Request) {
if r.uri.Path != "" { if r.uri.Path != "" {
frequency, err := strconv.ParseUint(r.uri.Path, 10, 64) frequency, err := strconv.ParseUint(r.uri.Path, 10, 64)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, fmt.Sprintf("Cannot parse frequency parameter: %v", err)), http.StatusBadRequest) Respond(w, r, fmt.Sprintf("cannot parse frequency parameter: %v", err), http.StatusBadRequest)
return return
} }
key, err := s.api.ResourceCreate(r.Context(), r.uri.Addr, frequency) key, err := s.api.ResourceCreate(r.Context(), r.uri.Addr, frequency)
if err != nil { if err != nil {
code, err2 := s.translateResourceError(w, r, "Resource creation fail", err) code, err2 := s.translateResourceError(w, r, "resource creation fail", err)
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err2), code) Respond(w, r, err2.Error(), code)
return return
} }
m, err := s.api.NewResourceManifest(r.uri.Addr) m, err := s.api.NewResourceManifest(r.uri.Addr)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("Failed to create resource manifest: %v", err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("failed to create resource manifest: %v", err), http.StatusInternalServerError)
return return
} }
rsrcResponse := &resourceResponse{ rsrcResponse := &resourceResponse{
@ -324,21 +326,21 @@ func (s *Server) HandlePostResource(w http.ResponseWriter, r *Request) {
} }
outdata, err = json.Marshal(rsrcResponse) outdata, err = json.Marshal(rsrcResponse)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("Failed to create json response for %v: error was: %v", r, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("failed to create json response: %s", err), http.StatusInternalServerError)
return return
} }
} }
data, err := ioutil.ReadAll(r.Body) data, err := ioutil.ReadAll(r.Body)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
_, _, _, err = s.api.ResourceUpdate(r.Context(), r.uri.Addr, data) _, _, _, err = s.api.ResourceUpdate(r.Context(), r.uri.Addr, data)
if err != nil { if err != nil {
code, err2 := s.translateResourceError(w, r, "Mutable resource update fail", err) code, err2 := s.translateResourceError(w, r, "mutable resource update fail", err)
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err2), code) Respond(w, r, err2.Error(), code)
return return
} }
@ -371,7 +373,7 @@ func (s *Server) handleGetResource(w http.ResponseWriter, r *Request, name strin
var data []byte var data []byte
var err error var err error
now := time.Now() now := time.Now()
log.Debug("handlegetdb", "name", name) log.Debug("handlegetdb", "name", name, "ruid", r.ruid)
switch len(params) { switch len(params) {
case 0: case 0:
updateKey, data, err = s.api.ResourceLookup(r.Context(), name, 0, 0) updateKey, data, err = s.api.ResourceLookup(r.Context(), name, 0, 0)
@ -392,16 +394,16 @@ func (s *Server) handleGetResource(w http.ResponseWriter, r *Request, name strin
} }
updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version)) updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version))
default: default:
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, "Invalid mutable resource request"), http.StatusBadRequest) Respond(w, r, "invalid mutable resource request", http.StatusBadRequest)
return return
} }
if err != nil { if err != nil {
code, err2 := s.translateResourceError(w, r, "Mutable resource lookup fail", err) code, err2 := s.translateResourceError(w, r, "mutable resource lookup fail", err)
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err2), code) Respond(w, r, err2.Error(), code)
return return
} }
log.Debug("Found update", "key", updateKey) log.Debug("Found update", "key", updateKey, "ruid", r.ruid)
w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Type", "application/octet-stream")
http.ServeContent(w, &r.Request, "", now, bytes.NewReader(data)) http.ServeContent(w, &r.Request, "", now, bytes.NewReader(data))
} }
@ -435,7 +437,7 @@ func (s *Server) translateResourceError(w http.ResponseWriter, r *Request, supEr
func (s *Server) HandleGet(w http.ResponseWriter, r *Request) { 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 {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
return return
} }
@ -444,7 +446,7 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
if r.uri.Path != "" { if r.uri.Path != "" {
walker, err := s.api.NewManifestWalker(key, nil) walker, err := s.api.NewManifestWalker(key, nil)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, fmt.Sprintf("%s is not a manifest", key)), http.StatusBadRequest) Respond(w, r, fmt.Sprintf("%s is not a manifest", key), http.StatusBadRequest)
return return
} }
var entry *api.ManifestEntry var entry *api.ManifestEntry
@ -472,7 +474,7 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
return api.SkipManifest return api.SkipManifest
}) })
if entry == nil { if entry == nil {
ShowError(w, &r.Request, fmt.Sprintf("NOT FOUND error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("Manifest entry could not be loaded")), http.StatusNotFound) Respond(w, r, fmt.Sprintf("manifest entry could not be loaded"), http.StatusNotFound)
return return
} }
key = storage.Key(common.Hex2Bytes(entry.Hash)) key = storage.Key(common.Hex2Bytes(entry.Hash))
@ -481,7 +483,7 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
// check the root chunk exists by retrieving the file's size // check the root chunk exists by retrieving the file's size
reader := s.api.Retrieve(key) reader := s.api.Retrieve(key)
if _, err := reader.Size(nil); err != nil { if _, err := reader.Size(nil); err != nil {
ShowError(w, &r.Request, fmt.Sprintf("NOT FOUND error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("Root chunk not found %s: %s", key, err)), http.StatusNotFound) Respond(w, r, fmt.Sprintf("root chunk not found %s: %s", key, err), http.StatusNotFound)
return return
} }
@ -507,19 +509,19 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
// contained in the manifest // contained in the manifest
func (s *Server) HandleGetFiles(w http.ResponseWriter, r *Request) { func (s *Server) HandleGetFiles(w http.ResponseWriter, r *Request) {
if r.uri.Path != "" { if r.uri.Path != "" {
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, "files request cannot contain a path"), http.StatusBadRequest) Respond(w, r, "files request cannot contain a path", http.StatusBadRequest)
return return
} }
key, err := s.api.Resolve(r.uri) key, err := s.api.Resolve(r.uri)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
return return
} }
walker, err := s.api.NewManifestWalker(key, nil) walker, err := s.api.NewManifestWalker(key, nil)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
@ -582,14 +584,14 @@ 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 {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
return return
} }
list, err := s.getManifestList(key, r.uri.Path) list, err := s.getManifestList(key, r.uri.Path)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
@ -682,7 +684,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 {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err)), http.StatusInternalServerError) Respond(w, r, fmt.Sprintf("cannot resolve %s: %s", r.uri.Addr, err), http.StatusInternalServerError)
return return
} }
@ -697,9 +699,9 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
} }
switch status { switch status {
case http.StatusNotFound: case http.StatusNotFound:
ShowError(w, &r.Request, fmt.Sprintf("NOT FOUND error serving %s %s: %s", r.Method, r.uri, err), http.StatusNotFound) Respond(w, r, err.Error(), http.StatusNotFound)
default: default:
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
} }
return return
} }
@ -710,19 +712,19 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
list, err := s.getManifestList(key, r.uri.Path) list, err := s.getManifestList(key, r.uri.Path)
if err != nil { if err != nil {
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError) Respond(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
log.Debug(fmt.Sprintf("Multiple choices! --> %v", list)) log.Debug(fmt.Sprintf("Multiple choices! --> %v", list), "ruid", r.ruid)
//show a nice page links to available entries //show a nice page links to available entries
ShowMultipleChoices(w, &r.Request, list) ShowMultipleChoices(w, r, list)
return return
} }
// check the root chunk exists by retrieving the file's size // check the root chunk exists by retrieving the file's size
if _, err := reader.Size(nil); err != nil { if _, err := reader.Size(nil); err != nil {
ShowError(w, &r.Request, fmt.Sprintf("NOT FOUND error serving %s %s: %s", r.Method, r.uri, fmt.Errorf("File not found %s: %s", r.uri, err)), http.StatusNotFound) Respond(w, r, fmt.Sprintf("file not found %s: %s", r.uri, err), http.StatusNotFound)
return return
} }
@ -732,16 +734,18 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
} }
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Debug(fmt.Sprintf("HTTP %s request URL: '%s', Host: '%s', Path: '%s', Referer: '%s', Accept: '%s'", r.Method, r.RequestURI, r.URL.Host, r.URL.Path, r.Referer(), r.Header.Get("Accept"))) req := &Request{Request: *r, ruid: uuid.New()[:8]}
log.Info("serve request", "ruid", req.ruid, "method", r.Method, "url", r.RequestURI)
uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/")) uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/"))
req := &Request{Request: *r, uri: uri}
if err != nil { if err != nil {
log.Error(fmt.Sprintf("Invalid URI %q: %s", r.URL.Path, err)) Respond(w, req, fmt.Sprintf("invalid URI %q", r.URL.Path), http.StatusBadRequest)
ShowError(w, r, fmt.Sprintf("Bad request %s %s: %s", r.Method, uri, fmt.Sprintf("Invalid URI %q: %s", r.URL.Path, err)), http.StatusBadRequest)
return return
} }
log.Debug(fmt.Sprintf("%s request received for %s", r.Method, uri))
req.uri = uri
log.Debug("parsed request path", "ruid", req.ruid, "method", req.Method, "uri", req.uri)
switch r.Method { switch r.Method {
case "POST": case "POST":
@ -760,7 +764,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// strictly a traditional PUT request which replaces content // strictly a traditional PUT request which replaces content
// at a URI, and POST is more ubiquitous) // at a URI, and POST is more ubiquitous)
if uri.Raw() || uri.DeprecatedRaw() { if uri.Raw() || uri.DeprecatedRaw() {
ShowError(w, r, fmt.Sprintf("No PUT to %s allowed.", uri), http.StatusBadRequest) Respond(w, req, fmt.Sprintf("PUT method to %s not allowed", uri), http.StatusBadRequest)
return return
} else { } else {
s.HandlePostFiles(w, req) s.HandlePostFiles(w, req)
@ -768,7 +772,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
case "DELETE": case "DELETE":
if uri.Raw() || uri.DeprecatedRaw() { if uri.Raw() || uri.DeprecatedRaw() {
ShowError(w, r, fmt.Sprintf("No DELETE to %s allowed.", uri), http.StatusBadRequest) Respond(w, req, fmt.Sprintf("DELETE method to %s not allowed", uri), http.StatusBadRequest)
return return
} }
s.HandleDelete(w, req) s.HandleDelete(w, req)
@ -798,8 +802,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.HandleGetFile(w, req) s.HandleGetFile(w, req)
default: default:
ShowError(w, r, fmt.Sprintf("Method "+r.Method+" is not supported.", uri), http.StatusMethodNotAllowed) Respond(w, req, fmt.Sprintf("%s method is not supported", r.Method), http.StatusMethodNotAllowed)
} }
} }

View file

@ -416,11 +416,11 @@ func TestBzzGetPath(t *testing.T) {
} }
nonhashresponses := []string{ nonhashresponses := []string{
"error resolving name: no DNS to resolve name: &#34;name&#34;", "cannot resolve name: no DNS to resolve name: &#34;name&#34;",
"error resolving nonhash: immutable address not a content hash: &#34;nonhash&#34;", "cannot resolve nonhash: immutable address not a content hash: &#34;nonhash&#34;",
"error resolving nonhash: no DNS to resolve name: &#34;nonhash&#34;", "cannot resolve nonhash: no DNS to resolve name: &#34;nonhash&#34;",
"error resolving nonhash: no DNS to resolve name: &#34;nonhash&#34;", "cannot resolve nonhash: no DNS to resolve name: &#34;nonhash&#34;",
"error resolving nonhash: no DNS to resolve name: &#34;nonhash&#34;", "cannot resolve nonhash: no DNS to resolve name: &#34;nonhash&#34;",
} }
for i, url := range nonhashtests { for i, url := range nonhashtests {