Skip to content
This repository has been archived by the owner on Sep 28, 2021. It is now read-only.

fix: update module #104

Merged
merged 4 commits into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ typings/
# while testing npm5
package-lock.json
yarn.lock
types
30 changes: 24 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,32 @@
"description": "Creates an HTTP response from an IPFS Hash",
"leadMaintainer": "Vasco Santos <vasco.santos@moxy.studio>",
"main": "src/index.js",
"types": "./types/src/index.d.ts",
"type": "module",
"eslintConfig": {
"extends": "ipfs",
"parserOptions": {
"sourceType": "module"
}
},
"exports": {
".": {
"import": "./src/index.js"
}
},
"scripts": {
"lint": "aegir lint",
"prepare": "aegir build --no-bundle && cp -R types dist",
"lint": "aegir ts -p check && aegir lint",
"build": "aegir build",
"release": "aegir release --target node",
"release-minor": "aegir release --type minor --target node",
"pretest": "aegir build --esm-tests",
"test": "aegir test -t node",
"test:node": "aegir test -t node"
},
"browser": {
"file-type": "file-type/browser"
"file-type": "file-type/browser",
"fs": false
},
"repository": {
"type": "git",
Expand All @@ -32,8 +48,9 @@
"homepage": "https://github.com/ipfs/js-ipfs-http-response#readme",
"dependencies": {
"debug": "^4.3.1",
"ejs": "^3.1.6",
"file-type": "^16.0.0",
"filesize": "^7.0.0",
"filesize": "^8.0.0",
"it-buffer": "^0.1.1",
"it-concat": "^2.0.0",
"it-reader": "^3.0.0",
Expand All @@ -43,13 +60,14 @@
"p-try-each": "^1.0.1"
},
"devDependencies": {
"aegir": "^34.0.2",
"@types/ejs": "^3.1.0",
"aegir": "^35.0.3",
"get-stream": "^6.0.0",
"ipfs-core": "^0.9.1",
"ipfs-core": "^0.10.5",
"ipfsd-ctl": "^10.0.1",
"it-all": "^1.0.5",
"path": "^0.12.7",
"uint8arrays": "^2.0.5",
"uint8arrays": "^3.0.0",
"util": "^0.12.3"
},
"contributors": [
Expand Down
135 changes: 65 additions & 70 deletions src/dir-view/index.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,76 @@
'use strict'

const filesize = require('filesize')

const mainStyle = require('./style')
const pathUtil = require('../utils/path')
import filesize from 'filesize'
import style from './style.js'
import { cidArray } from '../utils/path.js'
import ejs from 'ejs'

/**
* @param {string} path
*/
function getParentHref (path) {
const parts = pathUtil.cidArray(path).slice()
const parts = cidArray(path).slice()
if (parts.length > 1) {
// drop the last segment in a safe way that works for both paths and urls
return path.replace(`/${parts.pop()}`, '')
}
return path
}

function buildFilesList (path, links) {
const rows = links.map((link) => {
let row = [
'<div class="ipfs-icon ipfs-_blank">&nbsp;</div>',
`<a href="${path}${path.endsWith('/') ? '' : '/'}${link.Name}">${link.Name}</a>`,
filesize(link.Tsize)
]

row = row.map((cell) => `<td>${cell}</td>`).join('')

return `<tr>${row}</tr>`
})

return rows.join('')
}

function buildTable (path, links) {
return `
<table class="table table-striped">
<tbody>
<tr>
<td class="narrow">
<div class="ipfs-icon ipfs-_blank">&nbsp;</div>
</td>
<td class="padding">
<a href="${getParentHref(path)}">..</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>
/**
* @param {string} path
* @param {({ Name: string, Tsize: number })[]} links
*/
export function render (path, links) {
return ejs.render(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= path %></title>
<style>${style}</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>
<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>
`
<table class="table table-striped">
<tbody>
<tr>
<td class="narrow">
<div class="ipfs-icon ipfs-_blank">&nbsp;</div>
</td>
<td class="padding">
<a href="<%= parentHref %>">..</a>
</td>
<td></td>
</tr>
<% links.forEach(function (link) { %>
<tr>
<td><div class="ipfs-icon ipfs-_blank">&nbsp;</div></td>
<td><a href="<%= link.link %>"><%= link.name %></a></t>
<td><%= link.size %></td>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</div>
</body>
</html>
`, {
path,
links: links.map((link) => ({
name: link.Name,
size: filesize(link.Tsize),
link: `${path}${path.endsWith('/') ? '' : '/'}${link.Name}`
})),
parentHref: getParentHref(path)
})
}

exports.render = render
4 changes: 1 addition & 3 deletions src/dir-view/style.js

Large diffs are not rendered by default.

54 changes: 35 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/* global Response, Blob */

'use strict'

const toStream = require('it-to-stream')
const concat = require('it-concat')
const toBuffer = require('it-buffer')
const log = require('debug')('ipfs:http:response')

const resolver = require('./resolver')
const pathUtils = require('./utils/path')
const detectContentType = require('./utils/content-type')
// @ts-ignore no types
import toStream from 'it-to-stream'
import concat from 'it-concat'
// @ts-ignore no types
import toBuffer from 'it-buffer'
import debug from 'debug'
import * as ipfsResolver from './resolver.js'
import * as pathUtils from './utils/path.js'
import { detectContentType } from './utils/content-type.js'

const log = debug('ipfs:http:response')

// TODO: pass path and add Etag and X-Ipfs-Path + tests
const getHeader = (status = 200, statusText = 'OK', headers = {}) => ({
Expand All @@ -18,21 +19,27 @@ const getHeader = (status = 200, statusText = 'OK', headers = {}) => ({
headers
})

// handle hash resolve error (simple hash, test for directory now)
/**
* handle hash resolve error (simple hash, test for directory now)
*
* @param {*} node
* @param {string} path
* @param {*} error
*/
const handleResolveError = async (node, path, error) => {
const errorString = error.toString()

if (errorString.includes('dag node is a directory')) {
try {
const content = await resolver.directory(node, path, error.cid)
const content = await ipfsResolver.directory(node, path, error.cid)
// dir render
if (typeof content === 'string') {
return new Response(content, getHeader(200, 'OK', { 'Content-Type': 'text/html' }))
}

// redirect to dir entry point (index)
return Response.redirect(pathUtils.joinURLParts(path, content[0].Name))
} catch (error) {
} catch (/** @type {any} */ error) {
log(error)
return new Response(errorString, getHeader(500, error.toString()))
}
Expand All @@ -49,14 +56,20 @@ const handleResolveError = async (node, path, error) => {
return new Response(errorString, getHeader(500, errorString))
}

const getResponse = async (ipfsNode, ipfsPath) => {
/**
*
* @param {*} ipfsNode
* @param {*} ipfsPath
* @returns
*/
export async function getResponse (ipfsNode, ipfsPath) {
// remove trailing slash for files if needed
if (ipfsPath.endsWith('/')) {
return Response.redirect(pathUtils.removeTrailingSlash(ipfsPath))
}

try {
const resolvedData = await resolver.cid(ipfsNode, ipfsPath)
const resolvedData = await ipfsResolver.cid(ipfsNode, ipfsPath)
const { source, contentType } = await detectContentType(ipfsPath, ipfsNode.cat(resolvedData.cid))

if (typeof Blob === 'undefined') {
Expand All @@ -74,7 +87,7 @@ const getResponse = async (ipfsNode, ipfsPath) => {
return contentType
? new Response(blob, getHeader(200, 'OK', { 'Content-Type': contentType }))
: new Response(blob, getHeader())
} catch (err) {
} catch (/** @type {any} */ err) {
return new Response(err.toString(), getHeader(500, 'Error fetching the file'))
}
} catch (error) {
Expand All @@ -83,7 +96,10 @@ const getResponse = async (ipfsNode, ipfsPath) => {
}
}

module.exports = {
getResponse,
resolver
export const resolver = {
...ipfsResolver
}

export const utils = {
detectContentType
}
Loading