From 3c61200f80e9d66ef3e74880977baf22f0648eaf Mon Sep 17 00:00:00 2001 From: OKNoah Date: Fri, 19 Aug 2016 17:45:33 -0700 Subject: [PATCH 1/3] Adds koa route --- README.md | 18 +++++++- s3router-koa.js | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 s3router-koa.js diff --git a/README.md b/README.md index f4a8a43..6c4e574 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,11 @@ function getSignedUrl(file, callback) { Server-Side ----------- -### Bundled router +### Bundled routers You can use the Express router that is bundled with this module to answer calls to `/s3/sign` +#### Express + ```js app.use('/s3', require('react-s3-uploader/s3router')({ bucket: "MyS3Bucket", @@ -111,7 +113,19 @@ app.use('/s3', require('react-s3-uploader/s3router')({ })); ``` -This also provides another endpoint: `GET /s3/img/(.*)` and `GET /s3/uploads/(.*)`. This will create a temporary URL +# Koa 1.0 + +```js +import s3router from 'react-s3-uploader/s3router'; + +app.use(require('react-s3-uploader/s3router')({ + /* Same as above with these additional options: */ + endpoint: 'https://rest.s3alternative.com', // optional. useful for s3-compatible APIs + prefix: '/v1/s3' // optional. default is /s3. useful if you version your API endpoints +})); +``` + +These also provide another endpoint: `GET /s3/img/(.*)` and `GET /s3/uploads/(.*)`. This will create a temporary URL that provides access to the uploaded file (which are uploaded privately by default). The request is then redirected to the URL, so that the image is served to the client. diff --git a/s3router-koa.js b/s3router-koa.js new file mode 100644 index 0000000..fc13397 --- /dev/null +++ b/s3router-koa.js @@ -0,0 +1,111 @@ +import Router from 'koa-router'; +import uuid from 'node-uuid'; +import AWS from 'aws-sdk'; + +const { S3_ACCESS_KEY, S3_SECRET_ACCESS_KEY, S3_ENDPOINT } = process.env; + +function checkTrailingSlash (path) { + let newPath; + + if (path && path[path.length - 1] !== '/') { + newPath = path + '/'; + } + + return newPath; +} + +export default function S3Router (options) { + const S3_BUCKET = options.bucket; + + if (!S3_BUCKET) { + throw new Error('S3_BUCKET is required.'); + } + + const s3Options = {}; + if (options.region) { + s3Options.region = options.region; + } + if (options.signatureVersion) { + s3Options.signatureVersion = options.signatureVersion; + } + if (options.endpoint) { + s3Options.endpoint = options.endpoint; + } + + const s3 = new AWS.S3({ + ...s3Options, + accessKeyId: S3_ACCESS_KEY, + secretAccessKey: S3_SECRET_ACCESS_KEY, + endpoint: S3_ENDPOINT + }); + + const router = new Router({ + prefix: options.prefix || 's3' + }); + + /** + * Redirects image requests with a temporary signed URL, giving access + * to GET an upload. + */ + function * tempRedirect() { + const self = this; + + const params = { + Bucket: S3_BUCKET, + Key: options.key + }; + + s3.getSignedUrl('getObject', params, function (err, url) { + self.redirect(url); + }); + } + + /** + * Image specific route. + */ + router.get(/\/img\/(.*)/, tempRedirect); + + /** + * Other file type(s) route. + */ + router.get(/\/uploads\/(.*)/, tempRedirect); + + /** + * Returns an object with `signedUrl` and `publicUrl` properties that + * give temporary access to PUT an object in an S3 bucket. + */ + router.get('/sign', function * () { + const self = this; + const filename = uuid.v4() + '_' + this.query.objectName; + const mimeType = this.query.contentType; + + // Set any custom headers + if (options.headers) { + this.set(options.headers); + } + + const params = { + Bucket: S3_BUCKET, + Key: options.key, + Expires: 60, + ContentType: mimeType, + ACL: options.ACL || 'private' + }; + + s3.getSignedUrl('putObject', params, function (err, data) { + if (err) { + console.log(err); + self.status = 500; + self.body = 'Cannot create S3 signed URL'; + } + + self.body = { + signedUrl: data, + publicUrl: '/s3/uploads/' + filename, + filename + }; + }); + }); + + return router.routes(); +} From 3efcaa86cf8b8df5927928f571375ade3d13b0f8 Mon Sep 17 00:00:00 2001 From: OKNoah Date: Fri, 19 Aug 2016 17:48:43 -0700 Subject: [PATCH 2/3] Adds dependency --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f56468..8c1bb23 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,10 @@ "homepage": "https://github.com/odysseyscience/react-s3-uploader", "dependencies": { "aws-sdk": "2.x", + "koa-router": "^5.4.0", + "latinize": "0.2.x", "node-uuid": "1.x", "object-assign": "^2.0.0", - "latinize": "0.2.x", "unorm": "1.4.x" }, "peerDependencies": { From 92a6e0138f76fce85450abc0acef250b09f8c654 Mon Sep 17 00:00:00 2001 From: OKNoah Date: Sat, 20 Aug 2016 08:40:24 -0700 Subject: [PATCH 3/3] Fixes Keys Did not understand how they worked before --- s3router-koa.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s3router-koa.js b/s3router-koa.js index fc13397..eba3cce 100644 --- a/s3router-koa.js +++ b/s3router-koa.js @@ -86,7 +86,7 @@ export default function S3Router (options) { const params = { Bucket: S3_BUCKET, - Key: options.key, + Key: checkTrailingSlash(options.key) + filename, Expires: 60, ContentType: mimeType, ACL: options.ACL || 'private'