diff --git a/src/http/gateway/resources/gateway.js b/src/http/gateway/resources/gateway.js
index c3a866c359..2b4daa61f0 100644
--- a/src/http/gateway/resources/gateway.js
+++ b/src/http/gateway/resources/gateway.js
@@ -12,6 +12,21 @@ const Stream = require('readable-stream')
const { resolver } = require('ipfs-http-response')
const PathUtils = require('../utils/path')
+function detectContenType (ref, chunk) {
+ let fileSignature;
+
+ // try to guess the filetype based on the first bytes
+ // note that `file-type` doesn't support svgs, thereore we assume it's a svg if ref looks like it
+ if (!ref.endsWith('.svg')) {
+ fileSignature = fileType(chunk);
+ }
+
+ // if we were unable to, fallback to the `ref` which might contain the extension
+ const mimeType = mime.lookup(fileSignature ? fileSignature.ext : ref)
+
+ return mime.contentType(mimeType);
+}
+
module.exports = {
checkCID: (request, reply) => {
if (!request.params.cid) {
@@ -97,7 +112,7 @@ module.exports = {
}
// response.continue()
- let filetypeChecked = false
+ let contentTypeDetected = false
let stream2 = new Stream.PassThrough({ highWaterMark: 1 })
stream2.on('error', (err) => {
log.error('stream2 err: ', err)
@@ -108,29 +123,20 @@ module.exports = {
pull(
toPull.source(stream),
pull.through((chunk) => {
- // Check file type. do this once.
- if (chunk.length > 0 && !filetypeChecked) {
- log('got first chunk')
- let fileSignature = fileType(chunk)
- log('file type: ', fileSignature)
-
- filetypeChecked = true
- const mimeType = mime.lookup(fileSignature
- ? fileSignature.ext
- : null)
+ // Guess content-type (only once)
+ if (chunk.length > 0 && !contentTypeDetected) {
+ let contentType = detectContenType(ref, chunk)
+ contentTypeDetected = true
log('ref ', ref)
- log('mime-type ', mimeType)
-
- if (mimeType) {
- log('writing mimeType')
+ log('mime-type ', contentType)
- response
- .header('Content-Type', mime.contentType(mimeType))
- .send()
- } else {
- response.send()
+ if (contentType) {
+ log('writing content-type header')
+ response.header('Content-Type', contentType)
}
+
+ response.send()
}
stream2.write(chunk)
diff --git a/test/gateway/index.js b/test/gateway/index.js
index 84ce39914a..b08e5882d8 100644
--- a/test/gateway/index.js
+++ b/test/gateway/index.js
@@ -19,7 +19,9 @@ const directoryContent = {
'nested-folder/hello.txt': loadFixture('test/gateway/test-folder/nested-folder/hello.txt'),
'nested-folder/ipfs.txt': loadFixture('test/gateway/test-folder/nested-folder/ipfs.txt'),
'nested-folder/nested.html': loadFixture('test/gateway/test-folder/nested-folder/nested.html'),
- 'cat-folder/cat.jpg': loadFixture('test/gateway/test-folder/cat-folder/cat.jpg')
+ 'cat-folder/cat.jpg': loadFixture('test/gateway/test-folder/cat-folder/cat.jpg'),
+ 'unsniffable-folder/hexagons-xml.svg': loadFixture('test/gateway/test-folder/unsniffable-folder/hexagons-xml.svg'),
+ 'unsniffable-folder/hexagons.svg': loadFixture('test/gateway/test-folder/unsniffable-folder/hexagons.svg'),
}
describe('HTTP Gateway', function () {
@@ -113,6 +115,22 @@ describe('HTTP Gateway', function () {
expect(file.hash).to.equal(expectedMultihash)
cb()
})
+ },
+ (cb) => {
+ const expectedMultihash = 'QmVZoGxDvKM9KExc8gaL4uTbhdNtWhzQR7ndrY7J1gWs3F'
+
+ let dir = [
+ content('unsniffable-folder/hexagons-xml.svg'),
+ content('unsniffable-folder/hexagons.svg'),
+ ]
+
+ http.api.node.files.add(dir, (err, res) => {
+ expect(err).to.not.exist()
+ const file = res[res.length - 2]
+ expect(file.path).to.equal('test-folder/unsniffable-folder')
+ expect(file.hash).to.equal(expectedMultihash)
+ cb()
+ })
}
], done)
})
@@ -166,7 +184,7 @@ describe('HTTP Gateway', function () {
})
})
- it('load a non text file', (done) => {
+ it('load a jpg file', (done) => {
let kitty = 'QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg'
gateway.inject({
@@ -184,6 +202,34 @@ describe('HTTP Gateway', function () {
})
})
+ it('load a svg file (unsniffable)', (done) => {
+ let hexagons = 'QmVZoGxDvKM9KExc8gaL4uTbhdNtWhzQR7ndrY7J1gWs3F/hexagons.svg'
+
+ gateway.inject({
+ method: 'GET',
+ url: '/ipfs/' + hexagons
+ }, (res) => {
+ expect(res.statusCode).to.equal(200)
+ expect(res.headers['content-type']).to.equal('image/svg+xml')
+
+ done()
+ })
+ })
+
+ it('load a svg file with xml leading declaration (unsniffable)', (done) => {
+ let hexagons = 'QmVZoGxDvKM9KExc8gaL4uTbhdNtWhzQR7ndrY7J1gWs3F/hexagons-xml.svg'
+
+ gateway.inject({
+ method: 'GET',
+ url: '/ipfs/' + hexagons
+ }, (res) => {
+ expect(res.statusCode).to.equal(200)
+ expect(res.headers['content-type']).to.equal('image/svg+xml')
+
+ done()
+ })
+ })
+
it('load a directory', (done) => {
let dir = 'QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/'
diff --git a/test/gateway/test-folder/unsniffable-folder/hexagons-xml.svg b/test/gateway/test-folder/unsniffable-folder/hexagons-xml.svg
new file mode 100644
index 0000000000..fe6b79dfd2
--- /dev/null
+++ b/test/gateway/test-folder/unsniffable-folder/hexagons-xml.svg
@@ -0,0 +1,56 @@
+
+
+
diff --git a/test/gateway/test-folder/unsniffable-folder/hexagons.svg b/test/gateway/test-folder/unsniffable-folder/hexagons.svg
new file mode 100644
index 0000000000..557d927b39
--- /dev/null
+++ b/test/gateway/test-folder/unsniffable-folder/hexagons.svg
@@ -0,0 +1,55 @@
+
+