@cryptotaxi247 / kubo / commits / fd01acdfc

feat(gateway): ?filename with download=true

This implements 'attachment' mode triggered then ?filename parameter is accompanied with &download=true When Content-Disposition: attachment is detected by a modern browser it will skip rendering and immediately open the "save as" dialog, making this useful feature for using IPFS gateway as target of "Download" links on various websites. Parameter name was suggested in: https://github.com/ipfs/go-ipfs/pull/4177#issuecomment-414870327

Marcin Rataj committed Sep 16, 2020 at 22:10 UTC fd01acdfc0cede60706d59cfdeaa9784c8f7c8f3
3 files changed +21 -2
core/corehttp/gateway_handler.go
+5 -1
@@ -261,7 +261,11 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
261 urlFilename := r.URL.Query().Get("filename")
262 var name string
263 if urlFilename != "" {
264 - w.Header().Set("Content-Disposition", fmt.Sprintf("inline; filename*=UTF-8''%s", url.PathEscape(urlFilename)))
264 + disposition := "inline"
265 + if r.URL.Query().Get("download") == "true" {
266 + disposition = "attachment"
267 + }
268 + w.Header().Set("Content-Disposition", fmt.Sprintf("%s; filename*=UTF-8''%s", disposition, url.PathEscape(urlFilename)))
269 name = urlFilename
270 } else {
271 name = getFilename(urlPath)
docs/gateway.md
+10
@@ -49,6 +49,16 @@ your query string to explicitly specify the filename. For example:
49
50 > https://ipfs.io/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG?filename=hello_world.txt
51
52 +When you try to save above page, you browser will use passed `filename` instead of a CID.
53 +
54 +## Downloads
55 +
56 +It is possible to skip browser rendering of supported filetypes (plain text,
57 +images, audio, video, PDF) and trigger immediate "save as" dialog by appending
58 +`&download=true`:
59 +
60 +> https://ipfs.io/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG?filename=hello_world.txt&download=true
61 +
62 ## MIME-Types
63
64 TODO
test/sharness/t0110-gateway.sh
+6 -1
@@ -31,11 +31,16 @@ test_expect_success "GET IPFS path succeeds" '
31 curl -sfo actual "http://127.0.0.1:$port/ipfs/$HASH"
32 '
33
34 -test_expect_success "GET IPFS path with explicit filename succeeds with proper header" "
34 +test_expect_success "GET IPFS path with explicit ?filename succeeds with proper header" "
35 curl -fo actual -D actual_headers 'http://127.0.0.1:$port/ipfs/$HASH?filename=testтест' &&
36 grep -F \"Content-Disposition: inline; filename*=UTF-8''test%D1%82%D0%B5%D1%81%D1%82\" actual_headers
37 "
38
39 +test_expect_success "GET IPFS path with explicit ?filename and download=true succeeds with proper header" "
40 + curl -fo actual -D actual_headers 'http://127.0.0.1:$port/ipfs/$HASH?filename=testтест&download=true' &&
41 + grep -F \"Content-Disposition: attachment; filename*=UTF-8''test%D1%82%D0%B5%D1%81%D1%82\" actual_headers
42 +"
43 +
44 # https://github.com/ipfs/go-ipfs/issues/4025#issuecomment-342250616
45 test_expect_success "GET for Service Worker registration outside of an IPFS content root errors" "
46 curl -H 'Service-Worker: script' -svX GET 'http://127.0.0.1:$port/ipfs/$HASH?filename=sw.js' > curl_sw_out 2>&1 &&