mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +00:00
swarm/api/http: refactor ShowError and logging of HTTP requests
This commit is contained in:
parent
a375d95143
commit
a366b1a3df
3 changed files with 78 additions and 76 deletions
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -416,11 +416,11 @@ func TestBzzGetPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nonhashresponses := []string{
|
nonhashresponses := []string{
|
||||||
"error resolving name: no DNS to resolve name: "name"",
|
"cannot resolve name: no DNS to resolve name: "name"",
|
||||||
"error resolving nonhash: immutable address not a content hash: "nonhash"",
|
"cannot resolve nonhash: immutable address not a content hash: "nonhash"",
|
||||||
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
"cannot resolve nonhash: no DNS to resolve name: "nonhash"",
|
||||||
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
"cannot resolve nonhash: no DNS to resolve name: "nonhash"",
|
||||||
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
"cannot resolve nonhash: no DNS to resolve name: "nonhash"",
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, url := range nonhashtests {
|
for i, url := range nonhashtests {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue