From df96536d1af5b96271f6a34e10ab568a46b1251d Mon Sep 17 00:00:00 2001 From: Hakan Ensari Date: Sat, 4 Feb 2012 03:41:39 +0000 Subject: [PATCH] Add request without signature --- lib/vacuum/index.js | 1 + lib/vacuum/request.coffee | 65 ++++++++++++++++++++++++++++- lib/vacuum/response.coffee | 2 +- package.json | 3 +- spec/vacuum-spec.coffee | 6 --- spec/vacuum/request-spec.coffee | 72 +++++++++++++++++++++++++++++++++ 6 files changed, 140 insertions(+), 9 deletions(-) delete mode 100644 spec/vacuum-spec.coffee create mode 100644 spec/vacuum/request-spec.coffee diff --git a/lib/vacuum/index.js b/lib/vacuum/index.js index 363ff00..b7af468 100644 --- a/lib/vacuum/index.js +++ b/lib/vacuum/index.js @@ -1,3 +1,4 @@ require('coffee-script'); +require('underscore'); module.exports = require('./request'); diff --git a/lib/vacuum/request.coffee b/lib/vacuum/request.coffee index 8cd920c..060d622 100644 --- a/lib/vacuum/request.coffee +++ b/lib/vacuum/request.coffee @@ -1,4 +1,67 @@ +_ = require 'underscore' +http = require 'http' +Response = require './response' + class Request - constructor: -> + constructor: (options) -> + @_key = options.key or throw 'Missing key' + @_secret = options.secret or throw 'Missing secret' + @_tag = options.tag or throw 'Missing associate tag' + @_host = { + ca: 'ecs.amazonaws.ca', + cn: 'webservices.amazon.cn', + de: 'ecs.amazonaws.de', + es: 'webservices.amazon.es', + fr: 'ecs.amazonaws.fr', + it: 'webservices.amazon.it', + jp: 'ecs.amazonaws.jp', + uk: 'ecs.amazonaws.co.uk', + us: 'ecs.amazonaws.com' + }[options.locale or 'us'] or throw 'Bad locale' + @reset() + + add: (properties) -> + for key, value of properties + value = value.join(',') if value.constructor == Array + key = key[0].toUpperCase() + key.slice(1) + + @params[key] = value + + @ + + get: (callback) -> + options = + host: @_host + path: "/onca/xml?#{@_query()}" + + http.get options, (res) -> + data = '' + res.on 'data', (chunk) -> + data += chunk + .on 'end', -> + callback new Response(data, res.statusCode) + .on 'error', (error) -> + + reset: -> + @params = + AWSAccessKeyId : @_key + AssociateTag : @_tag + Service : 'AWSECommerceService' + Timestamp : new Date().toJSON() + Version : '2011-08-01' + + @ + + _query: -> + _ + .chain(@params) + .map (value, key) -> + [key, value] + .sortBy (tuple) -> + tuple[0] + .map (tuple) -> + "#{tuple[0]}=#{encodeURIComponent(tuple[1])}" + .value() + .join('&') module.exports = Request diff --git a/lib/vacuum/response.coffee b/lib/vacuum/response.coffee index ba3e2ae..7616796 100644 --- a/lib/vacuum/response.coffee +++ b/lib/vacuum/response.coffee @@ -1,4 +1,4 @@ class Response - constructor: -> + constructor: (data, statusCode) -> module.exports = Response diff --git a/package.json b/package.json index 632963b..0326d1f 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "url":"git://github.com/hakanensari/vacuum.git" }, "dependencies":{ - "coffee-script":"*" + "coffee-script":">= 1.0", + "underscore":">= 1.0" }, "devDependencies":{ "jasmine-node":"*" diff --git a/spec/vacuum-spec.coffee b/spec/vacuum-spec.coffee deleted file mode 100644 index fef08bc..0000000 --- a/spec/vacuum-spec.coffee +++ /dev/null @@ -1,6 +0,0 @@ -Vacuum = require '../lib/vacuum' - -describe 'Vacuum', -> - it 'returns a request', -> - req = new Vacuum - expect(typeof req).toBe 'object' diff --git a/spec/vacuum/request-spec.coffee b/spec/vacuum/request-spec.coffee new file mode 100644 index 0000000..21c16f6 --- /dev/null +++ b/spec/vacuum/request-spec.coffee @@ -0,0 +1,72 @@ +Request = require '../../lib/vacuum/request' + +describe 'Request', -> + beforeEach -> + @req = new Request + key: process.env.AMAZON_KEY + secret: process.env.AMAZON_SECRET + tag: process.env.AMAZON_TAG + + describe 'constructor', -> + it 'requires a key', -> + expect -> + new Request + secret: 'foo' + tag: ' bar' + .toThrow 'Missing key' + + it 'requires a secret', -> + expect -> + new Request + key: 'foo' + tag: 'bar' + .toThrow 'Missing secret' + + it 'requires an associate tag', -> + expect -> + new Request + key: 'foo' + secret: 'bar' + .toThrow 'Missing associate tag' + + it 'requires a valid locale', -> + expect -> + new Request + key: 'foo' + secret: 'bar' + tag: 'secret' + locale: 'invalid' + .toThrow 'Bad Locale' + + it 'defaults locale to the US', -> + expect(@req._host).toMatch /\.com/ + + it 'sets up the parameters with default values', -> + expect(@req.params.Timestamp).toBeDefined() + + describe '#add', -> + it 'adds new parameters to the existing ones', -> + expect(@req.add(foo: 'bar').params.Foo).toBe('bar') + + it 'casts values that are arrays to strings', -> + expect(@req.add(foo: [1, 2]).params.Foo).toBe('1,2') + + describe '#get', -> + it 'returns a response', -> + @req.get (res) -> + expect(res.constructor).toMatch /Response/ + + describe '#reset', -> + it 'resets the parameters to default values', -> + @req.params.foo = 1 + expect(@req.reset.foo).toBeUndefined() + + describe '#_query', -> + it 'sorts the parameters', -> + expect(@req.add(a: 0, z: 1)._query()).toMatch /^A=0&.*Z=1$/ + + it 'canonicalizes the parameters', -> + expect(@req._query()).toMatch /\w+=\w+&/ + + it 'URL-encodes values', -> + expect(@req.add(foo: 'bar,baz')._query()).toMatch /bar%2Cbaz/