gister 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gister.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Eric Allam
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Gister
2
+
3
+ Gister provides a way to cache gister embed code, basically creating a middleware that acts like a reverse-proxy
4
+ to the gist.github.com api.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'gister'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install gister
19
+
20
+ ## Usage
21
+
22
+ ## Contributing
23
+
24
+ 1. Fork it
25
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
26
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
27
+ 4. Push to the branch (`git push origin my-new-feature`)
28
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/gister.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/gister/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Eric Allam"]
6
+ gem.email = ["rubymaverick@gmail.com"]
7
+ gem.description = %q{Provides a Middleware to cache embedded gist content}
8
+ gem.summary = %q{Provides a Middleware to cache embedded gist content}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "gister"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Gister::VERSION
17
+
18
+ gem.add_development_dependency "rspec"
19
+ gem.add_development_dependency "vcr", "~> 2.0.0"
20
+ gem.add_development_dependency "webmock"
21
+
22
+ gem.add_runtime_dependency "faraday", "0.6.1"
23
+ end
data/lib/gister.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'gister/railtie' if defined?(Rails)
2
+
3
+ module Gister
4
+ def self.fetcher
5
+ @fetcher ||= Fetcher.new
6
+ end
7
+ end
@@ -0,0 +1,72 @@
1
+ require 'faraday'
2
+
3
+ module Gister
4
+ class Fetcher
5
+ ClientError = Class.new(StandardError)
6
+ GistNotFound = Class.new(ClientError)
7
+
8
+ def initialize
9
+ @store = Hash.new
10
+ end
11
+
12
+ def fetch(key)
13
+ if result = get(key)
14
+ result
15
+ else
16
+ result = fetch_result(key)
17
+ set key, result
18
+ result
19
+ end
20
+ end
21
+
22
+ def get(key)
23
+ @store[key]
24
+ end
25
+
26
+ def set(key, value)
27
+ @store[key] = value
28
+ end
29
+
30
+ private
31
+
32
+ def fetch_result(key)
33
+ path, params = parse_uri(key)
34
+
35
+ wrap_exceptions do
36
+ response = connection.get(path) do |req|
37
+ req.params = params
38
+ end
39
+ response.body
40
+ end
41
+ end
42
+
43
+ def wrap_exceptions
44
+ yield
45
+ rescue Faraday::Error::ResourceNotFound
46
+ raise GistNotFound.new($!)
47
+ rescue Faraday::Error::ClientError
48
+ raise ClientError.new($1)
49
+ end
50
+
51
+ def connection
52
+ @connection ||= Faraday.new(url: "https://gist.github.com") do |builder|
53
+ builder.use Faraday::Request::JSON
54
+ builder.use Faraday::Response::RaiseError
55
+ builder.use Faraday::Adapter::NetHttp
56
+ end
57
+ end
58
+
59
+ def parse_uri(uri)
60
+ uri = URI.parse(uri)
61
+ [uri.path, parse_params(uri.query)]
62
+ end
63
+
64
+ def parse_params(query_string)
65
+ query_string.split("&").inject(Hash.new) do |hash, kv|
66
+ key, value = kv.split("=")
67
+ hash[key] = value
68
+ hash
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,48 @@
1
+ require 'open-uri'
2
+
3
+ require_relative 'fetcher'
4
+
5
+ module Gister
6
+ class Middleware
7
+ def initialize(app, fetcher=Fetcher.new)
8
+ @app = app
9
+ @fetcher = fetcher
10
+ end
11
+
12
+ def call(env)
13
+ request = Rack::Request.new env
14
+ if request.path =~ /^\/gist\/[0-9]+.json/
15
+ respond_to_failures do
16
+ [200, {'Content-Type' => 'application/javascript'}, [get_body_content(request)]]
17
+ end
18
+ else
19
+ @app.call(env)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def respond_to_failures
26
+ yield
27
+ rescue Fetcher::ClientError
28
+ [404, {}, [""]]
29
+ end
30
+
31
+ def get_body_content(request)
32
+ path = request.path.gsub("/gist/", '')
33
+ path = "https://gist.github.com/#{path}?file=#{request.params["file"]}"
34
+
35
+ response = fetch_by_path path
36
+ wrap_in_jsonp(request.params["callback"], response)
37
+ end
38
+
39
+ def wrap_in_jsonp(callback, response)
40
+ "#{callback}(#{response})"
41
+ end
42
+
43
+ def fetch_by_path(path)
44
+ @fetcher.fetch path
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'middleware'
2
+
3
+ module Gister
4
+ class Railtie < Rails::Railtie
5
+ initializer "gister.configure_rails_initialization" do |app|
6
+ app.middleware.insert_before ActionDispatch::Cookies, Gister::Middleware, Gister.fetcher
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Gister
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,75 @@
1
+ require 'gister/fetcher'
2
+ require 'helper'
3
+
4
+ describe Gister::Fetcher do
5
+ subject { described_class.new }
6
+ let(:key) {
7
+ "https://gist.github.com/1111.json?file=app.js"
8
+ }
9
+
10
+ describe "set" do
11
+ it "should store the object based on it's key" do
12
+ subject.set(key, "hello")
13
+ subject.get(key).should == "hello"
14
+ end
15
+ end
16
+
17
+ describe "fetch" do
18
+ use_vcr_cassette "gister", record: :new_episodes
19
+
20
+ context "when the gist is already in the cache" do
21
+ let(:cached_response) {
22
+ "jQuery({})"
23
+ }
24
+
25
+ before do
26
+ subject.set(key, cached_response)
27
+ end
28
+
29
+ it "should return the response from the cache" do
30
+ subject.fetch(key).should == cached_response
31
+ end
32
+ end
33
+
34
+ context "when the gist is not already in the cache" do
35
+
36
+ context "and there is a successful response from gist" do
37
+ let(:key) {
38
+ "https://gist.github.com/1996296.json?file=challenge-1-2.js"
39
+ }
40
+
41
+ it "should return the response gist" do
42
+ subject.fetch(key).should include("Anatomy of Backbone 1-2")
43
+ end
44
+
45
+ it "should store the response from gist into the cache" do
46
+ subject.fetch(key)
47
+ subject.get(key).should_not be_nil
48
+ end
49
+ end
50
+
51
+ context "and gist responds with a 404" do
52
+ let(:key) {
53
+ "https://gist.github.com/199629612981921.json?file=challenge-1-2.js"
54
+ }
55
+
56
+ it "should raise a GistNotFound error" do
57
+ expect { subject.fetch(key) }.to raise_error(described_class::GistNotFound)
58
+ end
59
+ end
60
+
61
+ context "and gist responds with a 500" do
62
+ let(:key) {
63
+ "https://gist.github.com/client_error122.json?file=challenge-1-2.js"
64
+ }
65
+
66
+ it "should raise a ClientError error" do
67
+ expect { subject.fetch(key) }.to raise_error(described_class::ClientError)
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+
74
+
75
+ end
@@ -0,0 +1,308 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://gist.github.com/1996296.json?file=challenge-1-2.js
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - ! '*/*'
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: !binary |-
20
+ T0s=
21
+ headers:
22
+ !binary "U2VydmVy":
23
+ - !binary |-
24
+ bmdpbngvMS4wLjEy
25
+ !binary "RGF0ZQ==":
26
+ - !binary |-
27
+ TW9uLCAxMiBNYXIgMjAxMiAxNTo0MDoxMiBHTVQ=
28
+ !binary "Q29udGVudC1UeXBl":
29
+ - !binary |-
30
+ YXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOA==
31
+ !binary "VHJhbnNmZXItRW5jb2Rpbmc=":
32
+ - !binary |-
33
+ Y2h1bmtlZA==
34
+ !binary "Q29ubmVjdGlvbg==":
35
+ - !binary |-
36
+ a2VlcC1hbGl2ZQ==
37
+ !binary "U3RhdHVz":
38
+ - !binary |-
39
+ MjAwIE9L
40
+ !binary "RXRhZw==":
41
+ - !binary |-
42
+ IjU3YjRhMmIyNzE2OTBlNDEwZWRhNWI4MDdiYmRhMTEzIg==
43
+ !binary "WC1GcmFtZS1PcHRpb25z":
44
+ - !binary |-
45
+ ZGVueQ==
46
+ !binary "WC1SdW50aW1l":
47
+ - !binary |-
48
+ Njg=
49
+ !binary "Q2FjaGUtQ29udHJvbA==":
50
+ - !binary |-
51
+ cHJpdmF0ZSwgbWF4LWFnZT0wLCBtdXN0LXJldmFsaWRhdGU=
52
+ !binary "U3RyaWN0LVRyYW5zcG9ydC1TZWN1cml0eQ==":
53
+ - !binary |-
54
+ bWF4LWFnZT0yNTkyMDAw
55
+ !binary "Q29udGVudC1FbmNvZGluZw==":
56
+ - !binary |-
57
+ Z3ppcA==
58
+ body:
59
+ encoding: ASCII-8BIT
60
+ string: !binary |-
61
+ H4sIAAAAAAAAA6VUXW/aMBT9K5b7wCaROAnlK6RI3R66h+1tb2NCjnMhXhM7
62
+ sp1SVPW/7zoKrFDaPgwJgXzPuefmnuM8UWGAOyjW3NGUJlGcsGjEoimJR2l8
63
+ nY5HJIhmUUSHtGnzSgqaOtPCkBZghZGNk1oh71Zxp+s90RvyhYv7XCsgcZAg
64
+ q5APWM/wh8jiZkW30rogns8nyXyyokRU3Nr+eEWXK7VSpP90nJf1YCMr6EAH
65
+ CCGvQQV3nHQqdq8cfzwjeOoJqZTbssKvQ2DWGFi+qA4qqWDgBx98/xoPlplt
66
+ uDrOdF8g5YGbjPnjJTmtKq982zRaKleDcpdRGkE3l0tdg8M2e8ipRIOA8GKl
67
+ 4/7QBVQXyx8Q4dGBKt5kfnp6/rw4VBm6tMxYt7ju/4k7/cn7jtXg+CuXMk5K
68
+ AxuMRulcY1PGvKfhVrqyzUOha2b4jvVBYlExT/g44fl8AxMxmoyvi1HOk5zP
69
+ xrMxbGAM03w2m8ZMlLyqQG0hwHiGfyxG0Lp9BaizqTR3qfFRWHhjJewIamSM
70
+ nzwTxufD0fqxrnxg10fJdbx+R7LmZitV0OmncdQ8LoSutEmvJhO8KMvzwf9j
71
+ LOz2s5SW3OFCfRuSG92iKnGa7HVL8v3ZI3bLP+wd2XfSfWtzTw0vuX28wL37
72
+ h1zg26DbtS0B/MvmLWP/gWxnOoM6hyIU1mIHv1JL01/0fCH095DqnQKDnQUm
73
+ 34pS6yoQujUWGUM8rP099GSEGmg0Inun6PNfOWNkggkFAAA=
74
+ http_version:
75
+ recorded_at: Mon, 12 Mar 2012 15:40:12 GMT
76
+ - request:
77
+ method: get
78
+ uri: https://gist.github.com/199629612981921.json?file=challenge-1-2.js
79
+ body:
80
+ encoding: US-ASCII
81
+ string: ''
82
+ headers:
83
+ Accept-Encoding:
84
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
85
+ Accept:
86
+ - ! '*/*'
87
+ User-Agent:
88
+ - Ruby
89
+ response:
90
+ status:
91
+ code: 404
92
+ message: !binary |-
93
+ Tm90IEZvdW5k
94
+ headers:
95
+ !binary "U2VydmVy":
96
+ - !binary |-
97
+ bmdpbngvMS4wLjEy
98
+ !binary "RGF0ZQ==":
99
+ - !binary |-
100
+ TW9uLCAxMiBNYXIgMjAxMiAxNTo0MDoxMiBHTVQ=
101
+ !binary "Q29udGVudC1UeXBl":
102
+ - !binary |-
103
+ dGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04
104
+ !binary "VHJhbnNmZXItRW5jb2Rpbmc=":
105
+ - !binary |-
106
+ Y2h1bmtlZA==
107
+ !binary "Q29ubmVjdGlvbg==":
108
+ - !binary |-
109
+ a2VlcC1hbGl2ZQ==
110
+ !binary "U3RhdHVz":
111
+ - !binary |-
112
+ NDA0IE5vdCBGb3VuZA==
113
+ !binary "WC1GcmFtZS1PcHRpb25z":
114
+ - !binary |-
115
+ ZGVueQ==
116
+ !binary "WC1SdW50aW1l":
117
+ - !binary |-
118
+ MTI=
119
+ !binary "U2V0LUNvb2tpZQ==":
120
+ - !binary |-
121
+ X2doX3Nlc3M9QkFoN0J6b1FYMk56Y21aZmRHOXJaVzRpTVhkSFFsSTVSR01y
122
+ YUdoSGFGUmhlRzlQTTNJMlJVcHFZMnBQUVdKWFFtOWxNMVl4UjI1UGF6aFJV
123
+ RlU5T2c5elpYTnphVzl1WDJsa0lpVmhORFkyTkdOaFl6WTJNVFpoTWpoaU56
124
+ VTNOekZsWVdFMlpqSTFZVGhpT1ElM0QlM0QtLTdkMWYyNzlmOWQ1NDBjMmRl
125
+ MjhkZWFkZWU2YTI0Nzc5YmNjNDZlZmM7IHBhdGg9LzsgZXhwaXJlcz1TYXQs
126
+ IDAxLUphbi0yMDIyIDAwOjAwOjAwIEdNVDsgc2VjdXJlOyBIdHRwT25seQ==
127
+ !binary "Q2FjaGUtQ29udHJvbA==":
128
+ - !binary |-
129
+ bm8tY2FjaGU=
130
+ !binary "U3RyaWN0LVRyYW5zcG9ydC1TZWN1cml0eQ==":
131
+ - !binary |-
132
+ bWF4LWFnZT0yNTkyMDAw
133
+ !binary "Q29udGVudC1FbmNvZGluZw==":
134
+ - !binary |-
135
+ Z3ppcA==
136
+ body:
137
+ encoding: ASCII-8BIT
138
+ string: !binary |-
139
+ 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
177
+ +W3gRuoT9/Tjpgz1MgRMpI0eGpEgedYuAGxdLShYgmUa9DsdvansxFkT2lql
178
+ gJTPUWVGUYNJnuSRHuXn/p09du3fYv/ZR/KGySH2I3jGgt0KU3rAbOnHjMNp
179
+ dn3/GvLKJn7wOJCvrOdkyjZiU4lveoFvRg9BVYlvuZrfM/8kYDIfSVhUYaNx
180
+ ApbK9FHOnvdQ8qbDfuEee8EjD9f3E0z0rSeYAr0SwYmy3DO1CdR1tOqDNNbO
181
+ aUW8YbNETT6QSv24v0JlBneveyKBuo7KXrIxNq/oYciUVXgg0RVRLpnBb7O+
182
+ CvF19Ot9LMOKRBdXeV+Un6wqv5Kx3TPlJdjrKO/RNluh/EHK/3h1Uxe1v250
183
+ V7V/Ztn3TH3uMqwjvdvp7Zd0Wt2SPiPepoaP+FK2eynlxrei3FhHua4rcS+H
184
+ 2xQ7laJxeWMlpoZZ0ChkQUhESe5C7J69nATPlD2F/ZN+S571y2yuetJkeXKG
185
+ 7ElhtnixEMFlMiwZtYpNJfGbBu7F1O1o1pOcN11uXctQ5NJB3kelbtmPKNuE
186
+ SHj3xqOaHCXuIQH8iDLAVTCbYOQJuELaSxFzicxXMSsBwAkyEo0s98CQutmY
187
+ ReImEvHN8Tn9t5r2oaW75/X1OaMtXt4mg3UvBjJ3b4GEF+qCPebzxTP2AUsP
188
+ D+QrSEL47ngyYfgxudoGCCqaqByKANnGUBRrc9kCv8oebwkvjJAGLNX5KEEZ
189
+ CfZBPqhASTJktOOI+XmmdL3IfPR9VwnuBomhYq2IWlMeT1soKYAgXInwlJ17
190
+ 3F3+WXmu4Npk4lgVpGpECPBgVpA8RlrMuqYKMOhSN9hL3DlF7lWE4KZMo1Tp
191
+ rAGpCsohkJT1eAXzjRMiJ/XCt5F/9hxogmgrWEBvzq3aJYQnzn7i2xI5hwPr
192
+ rsjCuzCMkeMmQM7FzPfElgy78s0VSfjBN9lznwd2BcJXyMGrO6zfNoKA0vui
193
+ ljUf8KCCSc1KUV8F3Hwk0cpgPiICIv8fDypgvoKgl74Vz1MRuk8lAqeZcOvp
194
+ eosHFYTq6bLFjXDRQxGUKXuZ3mbnF++2BJWIcaHEn1QFJy6/QcXB1hC7XyPf
195
+ 49F2lO0e7HXyCBKqHm05l6y61K7pBT2pQCmuhjLe0kq3ZSo7sdKl+0UjLJ+r
196
+ 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
247
+ HaLt5jAlU3KQvqoBTdVWXzL6P/6KgBvhSAAA
248
+ http_version:
249
+ recorded_at: Mon, 12 Mar 2012 15:40:13 GMT
250
+ - request:
251
+ method: get
252
+ uri: https://gist.github.com/client_error122.json?file=challenge-1-2.js
253
+ body:
254
+ encoding: US-ASCII
255
+ string: ''
256
+ headers:
257
+ Accept-Encoding:
258
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
259
+ Accept:
260
+ - ! '*/*'
261
+ User-Agent:
262
+ - Ruby
263
+ response:
264
+ status:
265
+ code: 404
266
+ message: !binary |-
267
+ Tm90IEZvdW5k
268
+ headers:
269
+ !binary "U2VydmVy":
270
+ - !binary |-
271
+ bmdpbngvMS4wLjEy
272
+ !binary "RGF0ZQ==":
273
+ - !binary |-
274
+ TW9uLCAxMiBNYXIgMjAxMiAxNTo0MDoxMyBHTVQ=
275
+ !binary "Q29udGVudC1UeXBl":
276
+ - !binary |-
277
+ YXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOA==
278
+ !binary "VHJhbnNmZXItRW5jb2Rpbmc=":
279
+ - !binary |-
280
+ Y2h1bmtlZA==
281
+ !binary "Q29ubmVjdGlvbg==":
282
+ - !binary |-
283
+ a2VlcC1hbGl2ZQ==
284
+ !binary "U3RhdHVz":
285
+ - !binary |-
286
+ NDA0IE5vdCBGb3VuZA==
287
+ !binary "WC1GcmFtZS1PcHRpb25z":
288
+ - !binary |-
289
+ ZGVueQ==
290
+ !binary "WC1SdW50aW1l":
291
+ - !binary |-
292
+ Mw==
293
+ !binary "Q2FjaGUtQ29udHJvbA==":
294
+ - !binary |-
295
+ bm8tY2FjaGU=
296
+ !binary "U3RyaWN0LVRyYW5zcG9ydC1TZWN1cml0eQ==":
297
+ - !binary |-
298
+ bWF4LWFnZT0yNTkyMDAw
299
+ !binary "Q29udGVudC1FbmNvZGluZw==":
300
+ - !binary |-
301
+ Z3ppcA==
302
+ body:
303
+ encoding: ASCII-8BIT
304
+ string: !binary |-
305
+ H4sIAAAAAAAAA6tWSi0qyi9SslLyyy9RcMsvzUtRqgUAu/DzMBUAAAA=
306
+ http_version:
307
+ recorded_at: Mon, 12 Mar 2012 15:40:13 GMT
308
+ recorded_with: VCR 2.0.0
data/spec/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'vcr'
2
+
3
+ VCR.configure do |c|
4
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
5
+ c.hook_into :webmock
6
+ end
7
+
8
+ RSpec.configure do |c|
9
+ c.extend VCR::RSpec::Macros
10
+ end
@@ -0,0 +1,83 @@
1
+ require 'gister/middleware'
2
+ require_relative 'helper'
3
+ require 'rack'
4
+
5
+ describe Gister::Middleware do
6
+ let(:app) { load_app }
7
+ let(:response) { request(app, path) }
8
+
9
+ subject { response }
10
+
11
+ describe "when responding to a request with a gist path" do
12
+ let(:path) {
13
+ "/gist/1111.json?file=app.js&callback=jQueryCallback&_=12012981921"
14
+ }
15
+
16
+ context 'and getting content from the fetcher works' do
17
+ let(:response_body) {
18
+ "{hello:'world'}"
19
+ }
20
+
21
+ before do
22
+ app.stub(:fetch_by_path).and_return(response_body)
23
+ end
24
+
25
+ it "should use the url as the key to fetcher with the callback or timestamp" do
26
+ app.should_receive(:fetch_by_path).with("https://gist.github.com/1111.json?file=app.js").and_return(response_body)
27
+
28
+ subject
29
+ end
30
+
31
+ it "should wrap the response from fetcher in the callback param" do
32
+ subject[2].should == ["jQueryCallback(#{response_body})"]
33
+ end
34
+
35
+ it "should return a 200" do
36
+ subject[0].should == 200
37
+ end
38
+
39
+ it "should have a content type of application/javascript" do
40
+ subject[1]['Content-Type'].should == "application/javascript"
41
+ end
42
+ end
43
+
44
+ context 'and getting content from the fetcher raises a ClientError' do
45
+ before do
46
+ app.stub(:fetch_by_path).and_raise(Gister::Fetcher::ClientError)
47
+ end
48
+
49
+ it "should return a 404" do
50
+ subject[0].should == 404
51
+ end
52
+
53
+ it "should have an empty body" do
54
+ subject[2].should == [""]
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "when responding to a request without a gist path" do
60
+ let(:path) { "/hello" }
61
+
62
+ it "should pass through to the inner app" do
63
+ subject[2].should == 'Success'
64
+ end
65
+
66
+ end
67
+
68
+ def load_app
69
+ described_class.new inner_app, fetcher
70
+ end
71
+
72
+ def inner_app
73
+ lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'Success'] }
74
+ end
75
+
76
+ def request(app, path, options = {})
77
+ app.call Rack::MockRequest.env_for(path, options)
78
+ end
79
+
80
+ def fetcher
81
+ Gister::Fetcher.new
82
+ end
83
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gister
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eric Allam
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70220136504780 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70220136504780
25
+ - !ruby/object:Gem::Dependency
26
+ name: vcr
27
+ requirement: &70220136503880 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70220136503880
36
+ - !ruby/object:Gem::Dependency
37
+ name: webmock
38
+ requirement: &70220136503320 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70220136503320
47
+ - !ruby/object:Gem::Dependency
48
+ name: faraday
49
+ requirement: &70220136502740 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - =
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.1
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70220136502740
58
+ description: Provides a Middleware to cache embedded gist content
59
+ email:
60
+ - rubymaverick@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - gister.gemspec
71
+ - lib/gister.rb
72
+ - lib/gister/fetcher.rb
73
+ - lib/gister/middleware.rb
74
+ - lib/gister/railtie.rb
75
+ - lib/gister/version.rb
76
+ - spec/fetcher_spec.rb
77
+ - spec/fixtures/vcr_cassettes/gister.yml
78
+ - spec/helper.rb
79
+ - spec/middleware_spec.rb
80
+ homepage: ''
81
+ licenses: []
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 1.8.17
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Provides a Middleware to cache embedded gist content
104
+ test_files:
105
+ - spec/fetcher_spec.rb
106
+ - spec/fixtures/vcr_cassettes/gister.yml
107
+ - spec/helper.rb
108
+ - spec/middleware_spec.rb