minimal nip-96 file server behind tor
you can install this server on android phone, see below for instructions
upload
curl --socks5-hostname 127.0.0.1:9050 -X POST -H "Content-Type: multipart/form-data" -F "[email protected]" http://s6mn26rvxxoiezkh43e42on4nsnj2etpkvy7pjkj4rgpv7n5n4gjgqyd.onion/upload
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | const express = require('express')
const multer = require('multer')
const crypto = require('crypto')
const fs = require('fs/promises')
const fs_ = require('fs')
const path = require('path')
const upload = multer({ dest: 'uploads/' })
const app = express();
const port = 8000
// change hostname / baseurl if you are not using default termux + tor setup
const hostname = fs_.readFileSync("/data/data/com.termux/files/usr/var/lib/tor/hidden_service/hostname", "utf-8")
const baseurl = "http://" + hostname
function not_found(res){
res.send("404")
res.status(404)
}
app.get('/.well-known/nostr/nip96.json', async (req, res) => {
console.log("get /.well-known/nostr/nip96.json")
res.send({
"api_url": baseurl
})
})
app.post('/', upload.single('file'), async (req, res, next) => {
console.log("post /")
const file = req.file
if (!file) {
const error = new Error('Please upload a file')
error.httpStatusCode = 400
return next(error)
}
console.log("upload", file.originalname)
const fileBuffer = await fs.readFile(file.path);
const hashSum = crypto.createHash('sha256')
hashSum.update(fileBuffer)
const hash = hashSum.digest('hex')
const extension_match = file.originalname.match(/\.([a-z0-9]{1,4})$/)
const extension = extension_match && extension_match[1] || null
await fs.rename(file.path, "uploads/" + hash)
await fs.writeFile("uploads/" + hash + ".json", JSON.stringify({
originalname: file.originalname,
mimetype: file.mimetype,
extension: extension
}))
res.send(JSON.stringify({
status: "success",
message: "Upload successful",
nip94_event: {
tags: [
["url", baseurl + "/" + hash + "." + extension],
["ox", hash],
],
content: ""
}
}))
})
app.get('/', async (req, res) => {
console.log("get /")
res.send(
`<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
</head
<body>
<h1>nostr nip-96 filehosting</h1>
<p>curl --socks5-hostname 127.0.0.1:9050 -X POST -H "Content-Type: multipart/form-data" -F "[email protected] " ` + baseurl + `</p>
<p>
<a href="/.well-known/nostr/nip96.json">/.well-known/nostr/nip96.json</a>
</p>
</body>
</html>`
)
})
app.get('/:hash', async (req, res) => {
console.log("get", req.params.hash)
const match = req.params.hash.match(/^([^.]+)(\.([a-z0-9]+)|)$/)
const filename = "uploads/" + match[1] + ".json"
if(!match || !await fs_.existsSync(filename)){
return not_found(res)
}
try{
const info = JSON.parse(await fs.readFile(filename))
if(info.extension !== (match[3] || null)){
return not_found(res)
}
res.set("Content-Type", info.mimetype)
res.sendFile(path.join(__dirname, 'uploads/' + match[1]))
}catch(e){
console.log("info file does not exist for hash " + req.params.hash)
return not_found(res)
}
})
app.listen(port, () => {
console.log('Server is listening on port ' + port)
console.log("tor address is", baseurl)
})
|
install on android phone
you can install this server on android phone
first setup tor hidden service as instructed in this guide:
https://rentry.org/androidtor
after that:
create app.js with contents as above
pkg install nodejs
pkg install express
pkg install multer
node app.js