From 4d62f6fec6750b765fb25aa76cf97eb40d95949d Mon Sep 17 00:00:00 2001 From: gsuess Date: Sun, 21 Dec 2014 14:27:29 +0100 Subject: [PATCH] #17: Standardized CDN directive parameter to all services and readme cleanup. --- README.md | 66 ++++++++++++++++++++++++---------------- lib/directive.js | 3 +- services/aws-s3.js | 32 ++++++++++--------- services/google-cloud.js | 17 ++++------- services/rackspace.js | 3 +- 5 files changed, 64 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 0947453..13c84c1 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,8 @@ Meteor core packages: ### Directives +#### General + `authorize`: Function (required) - Function to determines if upload is allowed. `maxSize`: Number (required) - Maximum file-size (in bytes). Use `null` or `0` @@ -265,40 +267,41 @@ for unlimited. `allowedFileTypes` RegExp, String or Array (required) - Allowed MIME types. Use null for any file type. **Warning: This is not enforced on rackspace** -`cacheControl` String (optional) - RFC 2616 Cache-Control directive +`cdn` String (optional) - CDN URL domain for downloads. +i.e. `"https://d111111abcdef8.cloudfront.net"` -`contentDisposition` String (required) - RFC 2616 Content-Disposition directive. -Default is the uploaded file's name (inline). Use null to disable. +`expire` Number (optional) - Number of milliseconds in which an upload +authorization will expire after the request was made. Default is 5 minutes. -`bucket` String (required for Google Cloud and AWS S3) - Name of bucket to use. +#### AWS S3 and Google Cloud + +`bucket` String (required) - Name of bucket to use. For Google Cloud the default is `Meteor.settings.GoogleCloudBucket`. For AWS S3 the default bucket is `Meteor.settings.S3Bucket`. -`container` String (required for Rackspace Cloud files) - Name of container to -use. +`bucketUrl` String or Function (optional) - Override URL to which files are + uploaded. If it is a function, then the first argument is the bucket name. This + url also used for downloads unless a cdn is given. -`domain` String (optional) - Override domain to use to access bucket. +`key` String or Function (required) - Name of the file on the cloud storage +service. If a function is provided, it will be called with `userId` in the +context and its return value is used as the key. First argument is file info and +the second is the meta-information that can be passed by the client. -`cdn` String (required for rackspace cloud files) - CDN domain for downloads. +`acl` String (optional) -`key` String or Function (required for AWS S3 and Google Cloud) - Name of the -file on the cloud storage service. If a function is provided, it will be called -with `userId` in the context and its return value is used as the key. +`cacheControl` String (optional) - RFC 2616 Cache-Control directive -`pathPrefix` String or Function (required for Rackspace Cloud Files) - Prefix or -directory in which files are stored. The rest is taken from the uploaded file's -name and cannot be enforced. +`contentDisposition` String (required) - RFC 2616 Content-Disposition directive. +Default is the uploaded file's name (inline). Use null to disable. -`expire` Number (optional) - Number of milliseconds in which an upload -authorization will expire after the request was made. Default is 5 minutes. +#### AWS S3 specific -`acl` String (optional) +`AWSAccessKeyId` String (required) - Can also be set in `Meteor.settings` -`AWSAccessKeyId` String (required for AWS S3) - Can also be set in -`Meteor.settings` +`AWSSecretAccessKey` String (require) - Can also be set in `Meteor.settings` -`AWSSecretAccessKey` String (required for AWS S3) - Can also be set in -`Meteor.settings` +#### Google Cloud Storage specific `GoogleAccessId` String (required for Google Cloud Storage) - Can also be set in `Meteor.settings` @@ -306,11 +309,20 @@ authorization will expire after the request was made. Default is 5 minutes. `GoogleSecretKey` String (required for Google Cloud Storage) - Can also be set in `Meteor.settings` -`RackspaceAccountId` String (required for rackspace cloud files) - This is your -rackspace account number. It can also be set set in `Meteor.settings` +#### Rackspace Cloud Files + +`container` String (required) - Name of container to use. + +`region` String (optional) - The region used by your container. The default is +`iad3`. + +`pathPrefix` String or Function (required) - Prefix or directory in which files + are stored. The rest is taken from the uploaded file's name and cannot be + enforced. + +`RackspaceAccountId` String (required) - This is your rackspace account number. +It can also be set set in `Meteor.settings`. + +`RackspaceSecretKey` String (required) - Can also be set in `Meteor.settings` -`RackspaceSecretKey` String (required for rackspace cloud files) - Can also be -set in `Meteor.settings` -`region` String (optional for rackspace cloud files) - The region used by your -container. The default is `iad3`. diff --git a/lib/directive.js b/lib/directive.js index 5a5eefa..c5ba920 100644 --- a/lib/directive.js +++ b/lib/directive.js @@ -119,8 +119,7 @@ Slingshot.Directive = function (service, directive) { authorize: Function, maxSize: Match.OneOf(Number, null), allowedFileTypes: matchAllowedFileTypes, - cacheControl: Match.Optional(String), - contentDisposition: Match.Optional(Match.OneOf(String, null)) + cdn: Match.Optional(String) }, service.directiveMatch)); /** diff --git a/services/aws-s3.js b/services/aws-s3.js index 414e451..ee23862 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -7,7 +7,7 @@ Slingshot.S3Storage = { directiveMatch: { bucket: String, - domain: Match.Optional(String), + bucketUrl: Match.OneOf(String, Function), AWSAccessKeyId: String, AWSSecretAccessKey: String, @@ -32,22 +32,23 @@ Slingshot.S3Storage = { check(expire, Number); return expire > 0; - }) + }), + + cacheControl: Match.Optional(String), + contentDisposition: Match.Optional(Match.OneOf(String, null)) }, directiveDefault: _.chain(Meteor.settings) .pick("AWSAccessKeyId", "AWSSecretAccessKey") .extend({ bucket: Meteor.settings.S3Bucket, + bucketUrl: function (bucket) { + return "https://" + bucket + ".s3.amazonaws.com" + }, expire: 5 * 60 * 1000 //in 5 minutes }) .value(), - - host: function (directive) { - return directive.bucket + ".s3.amazonaws.com"; - }, - /** * * @param {{userId: String}} method @@ -60,6 +61,7 @@ Slingshot.S3Storage = { upload: function (method, directive, file, meta) { var url = Npm.require("url"), + policy = new Slingshot.StoragePolicy() .expireIn(directive.expire) .contentLength(0, Math.min(file.size, directive.maxSize || Infinity)), @@ -76,21 +78,21 @@ Slingshot.S3Storage = { "Cache-Control": directive.cacheControl, "Content-Disposition": directive.contentDisposition }, - domain = { - protocol: "https", - host: directive.domain || this.host(directive), - pathname: payload.key - }; + bucketUrl = _.isFunction(directive.bucketUrl) ? + directive.bucketUrl(directive.bucket) : directive.bucketUrl, - payload[this.accessId] = directive[this.accessId]; + download = _.extend(url.parse(directive.cdn || bucketUrl), { + pathname: payload.key + }); + payload[this.accessId] = directive[this.accessId]; payload.policy = policy.match(_.omit(payload, this.accessId)).stringify(); payload.signature = this.sign(directive[this.secretKey], payload.policy); return { - upload: url.format(_.omit(domain, "pathname")), - download: url.format(domain), + upload: bucketUrl, + download: url.format(download), postData: [{ name: "key", value: payload.key diff --git a/services/google-cloud.js b/services/google-cloud.js index 2f0c95b..245ac84 100644 --- a/services/google-cloud.js +++ b/services/google-cloud.js @@ -1,4 +1,4 @@ -//GoogleCloud is based on the very same method as AWS S3, so we extend it: +//GoogleCloud is based on the very same api as AWS S3, so we extend it: Slingshot.GoogleCloud = _.defaults({ @@ -29,19 +29,14 @@ Slingshot.GoogleCloud = _.defaults({ directiveDefault: _.chain(Meteor.settings) .pick("GoogleAccessId") - .extend(Slingshot.S3Storage.directiveDefault) + .extend(Slingshot.S3Storage.directiveDefault, { + bucketUrl: function (bucket) { + return "https://" + bucket + ".storage.googleapis.com"; + } + }) .omit(Slingshot.S3Storage.accessId, Slingshot.S3Storage.secretKey) .value(), - /** - * @param {Directive} directive - * @returns {string} - */ - - host: function (directive) { - return directive.bucket + ".storage.googleapis.com"; - }, - /** * @param {String} secretKey - pem private key * @param {String} policy diff --git a/services/rackspace.js b/services/rackspace.js index de47faa..480e4a5 100644 --- a/services/rackspace.js +++ b/services/rackspace.js @@ -5,7 +5,6 @@ Slingshot.RackspaceFiles = { RackspaceSecretKey: String, container: String, region: String, - cdn: String, pathPrefix: Match.OneOf(String, Function), expire: Match.Where(function (expire) { check(expire, Number); @@ -89,7 +88,7 @@ Slingshot.RackspaceFiles = { return { upload: url, - download: directive.cdn + path + "/" + file.name, + download: (directive.cdn || host) + path + "/" + file.name, postData: data }; },