This repository has been archived by the owner on Sep 28, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f236f1b
commit d9d0c08
Showing
20 changed files
with
27,221 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
dist/ | ||
|
||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
# while testing npm5 | ||
package-lock.json | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,22 @@ | ||
# ipfs-http-response | ||
# js-ipfs-http-response | ||
|
||
> Creates an HTTP response from an IPFS Hash | ||
### Installation | ||
|
||
> TODO | ||
## Usage | ||
|
||
This project consists on creating a HTTP response from an IPFS Hash. This response can be a file, a directory list view or the entry point of a web page. | ||
|
||
```js | ||
const ipfsHttpResponse = require('ipfs-http-response') | ||
|
||
ipfsHttpResponse(ipfsNode, ipfsPath) | ||
.then((response) => { | ||
... | ||
}) | ||
``` | ||
|
||
![ipfs-http-response usage](docs/ipfs-http-response.png "ipfs-http-response usage") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories. | ||
javascript() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
"name": "js-ipfs-http-response", | ||
"version": "0.1.0", | ||
"description": "Creates an HTTP response from an IPFS Hash", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"lint": "aegir lint", | ||
"release": "aegir release", | ||
"build": "aegir build", | ||
"test": "aegir test -t node" | ||
}, | ||
"pre-push": [ | ||
"lint", | ||
"test" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ipfs/js-ipfs-http-response.git" | ||
}, | ||
"keywords": [ | ||
"ipfs", | ||
"http", | ||
"response" | ||
], | ||
"author": "Vasco Santos <vasco.santos@moxy.studio>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/ipfs/js-ipfs-http-response/issues" | ||
}, | ||
"homepage": "https://github.com/ipfs/js-ipfs-http-response#readme", | ||
"dependencies": { | ||
"async": "^2.6.0", | ||
"cids": "^0.5.3", | ||
"debug": "^3.1.0", | ||
"file-type": "^8.0.0", | ||
"filesize": "^3.6.1", | ||
"ipfs-unixfs": "^0.1.14", | ||
"mime-types": "^2.1.18", | ||
"multihashes": "^0.4.13", | ||
"promisify-es6": "^1.0.3", | ||
"readable-stream-node-to-web": "^1.0.1" | ||
}, | ||
"devDependencies": { | ||
"aegir": "^13.1.0", | ||
"chai": "^4.1.2", | ||
"dirty-chai": "^2.0.1", | ||
"ipfs": "^0.28.2", | ||
"ipfsd-ctl": "^0.36.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
'use strict' | ||
|
||
const filesize = require('filesize') | ||
|
||
const mainStyle = require('./style') | ||
const pathUtil = require('../utils/path') | ||
|
||
function getParentDirectoryURL (originalParts) { | ||
const parts = originalParts.slice() | ||
|
||
if (parts.length > 1) { | ||
parts.pop() | ||
} | ||
|
||
return [ '', 'ipfs' ].concat(parts).join('/') | ||
} | ||
|
||
function buildFilesList (path, links) { | ||
const rows = links.map((link) => { | ||
let row = [ | ||
`<div class="ipfs-icon ipfs-_blank"> </div>`, | ||
`<a href="${pathUtil.joinURLParts(path, link.name)}">${link.name}</a>`, | ||
filesize(link.size) | ||
] | ||
|
||
row = row.map((cell) => `<td>${cell}</td>`).join('') | ||
|
||
return `<tr>${row}</tr>` | ||
}) | ||
|
||
return rows.join('') | ||
} | ||
|
||
function buildTable (path, links) { | ||
const parts = pathUtil.splitPath(path) | ||
const parentDirectoryURL = getParentDirectoryURL(parts) | ||
|
||
return ` | ||
<table class="table table-striped"> | ||
<tbody> | ||
<tr> | ||
<td class="narrow"> | ||
<div class="ipfs-icon ipfs-_blank"> </div> | ||
</td> | ||
<td class="padding"> | ||
<a href="${parentDirectoryURL}">..</a> | ||
</td> | ||
<td></td> | ||
</tr> | ||
${buildFilesList(path, links)} | ||
</tbody> | ||
</table> | ||
` | ||
} | ||
|
||
function render (path, links) { | ||
return ` | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>${path}</title> | ||
<style>${mainStyle}</style> | ||
</head> | ||
<body> | ||
<div id="header" class="row"> | ||
<div class="col-xs-2"> | ||
<div id="logo" class="ipfs-logo"></div> | ||
</div> | ||
</div> | ||
<br> | ||
<div class="col-xs-12"> | ||
<div class="panel panel-default"> | ||
<div class="panel-heading"> | ||
<strong>Index of ${path}</strong> | ||
</div> | ||
${buildTable(path, links)} | ||
</div> | ||
</div> | ||
</body> | ||
</html> | ||
` | ||
} | ||
|
||
exports = module.exports | ||
exports.render = render |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* global Response */ | ||
|
||
'use strict' | ||
|
||
const fileType = require('file-type') | ||
const mimeTypes = require('mime-types') | ||
const stream = require('stream') | ||
const nodeToWebStream = require('readable-stream-node-to-web') | ||
|
||
const resolver = require('./resolver') | ||
const pathUtils = require('./utils/path') | ||
|
||
const header = (status = 200, statusText = 'OK', headers = {}) => ({ | ||
status, | ||
statusText, | ||
headers | ||
}) | ||
|
||
module.exports = (ipfsNode, ipfsPath) => { | ||
// handle hash resolve error (simple hash, test for directory now) | ||
const handleResolveError = (node, path, error) => { | ||
if (error) { | ||
const errorString = error.toString() | ||
|
||
return new Promise((resolve, reject) => { | ||
// switch case with true feels so wrong. | ||
switch (true) { | ||
case (errorString === 'Error: This dag node is a directory'): | ||
resolver.directory(node, path, error.fileName) | ||
.then((content) => { | ||
// dir render | ||
if (typeof content === 'string') { | ||
resolve(new Response(content, header(200, 'OK', { 'Content-Type': 'text/html' }))) | ||
} | ||
|
||
// redirect to dir entry point (index) | ||
resolve(Response.redirect(pathUtils.joinURLParts(path, content[0].name))) | ||
}) | ||
.catch((error) => { | ||
resolve(new Response(errorString, header(500, error.toString()))) | ||
}) | ||
break | ||
case errorString.startsWith('Error: no link named'): | ||
resolve(new Response(errorString, header(404, errorString))) | ||
break | ||
case errorString.startsWith('Error: multihash length inconsistent'): | ||
case errorString.startsWith('Error: Non-base58 character'): | ||
resolve(new Response(errorString, header(400, errorString))) | ||
break | ||
default: | ||
resolve(new Response(errorString, header(500, errorString))) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
// remove trailing slash for files if needed | ||
if (ipfsPath.endsWith('/')) { | ||
resolve(Response.redirect(pathUtils.removeTrailingSlash(ipfsPath))) | ||
} | ||
|
||
resolver.multihash(ipfsNode, ipfsPath) | ||
.then((resolvedData) => { | ||
const readableStream = ipfsNode.files.catReadableStream(resolvedData.multihash) | ||
const responseStream = new stream.PassThrough({ highWaterMark: 1 }) | ||
readableStream.pipe(responseStream) | ||
|
||
readableStream.once('error', (error) => { | ||
if (error) { | ||
resolve(new Response(error.toString(), header(500, 'Service Worker Error'))) | ||
} | ||
}) | ||
|
||
// return only after first chunk being checked | ||
let filetypeChecked = false | ||
readableStream.on('data', (chunk) => { | ||
// check mime on first chunk | ||
if (filetypeChecked) { | ||
return | ||
} | ||
filetypeChecked = true | ||
// return Response with mime type | ||
const fileSignature = fileType(chunk) | ||
const mimeType = mimeTypes.lookup(fileSignature ? fileSignature.ext : null) | ||
|
||
if (mimeType) { | ||
resolve( | ||
new Response(typeof ReadableStream === 'function' ? nodeToWebStream(responseStream) : responseStream, | ||
header(200, 'OK', { 'Content-Type': mimeTypes.contentType(mimeType) })) | ||
) | ||
} else { | ||
resolve(new Response(typeof ReadableStream === 'function' ? nodeToWebStream(responseStream) : responseStream, | ||
header())) | ||
} | ||
}) | ||
}) | ||
.catch((error) => { | ||
resolve(handleResolveError(ipfsNode, ipfsPath, error)) | ||
}) | ||
}) | ||
} |
Oops, something went wrong.