Skip to content

Commit 1ae0411

Browse files
holisticodefjl
authored andcommitted
swarm/api: fixed 404 handling on missing default entry (#15139)
1 parent d54e353 commit 1ae0411

File tree

6 files changed

+311
-39
lines changed

6 files changed

+311
-39
lines changed

swarm/api/api.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,13 @@ func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionRe
144144
if entry != nil {
145145
key = common.Hex2Bytes(entry.Hash)
146146
status = entry.Status
147-
mimeType = entry.ContentType
148-
log.Trace(fmt.Sprintf("content lookup key: '%v' (%v)", key, mimeType))
149-
reader = self.dpa.Retrieve(key)
147+
if status == http.StatusMultipleChoices {
148+
return
149+
} else {
150+
mimeType = entry.ContentType
151+
log.Trace(fmt.Sprintf("content lookup key: '%v' (%v)", key, mimeType))
152+
reader = self.dpa.Retrieve(key)
153+
}
150154
} else {
151155
status = http.StatusNotFound
152156
err = fmt.Errorf("manifest entry for '%s' not found", path)

swarm/api/http/error.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import (
2525
"fmt"
2626
"html/template"
2727
"net/http"
28+
"strings"
2829
"time"
2930

3031
"github.com/ethereum/go-ethereum/log"
32+
"github.com/ethereum/go-ethereum/swarm/api"
3133
)
3234

3335
//templateMap holds a mapping of an HTTP error code to a template
@@ -51,12 +53,14 @@ func initErrHandling() {
5153
//pages are saved as strings - get these strings
5254
genErrPage := GetGenericErrorPage()
5355
notFoundPage := GetNotFoundErrorPage()
56+
multipleChoicesPage := GetMultipleChoicesErrorPage()
5457
//map the codes to the available pages
5558
tnames := map[int]string{
56-
0: genErrPage, //default
57-
400: genErrPage,
58-
404: notFoundPage,
59-
500: genErrPage,
59+
0: genErrPage, //default
60+
http.StatusBadRequest: genErrPage,
61+
http.StatusNotFound: notFoundPage,
62+
http.StatusMultipleChoices: multipleChoicesPage,
63+
http.StatusInternalServerError: genErrPage,
6064
}
6165
templateMap = make(map[int]*template.Template)
6266
for code, tname := range tnames {
@@ -65,6 +69,40 @@ func initErrHandling() {
6569
}
6670
}
6771

72+
//ShowMultipeChoices is used when a user requests a resource in a manifest which results
73+
//in ambiguous results. It returns a HTML page with clickable links of each of the entry
74+
//in the manifest which fits the request URI ambiguity.
75+
//For example, if the user requests bzz:/<hash>/read and that manifest containes entries
76+
//"readme.md" and "readinglist.txt", a HTML page is returned with this two links.
77+
//This only applies if the manifest has no default entry
78+
func ShowMultipleChoices(w http.ResponseWriter, r *http.Request, list api.ManifestList) {
79+
msg := ""
80+
if list.Entries == nil {
81+
ShowError(w, r, "Internal Server Error", http.StatusInternalServerError)
82+
return
83+
}
84+
//make links relative
85+
//requestURI comes with the prefix of the ambiguous path, e.g. "read" for "readme.md" and "readinglist.txt"
86+
//to get clickable links, need to remove the ambiguous path, i.e. "read"
87+
idx := strings.LastIndex(r.RequestURI, "/")
88+
if idx == -1 {
89+
ShowError(w, r, "Internal Server Error", http.StatusInternalServerError)
90+
return
91+
}
92+
//remove ambiguous part
93+
base := r.RequestURI[:idx+1]
94+
for _, e := range list.Entries {
95+
//create clickable link for each entry
96+
msg += "<a href='" + base + e.Path + "'>" + e.Path + "</a><br/>"
97+
}
98+
respond(w, r, &ErrorParams{
99+
Code: http.StatusMultipleChoices,
100+
Details: template.HTML(msg),
101+
Timestamp: time.Now().Format(time.RFC1123),
102+
template: getTemplate(http.StatusMultipleChoices),
103+
})
104+
}
105+
68106
//ShowError is used to show an HTML error page to a client.
69107
//If there is an `Accept` header of `application/json`, JSON will be returned instead
70108
//The function just takes a string message which will be displayed in the error page.

swarm/api/http/error_templates.go

Lines changed: 179 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func GetGenericErrorPage() string {
165165
</tr>
166166
<tr>
167167
<td class="value">
168-
{{.Msg}}
168+
{{.Msg}}
169169
</td>
170170
</tr>
171171
@@ -339,7 +339,184 @@ func GetNotFoundErrorPage() string {
339339
</tr>
340340
<tr>
341341
<td class="value">
342-
{{.Msg}}
342+
{{.Msg}}
343+
</td>
344+
</tr>
345+
346+
<tr>
347+
<td class="key">
348+
Error code:
349+
</td>
350+
</tr>
351+
<tr>
352+
<td class="value">
353+
{{.Code}}
354+
</td>
355+
</tr>
356+
357+
</tbody>
358+
</table>
359+
</section>
360+
</content-body>
361+
362+
<footer>
363+
<p>
364+
Swarm: Serverless Hosting Incentivised Peer-To-Peer Storage And Content Distribution<br/>
365+
<a href="http://swarm-gateways.net/bzz:/theswarm.eth">Swarm</a>
366+
</p>
367+
</footer>
368+
369+
370+
</div>
371+
</body>
372+
373+
</html>
374+
`
375+
return page
376+
}
377+
378+
//This returns the HTML for a page listing disambiguation options
379+
//i.e. if user requested bzz:/<hash>/read and the manifest contains "readme.md" and "readinglist.txt",
380+
//this page is returned with a clickable list the existing disambiguation links in the manifest
381+
func GetMultipleChoicesErrorPage() string {
382+
page := `
383+
<html>
384+
385+
<head>
386+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
387+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
388+
<meta http-equiv="X-UA-Compatible" ww="chrome=1">
389+
<meta name="description" content="Ethereum/Swarm multiple options page">
390+
<meta property="og:url" content="https://swarm-gateways.net/bzz:/theswarm.eth">
391+
392+
<style>
393+
394+
body, div, header, footer {
395+
margin: 0;
396+
padding: 0;
397+
}
398+
399+
body {
400+
overflow: hidden;
401+
}
402+
403+
.container {
404+
min-width: 100%;
405+
min-height: 100%;
406+
max-height: 100%;
407+
}
408+
409+
header {
410+
display: flex;
411+
align-items: center;
412+
background-color: #ffa500;
413+
/* height: 20vh; */
414+
padding: 5px;
415+
}
416+
417+
.header-left, .header-right {
418+
width: 20%;
419+
}
420+
421+
.header-left {
422+
padding-left: 40px;
423+
float: left;
424+
}
425+
426+
.header-right {
427+
padding-right: 40px;
428+
float: right;
429+
}
430+
431+
.page-title {
432+
/* margin-top: 4.5vh; */
433+
text-align: center;
434+
float: left;
435+
width: 60%;
436+
color: white;
437+
}
438+
439+
content-body {
440+
display: block;
441+
margin: 0 auto;
442+
/* width: 50%; */
443+
min-height: 60vh;
444+
max-height: 60vh;
445+
padding: 50px 20px;
446+
opacity: 0.6;
447+
background-color: #A9F5BF;
448+
}
449+
450+
table {
451+
font-size: 1.2em;
452+
margin: 0 auto;
453+
}
454+
455+
tr {
456+
height: 60px;
457+
}
458+
459+
td {
460+
text-align: center;
461+
}
462+
463+
.key {
464+
color: #111;
465+
font-weight: bold;
466+
width: 200px;
467+
}
468+
469+
.value {
470+
color: red;
471+
font-weight: bold
472+
}
473+
474+
footer {
475+
height: 20vh;
476+
background-color: #ffa500;
477+
font-size: 1em;
478+
text-align: center;
479+
padding: 20px;
480+
}
481+
482+
</style>
483+
484+
<title>Swarm::HTTP Disambiguation Page</title>
485+
</head>
486+
487+
488+
<body>
489+
<div class="container">
490+
491+
<header>
492+
<div class="header-left">
493+
<img style="height:18vh;margin-left:40px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACrCAYAAACE5WWRAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QMKDzsK7uq5KAAAGndJREFUeNrtnXuU3MV15z+3qnokjYQkQA8wD4NsApg4WfzaEIN5GQgxWSfxiWObtZOsE++exDl2nGTxcZKTk3iPj53jRxwM8XHYYHsdP9aQALIBARbExDjGMbGDMCwvIQGWkITempGm+1d3/6j6df+6p3tmeqZ75tet+p6jwzDd0/37Vn3r3lu3qm5BQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkLCbGALPzszkI+dUEYsEgt2HcgqMr8bACOg5X5sST1XMhgHvhZ+HnGnU+OdwOWQLQVuA67H6wt1C1bzSVgJXcDZ/0EmVwMVBAPZ6vjKAeCTeP183Xr58pmv5ApnbEnEIHIKIhnKBAjYHrikim0Iw9ilGHsBYq9DuRTwcfgL6Gg0BIuAqxC5CJHNwE6UDAOIAy2HBUsWq+OQM5D5XFQvBX4f+AXgYeAGvH4rtKCAzlJd1kKW5S7wUuDXUF5NkKsv9JKBbFVLfzmgBtwHfA6v3y2TBUvC6tgsuRWR9wJ/CCyOvzwSO/QHwHvxuqvrzqxYqEZBOXccykfwvDKKRds8TjthFVED/hn4AF73l0FcyRU2XF2jS42MInIhIl8D3tZkPUInWuA04LcQGQe2oozNaMZWqUC1Bs6twcg78PIZlBOn0XnRFbZ9euBM4F2I7AOeQxlPFqsMoqrHOXIF8G7gDbHDssI7FThcaDeJluxR4GvRJfkgLu0sMOsuRvkQyqpoAafrpeksVlFgI8Am4K8x3EFtYYIue9QLSqKojKxA5MYYS51eEFI7tyMt/78SeD1wNSKP4nVrPU5rF39Z2YaIB141o8E9vcUqCr8GOIR9wHdQkrDm3e0pILIGkXcB/wicwfTzvFqHDhZgKfAORF6GyNPAi2gb9+g1w/sfMWK+AXIKypo429NZCkuiux5H2IkwATwN3J+ENZ8InW0R+V3gIzGOqrW4vW6FVXz9HOAq4DREHsfrvsmxloOJ2kG8vwtjfoSwFOGcKBDtSljCGMI+hIMFl/hUEta8MG0Kzi8EbgZ+ETg2imGmmE5YRIEuAk5CeA7l4Unv8D7MAT2gfjvIRoT7MfI6YHmTuDoLKwNeRDgUfy7GfgsqLDP0gjKSWymDkTMxcj2wHnhJHyYveZ5iHOEn0YLIlBKtP6d6fPYw2fI3AzcCO2P/SAfh7ovfMVHGZndDP9MLgfmpwPuBXwJWAYf6NMM+FK3HRNez7syDqYDfrXiux7rbUK4C3omyLFgtfBRrbqFKaxiG02LZKConYOSDwP3A24FlMV3Qa2TADoQ9BVF1D1+FUQEqkNWew1Y+i+hVGL0LOILwAmGt0Jc9VTScFksZxcjP4fkIIXF4uE/flEUrtb9nHT2mQDUKbQKybA+WP0HMCtB1MW8mlHzjzHAIqznBeRnw3wkJTumDqEy0GAcQxmYYzM9Stvkk1SwOlkqeCoG9rgGWAD4Jq29uLy4WG1kLfLogqKxP3zgWk49Z13HU3GM4D+wF2Qe6CjixrJZr8GOszMOxKwT4akFU/UIVYUcfRTtzZ4+8APIIsK+MMddwBO/79wvCiwjPxGl6P2dMUqK+y0C2gmwOlqxjeiIJa86uQtiPsAV4kaMHY0FgPDmnWWkS1gxcRbBgW0Ojl3963qOxdRDkUWBHFNiCxV9umFs5xkTbgCUoxwKjlP58y9ymMkAF5A7gTvBZElZ/MY4wjjIKrKHTTs3BH0g7gS+Q8cRCZyKOFmHlTX8I2IJyHCELX+mzwLRpBlncR987MRlgF/AdhNupeQ3fQxLWPI9qRdgF7AeOiS6y15lsRVGQlcDVGDbh9eGYb+vVfvQKIfm7AfhO4zBrz8WbhNV1/AW7CWtva2L81aseWYSakxFGQVcDt2PkZuDP8bqvB+JyhMMc/0Dm99etIZRCVEezsIoSqwLPohxD2Ju1aPZuT0ZQjkVlNSAoGueiVeCtwCUY+Thwe3Rf3Rwfs3FAbAa+QeYfaXKvWblWd4Zjo58RiR23bNbyEiYQDsX9TYs7BPgZUk9EFuMoQWUtyEtQWd7yyfnO1Iywvnc58IZ48PXh+PxTO2Iji4CzgJuAW8n89sa3a0nH61BMssUAXwfW9qxdQuy1sqWNJmJ23zZiKTkG5GS0wyAVPQx6uIO3eAx4H15/PK3sEUPFZkzUYs0GLfXENlmsqWaQYRbpYqBsmiyWMgrmJFROmHKABovVbuuzB1YDv4nIWkSeRaN7bG/BtO7ufPkzJUlYU1vzsGNTGG8ITMbAnBzjqMXTmo3OwiqmI84FrkDkdEQewuvhQe+S5Aq7Q4aaM9EuAvzOrrBTf+wGLsPrQK91plnhTKwWHAR2gFQRfxjMS6Y9C9g9aoTdqEcYgjXcJKwpHCywH2QXMB4FNBLco98S9p/LWlROidLSOQh3f9yNmg1LnyRhdXJ58BzIgQ5hgwBHQLciug3MWWjLWcCZYSwewNChCk2SsCZZjyqwD2QnM99qU0X8D8GsAU5CWcbUS0RK2NJyAGkqMDJUSMJqdOxOkL2x06XLDreI3xX+Xo9FzUuZfNhBCHmw/cHaDfcesSQsOATyfCElILMXqGYIuxC/C5XTUHlJ4fW9hdoKMOQbD49mYY0De6KV6n0niz6J6HZUVkVBHSW7WI9OYZng6mQHYVdD1sfOdsA4os8SMveL6P/+rySsBcKOGJjPlzvKPz/Pvldi7CVJWIMfmGcxjtoRg+aF7NRqFNgiQk4sBe8D6vZaE5xl6Mi8julEFNf0641JWKVBBvJsjKOkpLMwXxDYKENWBG+YhGVoTnAqg+FqfBwAI9FFumFwkUNyYPVcHyqxyI4YSzFgnSPRch0h7G6oDnqPDL75tQ6y50H1LozsJ2zhNX1sr2V9iokM4YDEH5HpnmGYNQ2BEzShWCyANccDvwz8LHAM3RWunQ4V0LX07jSPjZ/1CPB1Mn0wfItAdbDj+eEIGPMDBeefBVt2jmPk32NnLSFcBtBLIfTKYo0STtx8GvgymW5hsQ172f3gd8lgWqzWc3lWIOvQ19acAbyHcLRrzpfA9chi1YAvY7iJqmZtn7+VY0nvJRwei2WbykKuRDkc5CKTO8Y5qGW7Ub0bIxOEiskr5yCwuVgsR6h2/C/A/yLTB/FoW1E1czwOZXzQMl2DI6wRAV+vhlwB+SDw5/GEy/dRzZpOtyixSH+8aFL1SYw8RChQdgazW7ebjbBMdMn3AZ8i02+iHMLFnTm+g6WqiAW5JnI8MXCkNgj3QQ+GK5zsEq4EPg6cQKP21U7gj4H78DHgauc68lPD1qwAfhP4mS7d2mxc4QvAJ8l0U8fnmszxCuATkeNhwrLUTuCDwLem5JiE1bXAzgfeC1wRcz6exuKuicHwBuC6pttGobnxKwaq9Rnk2YQ7b86Kr/oeCEui29sC3AXcTKZ+yjiwwfH1hNvHihyzmNfKLd89wGfw+kBHjklYUz1WPcZYB3wYOI9wx0y1JQiutbiqMeAB4MN43TytFbRmJArrrcCpTH1/4HTCqsS//wfgHjLd1XFyUfxd4PgXwM9HjkVOWQvnnOO/An+J16eTxZrO5RnCdHuxwGEWYXg/4aqSTnvIpzoMKsD1wHXAoY4juuEeBbgyWrDKLIQlwPeAT5Pp3uldu4BlBOV9wB9Ei9TuIVuF1fqdnwWunZLjURu857MgD1gZJeNtCH8PvJmplzf8NG7pQuBNwDgiz4Tb52m+CSzPgamC6hMgDyAsgbbnBluDdxsF8UPgM2T6VZTDbW+3t4U7Eo2MIvw6cAPwK9Nw1Gk4viEOhmaOCxzkSylE1XAJb45B+DoaWenp8kHTZdZzS/A48Am8bmifC8ur4NXjr5OB/xJdcB7vFC3WCPAM8DngYbJ42rldQO0kFvEAjFwF/E/g5TPkmDH92mHO8Qng43WOC3gzysILy4gBTokzvYvo/u7Abt6/BPg2cA3wTMfZVfMS0U/FGeSqYMF0TRTa/wW+QhbvgJ7KDYkIhlNQ/gq4tMtnnomwihglXEp1DYbN9Tuh53kGKQsgpGLyb13stN8mbHg70uWndSusPMA+DHwR+Apen5hBesJGQZwPugflS3jd2TEwb+Z4WuT4O1HY3XLsVljdcRw6i2XkzwhXva2i3XW1/RNWztsC2wk3rX4sWC8Jv810srjCz0tBx2dkpQLHDwFXE8oVzZbjbITVyvGfgI/i1YcFbvruImWeLdQIcDHwN8BxzH3nQa0HnzESk49/hHAvmWZdj+5mjpU4abg2Dpq5Pt9shdWO4x/j2QiR40xya6UUVt7gIiBcRLju7RcKwTAlEFYe/C4C7gb+N17vm/HEA4qTj4sIC95X9pBjL4SV93WeYL0Br/cOnsVqHsEnxcD8vBhY9rICea+EVUwnHAIeAv60nmCdLsFp5QSUT8QE59Iec+yVsFo5/hD4k3qCtcfWqz95LBEQWYbIB4CvxFmf7YNj9/R295ISlmNOBf4bIh4jm8h0cseqgJVliLwvzhBPpT83XmifOJ4C/FaYscp/tOVYOotlZRnK5+NM6kgfI8VeW6zWthkFHkS4mkz3tXAcRbkB+MU4A+sXx15brHbu8QcYeRu1WDO+R7FFP+AQLMIThGp4g3ZoQwj37zyNUIkCa8fRIDxOOGUzqBw3I1hUR3srgP4gN9/57Vv7UVYzGMfNPLAnFrTNU9c6xXurCNuBAwPGcW+sItiX9Lybp5FxCGEMZSVh9X6Ecm1Xy4uujSEcoPsziUcDx9IJqxHLhRrpB+L1IqsK1m2hm3wvjU2Ds409jwaOpRNWczAa6m7uR1nLwlZfmUDYTe8vYcsvGtiHcsKQciydsPLR4hF+AixFWRHzPzpP33247rr62+GK8BOUpYRDHEuYny0H88mxVMIqNsBYvP003wPVr9tPBahFS3KE+avtILFzxwlXCK+mfwXYFopj6YRVHNljwOZ4++nKHk/ffbwXZ/+CcgyD6Jkh5lg6YRVH927gYJxdLWP2Gfu8OP9YrAE6QTlyTUWOKwhlAHrFsUpJtpuXMeeS3z6/E9iLcjyzO8s3hrCPRmbelJDjrhjgHxdTFN0s3dgYQxU5luYMQ9mTeSHB2nz7/ExmZLti8DoIx9vyBOu+OEseCo6DkCXOg98t0XWsIGxx8ZMsAPU7Bget9HW+vDI9x8Cv9BzdADU80ewfBJahrCo07P7Y4FnZXEIPOe4rXORUeo6DWCoyi418EGVZXJ7IGK4KxAPP0Q3kqA4jeifCSJy2jzA89VQLHGUXopawjXugOLoBa/AJkO2ENa8a6GIatdMtIbPdjw2FC8iRYyPHKiGxungQOA6KsBTYNcWtEho74UBs+EEszu+B3dPcnJELrPQcXclHb4g1wiUAM01wjsfGH4n/ym6hwt4o5EWY8bW947E9FpWVY1mFZWJj76CxLdd0Kci88RdTzsuRTBw0L8ySo28jME3C6owqyLYYoM/V1Gfxc/LLkcyQcjwUBVYajmURVrxjmT0gu+ntqrzE+OtgwT0uRPBb5LiH3iY4pRBjLlpAjqURVt6wO6Kg+rm7UWPHFi9Hmi+OGjnuof8JzoXgWCphaczVbGN+V+Xz27eqhfhrWDnm7rEy7MLKG/ZAtFB5jCEL8Bxhu0log17ffiol4agx/pr3G17dPBOdALaBjFGe27lq0T3ZHgS/+WL4T0rEUXrMsVTCymhO/pUtsdeLBGvOcRflvNJuXpPI/RSWIT/8GVzCBIORDR8vBL+LZuhudrdwlCHiWDphHQI5QKOC3aAsseTx1+EZDIYxkKeHgGPPXWN/qs2YkSOgm4CTCNuK++XT+zXjyRt+C/BRMn2qA8fH5oFj7rb6FdxvjRyf7McsrT+wxgA/B7wReFkcHT2MGfS4KK5etscosIlQXvHe+q0S0L5+VIPjpYRKyL3muJJw5rLXHB8pcMyoSIgSe1SjVPooqmLtzgrwekI9TktvTuX2Wlj5ndLXA/fVy2tPfWVdg6MzIyjnAf+1xxx7KSwThf/ZKKjpOZbSYtUjOQM1D8YsQXgn4XKkJcytoFivhGViMPsDwiUA+7pu6BET5lvegzVLorh+JloGXwJh5Rwfihz39rP+6PwGm821088gFLl9XSGemW9hmWhZNgLryfSRMAgKxf7nZqVfHjn+5zlynIuwTJygbQRuq3Pss6jmfxbT3PAWeCmhGOwJdF+1bi7CGomB+ceAp+uVkntxF/NkjqdGjifOkuNshbWIcHPGx4DNZFqbL1Et7PTYWahleQdcAVxG2L8eG7Tnwsq5vgjcQqY3972hm0V2OXA54WiXdMGxG2HlHHdHjjfVOSpDfjNF5044lnDh0MWEwwNHeiiskdjY3wA2kOmOBbLSKyPHS7rgOFNhVYA9keNdZPrCQifKKJG4JI7oX4kdUJujsPLirXcAfwfsJVMNdzbECcXCcFweOV44A47TCStPH9xOuE1sD5nqlCmSo1BYxdF9JvCOGH+127Q2lbDy1MEW4DoyfWw+44upQwAHtVpxEnN15Og6cOwkrAZH5Tp8iThSxiWI5qm7iTPHywi3oI7TdJ34JGFJDFo3Abch8m1qvlqWxm48pYRLFrImjm+MHA+3cGwVVpHjeuDbZDpRtvuhy7u21Wy9RoDXxPxQXtOgVVj5ove1wD+T6XidoQ4Mx1cD72zhWBSWISReryckOMfLZKUGQ1jFxod8dI8Srmg7G1gchTVK2LD3b8Cn6tnkQYJEF1mt5QnW3wDOCYNGVxDWIscISdy/JtOxQaA0GGhOT5wBXAT6RuDfCcm/H5d19M7SgsUEq14C/AfznOA8umBN8WeLlVVYcUPF0dlWjquHjmOpYaT5v8M8kKxJ/Z2QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJBwdMCZLt+7LPxsl1HfkjtTmOKib5u1XlPp/L3FNbyR+DnFtUtrYMS151ZpfK50fOaRsK/UCZg2p+zdovBawgwwOlroGFmKtWdg7csxprGL0rbpbGeDuqTltREBawXboWziMctzUR3T5jOLojsLUzkfa89seo/Ez80FOhr3HR4zaUuSY6TwOxveP+oKvzNmGabyGsSdXWiQVmH+NMa+CiuxSswqqNikmymRD8qRyjqM/SLOPoBzd+LcBpy7H+P+FuOODyO+YC2WW4ux92Ds6rafa+2pWHcLzq6g0maEW/cWrLu2rWVx9iycW4+rbMC4r+Aqd2PcHVj3n8LrlZtw5oymv63YMzHu8/H10zHuizj3XZy9vEW4x+Mqd8dn+CDOfQfrbqVS2YB1d2LMKwuW9QKsuxdXuR3rbsO5B7GVdyfRzBS2cjzOfR3rfh1nljcaVo7Fud/D2jsYcaOTXZb7S5z7wya3lIvPufcg7hGcfU2H7/xHXOWyNm7ycoy7F+eubBHqpVh3O85ehavcgnOvaHn9HMT9H4x5NcZ9E2t/B2fWTraIbg2u8n2M+1Os/QNMYf++sZdiK7dgKyfj7M9j3XpM4fmNOxlX+RKu8m5Gka7Ch6NTWO5crPtY55jI/R3O/vZky+LOwbgNLG1Tmsm4m7DuL3Dur8J7i3FQ5Wysu5MTW1yXtWdj3T0YWdchHjsN476Ac9/DFV0X4OwrEHcrxq7H2Fc2f27Rsrk1GPdYfUCELyk+99tx7pNYdwvWva6NJV6NdZ/H2lVl68Yyynw/yqlYe0zbeMf4ryHyXP33+dnAWu0RRPZyxJ0X3VH8u8prEUYwtWvJOJcRljfVZhC5ANjINrQu0kUYvLwF9G/x+nQ9sPdZI8jPas8gbMQz2maDtwLHI+Y2fPZw0yuTa9CM4XVDY5AUzjq67Ftk/DSeF8hqD7aICrC7gW3A6UlYU87wHIjfAvwrmBsx9gNYdyXWnY2XNWAsNX8P1dqdVNrM4MTfipcLGEWoZnkX/wbwNarswshWMvemesdU3BK8fy3Kzc0itYtxnIwx97M6zhmywrnS/GflBwiH250GRKjgql+dhnGoC2r1iabvzzGhOwDF6cYwWIoCzSCbyBCeB3lpEtZUqNWg5mv42qdRrgGeBP0p0HcDH8fZv8HYc4FG5ZqmbpKNiL6CqlsaXckq0LPQ7NYgvOwGlLc3OoY14X26Hdck1AqeGqpVdh7q/LyeHbQ/yWxQnucIB6ZhLAgTVP00R+1NqCjYtqSIeKR8h2LKtUm/ePrEV5/ieJ5inxUUg+DwejEi12Hl/WS+2TVUDHjdg8pevK4jnGy5AOV7eD0YLcJ3seKx7hVktR8jegHIY9SyZvWI5NeR2GmG5WI6n3Sa/hiaKogx01u1eH5wgFAui5UpOPvy+uztRaCWKVmWkdWO4Gt3IvJRsB+a9LdVD1l2BOHfQN4U7cF5wDdjoJyr5m7g/PjzLyF8u60oVCYI9UXbJ05Dn5/N3KsOD2WGs4TBu/wsmEsndWjdVWXbQaYoBKL34rkE51aDrEVkE9aGw6ABG1DOwZnXAsupyUNtXHIV9RtR+UA9pio+S8XBUgTkKvpVIDgJq8dQ/RFeX4V1y5oC5lotzH3Uvg+Jta3aWr1sK5bnQf8M4f8h1YNkphgXbQMs3vw+sJ56lN8aP2XrQSeoVD41KXiv1uCwvQb0ECLPDqvVGR5hVQxYsxnhX4DrMO6tWHsh1r0BW3krz1a+AH4rtdrncO9qE6NF4+H1y2RyCV4foIZvinq1dghhE3AumK+3jzyjTlaveQ9ewbobMe4tOHcxxv0q1t2Il5NYlH2Yxt3NzWH91OWJGoH39FX+PFMWytVpXl+gcLlUT+MVMq+s9t9n3D4FnILwMpBTQBS4hdHal0LJ+4cnV1dRzfNMzyLyIqIbUZ3cccbsQHiUrPoQdiW0lnvwgKvA/n3g/F14eR5kHcKpgEN0PSuyv+cAE4h5EngK9bXC548h8jjqt0/d+qaK8jjqt3bWntkC/lFU2wvVyG6Qp/D+ULKTU85TTfPP1kr4V9g2MJPlC+ekY1hdcY2Yyc5w2I04wdnwr47CKk3+eS2L4KZiOufsoLE+ajpMEJa3WONOPmfp0qSdhISEhISEhISEhISEhISEhISEhISEhISEhISEhIThxP8HhRpz3L2ZmSwAAAAASUVORK5CYII="/>
494+
</div>
495+
<div class="page-title">
496+
<h1>Swarm: disambiguation</h1>
497+
</div>
498+
<div class="header-right">
499+
<div id="timestamp">{{.Timestamp}}</div>
500+
</div>
501+
</header>
502+
503+
<content-body>
504+
<section>
505+
<table>
506+
<thead>
507+
<td style="height: 150px; font-size: 1.3em; color: black; font-weight: bold">
508+
Your request yields ambiguous results!
509+
</td>
510+
</thead>
511+
<tbody>
512+
<tr>
513+
<td class="key">
514+
Your request may refer to:
515+
</td>
516+
</tr>
517+
<tr>
518+
<td class="value">
519+
{{ .Details}}
343520
</td>
344521
</tr>
345522

swarm/api/http/server.go

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -441,14 +441,37 @@ func (s *Server) HandleGetList(w http.ResponseWriter, r *Request) {
441441
return
442442
}
443443

444-
walker, err := s.api.NewManifestWalker(key, nil)
444+
list, err := s.getManifestList(key, r.uri.Path)
445+
445446
if err != nil {
446447
s.Error(w, r, err)
447448
return
448449
}
449450

450-
var list api.ManifestList
451-
prefix := r.uri.Path
451+
// if the client wants HTML (e.g. a browser) then render the list as a
452+
// HTML index with relative URLs
453+
if strings.Contains(r.Header.Get("Accept"), "text/html") {
454+
w.Header().Set("Content-Type", "text/html")
455+
err := htmlListTemplate.Execute(w, &htmlListData{
456+
URI: r.uri,
457+
List: &list,
458+
})
459+
if err != nil {
460+
s.logError("error rendering list HTML: %s", err)
461+
}
462+
return
463+
}
464+
465+
w.Header().Set("Content-Type", "application/json")
466+
json.NewEncoder(w).Encode(&list)
467+
}
468+
469+
func (s *Server) getManifestList(key storage.Key, prefix string) (list api.ManifestList, err error) {
470+
walker, err := s.api.NewManifestWalker(key, nil)
471+
if err != nil {
472+
return
473+
}
474+
452475
err = walker.Walk(func(entry *api.ManifestEntry) error {
453476
// handle non-manifest files
454477
if entry.ContentType != api.ManifestType {
@@ -495,27 +518,8 @@ func (s *Server) HandleGetList(w http.ResponseWriter, r *Request) {
495518
// so just skip it
496519
return api.SkipManifest
497520
})
498-
if err != nil {
499-
s.Error(w, r, err)
500-
return
501-
}
502521

503-
// if the client wants HTML (e.g. a browser) then render the list as a
504-
// HTML index with relative URLs
505-
if strings.Contains(r.Header.Get("Accept"), "text/html") {
506-
w.Header().Set("Content-Type", "text/html")
507-
err := htmlListTemplate.Execute(w, &htmlListData{
508-
URI: r.uri,
509-
List: &list,
510-
})
511-
if err != nil {
512-
s.logError("error rendering list HTML: %s", err)
513-
}
514-
return
515-
}
516-
517-
w.Header().Set("Content-Type", "application/json")
518-
json.NewEncoder(w).Encode(&list)
522+
return list, nil
519523
}
520524

521525
// HandleGetFile handles a GET request to bzz://<manifest>/<path> and responds
@@ -544,6 +548,22 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
544548
return
545549
}
546550

551+
//the request results in ambiguous files
552+
//e.g. /read with readme.md and readinglist.txt available in manifest
553+
if status == http.StatusMultipleChoices {
554+
list, err := s.getManifestList(key, r.uri.Path)
555+
556+
if err != nil {
557+
s.Error(w, r, err)
558+
return
559+
}
560+
561+
s.logDebug(fmt.Sprintf("Multiple choices! --> %v", list))
562+
//show a nice page links to available entries
563+
ShowMultipleChoices(w, &r.Request, list)
564+
return
565+
}
566+
547567
// check the root chunk exists by retrieving the file's size
548568
if _, err := reader.Size(nil); err != nil {
549569
s.NotFound(w, r, fmt.Errorf("File not found %s: %s", r.uri, err))

0 commit comments

Comments
 (0)