-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
149 lines (137 loc) · 3.68 KB
/
index.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
var fs = require('fs')
const helmet = require('helmet')
const util = require('util')
const readFile = util.promisify(fs.readFile)
const condis = require('content-disposition')
var nano = require('nano')
var express = require('express')
var mime = require('mime')
var multer = require('multer')
var upload = multer({ dest: '/tmp' })
const { path, propOr, merge } = require('ramda')
/**
* couchFS
*
* CouchFS is a file server based middleware for expressJS
*
* @param {object} config - configuration object for nano couchdb connection see https://github.com/apache/couchdb-nano#configuration
*
*/
module.exports = function(config) {
var app = express()
var server, db
if (config.couch && !config.request_defaults) {
db = nano(config.couch)
} else if (config.request_defaults) {
server = nano({
url: config.url,
request_defaults: config.request_defaults
})
db = config.database_parameter_name || 'COUCH_DB'
} else {
server = nano(config.url)
db = config.database_parameter_name || 'COUCH_DB'
}
/**
* getDb
*
* returns current db or grabs db from request
*
* @param {object} req - express request object
*/
function getDb(req) {
if (typeof db === 'object') {
return db
} else {
return server.use(req[db])
}
}
// helmet adds some security protection for express api servers
app.use(helmet())
/**
* @swagger
* /{name}:
* get:
* description: Downloads file, inline or as attachment
* responses:
* 200:
* description: successful response
*/
app.get('/:name', async function(req, res) {
var disposition = req.query.inline ? 'inline' : 'attachment'
const db = getDb(req)
const doc = await db
.get(req.params.name)
.catch(() => ({ name: 'file not found' }))
if (path(['_attachments', 'file'], doc)) {
const s = db.attachment.getAsStream(req.params.name, 'file')
s.on('response', function(res) {
res.headers = merge(res.headers, {
'Content-Type': propOr(
mime.getType(doc.name) || 'application/octlet-stream',
'mime',
doc
),
'Content-Disposition': condis(doc.name, { type: disposition })
})
})
s.on('error', e => {})
s.pipe(res)
} else {
return res.status(404).send({ error: 'file not found' })
}
})
/**
* @swagger
* /:
* post:
* description: Uploads file as an attachment to couchdb
* responses:
* 200:
* description: successful response
*/
app.post('/', upload.single('uploadFile'), async function(req, res) {
var meta = {
name: req.file.originalname,
type: 'file',
mime: mime.getType(req.file.originalname),
size: req.file.size
}
var filename = req.file.originalname
const db = getDb(req)
try {
const doc = await db.insert(meta)
const data = await readFile(req.file.path)
const response = await db.attachment.insert(
doc.id,
'file',
data,
meta.mime,
{ rev: doc.rev }
)
res.send(response)
} catch (err) {
res.status(500).send({ ok: false, error: err.message })
}
})
/**
* @swagger
* /:
* delete:
* description: removes couchdb document
* responses:
* 200:
* description: successful response
*/
app.delete('/:name', async function(req, res) {
try {
const db = getDb(req)
const doc = await db.get(req.params.name)
const response = await db.destroy(req.params.name, doc._rev)
res.send(response)
} catch (err) {
res.status(500).send({ error: err.message })
}
})
return app
}