diff --git a/.github/workflows/master-latest.yml b/.github/workflows/master-latest.yml index e799d85..126377d 100644 --- a/.github/workflows/master-latest.yml +++ b/.github/workflows/master-latest.yml @@ -44,7 +44,7 @@ jobs: platforms: linux/amd64 #,linux/arm64 pull: true # avoid bitrot with repeated cache hits push: true - tags: ghcr.io/${{ github.repository_owner }}/ansi-hastebin:latest,ghcr.io/${{ github.repository_owner }}/ansi-hastebin:0.0.1 # @TODO: read from package.json + tags: ghcr.io/${{ github.repository_owner }}/ansi-hastebin:latest,ghcr.io/${{ github.repository_owner }}/ansi-hastebin:0.0.2 # @TODO: read from package.json labels: | org.opencontainers.image.title=ansi-hastebin org.opencontainers.image.description=${{ github.event.repository.description }} diff --git a/lib/document_handler.js b/lib/document_handler.js index ce31986..9cc3da8 100644 --- a/lib/document_handler.js +++ b/lib/document_handler.js @@ -132,6 +132,72 @@ DocumentHandler.prototype.handlePost = function (request, response) { } }; +// Handle adding a new Document +DocumentHandler.prototype.handlePutLog = function (request, response) { + const _this = this; + let buffer = ''; + let cancelled = false; + + // What to do when done + const onSuccess = function () { + // Check length + if (_this.maxLength && buffer.length > _this.maxLength) { + cancelled = true; + winston.warn('document >maxLength', {maxLength: _this.maxLength}); + response.writeHead(400, {'content-type': 'application/json'}); + response.end(JSON.stringify({message: 'Document exceeds maximum length.'})); + return; + } + // And then save if we should + _this.chooseKey(function (key) { + _this.store.set(key, buffer, function (res) { + if (res) { + winston.verbose('added document', {key: key}); + response.writeHead(200, {'content-type': 'text/plain'}); + let logUrl = "https://" + request.headers['host'] + "/" + key; + response.end("\n" + logUrl + "\n\n"); + } else { + winston.verbose('error adding document'); + response.writeHead(500, {'content-type': 'application/json'}); + response.end(JSON.stringify({message: 'Error adding document.'})); + } + }); + }); + }; + + // If we should, parse a form to grab the data + const ct = request.headers['content-type']; + if (ct && ct.split(';')[0] === 'multipart/form-data') { + const busboy = new Busboy({headers: request.headers}); + busboy.on('field', function (field_name, val) { + if (field_name === 'data') { + buffer = val; + } + }); + busboy.on('finish', function () { + onSuccess(); + }); + request.pipe(busboy); + // Otherwise, use our own and just grab flat data from POST body + } else { + request.on('data', function (data) { + buffer += data.toString(); + }); + request.on('end', function () { + if (cancelled) { + return; + } + onSuccess(); + }); + request.on('error', function (error) { + winston.error('connection error: ' + error.message); + response.writeHead(500, {'content-type': 'application/json'}); + response.end(JSON.stringify({message: 'Connection error.'})); + cancelled = true; + }); + } +}; + // Keep choosing keys until one isn't taken DocumentHandler.prototype.chooseKey = function (callback) { const key = this.acceptableKey(); diff --git a/server.js b/server.js index c44373e..a96aa42 100644 --- a/server.js +++ b/server.js @@ -119,6 +119,15 @@ app.use(route(function (router) { return documentHandler.handleRawGet(request, response, config); }); + // add logs, via PUT and POST, for scripting + router.post('/log', function (request, response) { + return documentHandler.handlePutLog(request, response); + }); + router.put('/log', function (request, response) { + return documentHandler.handlePutLog(request, response); + }); + + // add documents router.post('/documents', function (request, response) {