storage-upload/test/helper.client.mjs
Jonatan Nilsson 68eef3a6b6 Complete refactor, features and optimization of code
Removed large amount of dependencies.
Added vips support and automatically resizing based on any criteria.
Faster and leaner.
Added ability to fetch listing of files in folders.
2022-01-05 14:47:51 +00:00

169 lines
4.8 KiB
JavaScript

import http from 'http'
import fs from 'fs/promises'
import path from 'path'
import { URL } from 'url'
import defaults from '../api/defaults.mjs'
import config from '../api/config.mjs'
export default function Client(port = config.get('server:port'), opts) {
this.options = defaults(opts, {})
this.prefix = `http://localhost:${port}`
}
Client.prototype.customRequest = function(method = 'GET', path, body, options) {
if (path.slice(0, 4) !== 'http') {
path = this.prefix + path
}
let urlObj = new URL(path)
return new Promise((resolve, reject) => {
const opts = defaults(defaults(options, {
method: method,
timeout: 500,
protocol: urlObj.protocol,
username: urlObj.username,
password: urlObj.password,
host: urlObj.hostname,
port: Number(urlObj.port),
path: urlObj.pathname + urlObj.search,
}))
const req = http.request(opts)
if (body) {
req.write(body)
}
req.on('error', reject)
req.on('timeout', function() { reject(new Error(`Request ${method} ${path} timed out`)) })
req.on('response', res => {
res.setEncoding('utf8')
let output = ''
res.on('data', function (chunk) {
output += chunk.toString()
})
res.on('end', function () {
try {
output = JSON.parse(output)
} catch (e) {
return reject(new Error(`${e.message} while decoding: ${output}`))
}
if (output.status) {
let err = new Error(`Request failed [${output.status}]: ${output.message}`)
err.body = output
err.status = output.status
return reject(err)
}
resolve(output)
})
})
req.end()
})
}
Client.prototype.get = function(url = '/') {
return this.customRequest('GET', url, null)
}
const random = (length = 8) => {
// Declare all characters
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
// Pick characers randomly
let str = '';
for (let i = 0; i < length; i++) {
str += chars.charAt(Math.floor(Math.random() * chars.length));
}
return str;
}
Client.prototype.upload = function(url, file, method = 'POST', body = {}) {
return fs.readFile(file).then(data => {
const crlf = '\r\n'
const filename = path.basename(file)
const boundary = `---------${random(32)}`
const multipartBody = Buffer.concat([
Buffer.from(
`${crlf}--${boundary}${crlf}` +
`Content-Disposition: form-data; name="file"; filename="${filename}"` + crlf + crlf
),
data,
Buffer.concat(Object.keys(body).map(function(key) {
return Buffer.from(''
+ `${crlf}--${boundary}${crlf}`
+ `Content-Disposition: form-data; name="${key}"` + crlf + crlf
+ JSON.stringify(body[key])
)
})),
Buffer.from(`${crlf}--${boundary}--`),
])
return this.customRequest(method, url, multipartBody, {
timeout: 5000,
headers: {
'Content-Type': 'multipart/form-data; boundary=' + boundary,
'Content-Length': multipartBody.length,
},
})
})
}
/*
export function createClient(host = config.get('server:port'), opts) {
let options = defaults(opts, {})
let prefix = `http://localhost:${host}`
options.headers['x-request-id'] = 'asdf'
client.auth = (user) => {
// let m = helperDB.model('user', {
// id: user.id,
// level: (user.get && user.get('level')) || 1,
// institute_id: (user.get && user.get('institute_id')) || null,
// password: (user.get && user.get('password')) || null,
// })
// let token = jwt.createUserToken(m)
// client.headers.authorization = `Bearer ${token}`
}
// Simple wrappers to wrap into promises
client.getAsync = (path) =>
new Promise((resolve, reject) => {
if (path.slice(0, 4) === 'http') {
return client.get(path, callback(resolve, reject))
}
client.get(prefix + path, callback(resolve, reject))
})
// Simple wrappers to wrap into promises
client.saveFileAsync = (path, destination) =>
new Promise((resolve, reject) => {
client.saveFile(prefix + path, destination, callback(resolve, reject, true))
})
client.postAsync = (path, data) =>
new Promise((resolve, reject) => {
client.post(prefix + path, data, callback(resolve, reject))
})
client.putAsync = (path, data) =>
new Promise((resolve, reject) => {
client.put(prefix + path, data, callback(resolve, reject))
})
client.deleteAsync = (path) =>
new Promise((resolve, reject) => {
client.del(prefix + path, callback(resolve, reject))
})
client.sendFileAsync = (path, files, data) =>
new Promise((resolve, reject) => {
client.sendFile(prefix + path, files, data || {}, callback(resolve, reject))
})
return client
}
*/