social-avatar-proxy 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -27,7 +27,7 @@ Or install it yourself as:
27
27
 
28
28
  ## Usage
29
29
 
30
- # Rails
30
+ ### Rails
31
31
 
32
32
  In your `config/routes.rb` file:
33
33
 
@@ -51,7 +51,18 @@ image_tag(facebook_avatar_path("username"))
51
51
  image_tag(facebook_avatar_path(12345))
52
52
  ```
53
53
 
54
- # Rack
54
+ You might wish to configure a default image which will be rendered if an avatar could not be found, or if the remote service has an error (e.g. times out or has a redirect loop), this is simple with an initializer:
55
+
56
+ ```ruby
57
+ require "social_avatar_proxy/config"
58
+
59
+ # choose our image
60
+ image_path = Rails.root.join("public", "default_avatar.jpg")
61
+ # set the config
62
+ SocialAvatarProxy::Config.default_image = image_path
63
+ ```
64
+
65
+ ### Rack
55
66
 
56
67
  The Rack app is available at: SocialAvatarProxy::App.
57
68
 
@@ -1,4 +1,5 @@
1
1
  require "social_avatar_proxy/version"
2
+ require "social_avatar_proxy/config"
2
3
  require "social_avatar_proxy/app"
3
4
  require "social_avatar_proxy/avatar"
4
5
  require "social_avatar_proxy/facebook_avatar"
@@ -1,3 +1,4 @@
1
+ require "social_avatar_proxy/config"
1
2
  require "social_avatar_proxy/facebook_avatar"
2
3
  require "social_avatar_proxy/twitter_avatar"
3
4
  require "social_avatar_proxy/routes"
@@ -54,25 +55,13 @@ module SocialAvatarProxy
54
55
  if avatar.exist?
55
56
  # render the avatar to the response
56
57
  Rack::Response.new do |response|
57
- # set the last modified header
58
- response["Last-Modified"] = avatar.last_modified
59
- # set the content type header
60
- response["Content-Type"] = avatar.content_type
61
- # if we want to expire in a set time, calculate the header
62
- if options[:expires]
63
- response["Expires"] = (Time.now + options[:expires]).httpdate
64
- end
65
- # if we want to set cache control settings
66
- if cc = options[:cache_control]
67
- directives = []
68
- directives << "no-cache" if cc[:no_cache]
69
- directives << "max-stale=#{cc[:max_stale]}" if cc[:max_stale]
70
- directives << "max-age=#{cc[:max_age]}" if cc[:max_age]
71
- directives << (cc[:public] ? "public" : "private")
72
- response["Cache-Control"] = directives.join(", ")
73
- end
74
- # set the data
58
+ # set the response data
75
59
  response.write(avatar.body)
60
+ # set the response headers
61
+ response = set_avatar_headers(response, avatar)
62
+ response = set_caching_headers(response)
63
+ # return the response
64
+ response
76
65
  end
77
66
  # if the avatar doesn't exist
78
67
  else
@@ -81,15 +70,39 @@ module SocialAvatarProxy
81
70
  end
82
71
 
83
72
  def not_found
84
- Rack::Response.new("Not Found", 404)
73
+ Rack::Response.new([], 404) do |response|
74
+ # if we have a custom default image
75
+ if Config.default_image
76
+ render_default_image(response)
77
+ # without a default image
78
+ else
79
+ response.write "Not Found"
80
+ end
81
+ end
85
82
  end
86
83
 
87
84
  def timeout
88
- Rack::Response.new("Remote server timeout", 504)
85
+ Rack::Response.new([], 504) do |response|
86
+ # if we have a custom default image
87
+ if Config.default_image
88
+ render_default_image(response)
89
+ # without a default image
90
+ else
91
+ response.write "Remote server timeout"
92
+ end
93
+ end
89
94
  end
90
95
 
91
96
  def bad_gateway
92
- Rack::Response.new("Bad response from remote server", 502)
97
+ Rack::Response.new([], 502) do |response|
98
+ # if we have a custom default image
99
+ if Config.default_image
100
+ render_default_image(response)
101
+ # without a default image
102
+ else
103
+ response.write "Bad response from remote server"
104
+ end
105
+ end
93
106
  end
94
107
 
95
108
  def routes
@@ -97,6 +110,44 @@ module SocialAvatarProxy
97
110
  end
98
111
 
99
112
  private
113
+ def render_default_image(response)
114
+ # render the image
115
+ response.write(Config.default_image_data)
116
+ # set the content type
117
+ response["Content-Type"] = Config.default_image_content_type
118
+ # set expiry
119
+ response = set_caching_headers(response)
120
+ # return the response
121
+ response
122
+ end
123
+
124
+ def set_avatar_headers(response, avatar)
125
+ # set the last modified header
126
+ response["Last-Modified"] = avatar.last_modified
127
+ # set the content type header
128
+ response["Content-Type"] = avatar.content_type
129
+ # return the response
130
+ response
131
+ end
132
+
133
+ def set_caching_headers(response)
134
+ # if we want to expire in a set time, calculate the header
135
+ if options[:expires]
136
+ response["Expires"] = (Time.now + options[:expires]).httpdate
137
+ end
138
+ # if we want to set cache control settings
139
+ if cc = options[:cache_control]
140
+ directives = []
141
+ directives << "no-cache" if cc[:no_cache]
142
+ directives << "max-stale=#{cc[:max_stale]}" if cc[:max_stale]
143
+ directives << "max-age=#{cc[:max_age]}" if cc[:max_age]
144
+ directives << (cc[:public] ? "public" : "private")
145
+ response["Cache-Control"] = directives.join(", ")
146
+ end
147
+ # return the response
148
+ response
149
+ end
150
+
100
151
  def load_avatar(service, id)
101
152
  # titleize the service name
102
153
  service = service.gsub(/[\_\-]/, " ").gsub(/\b([a-z])/) do |match|
@@ -0,0 +1,30 @@
1
+ module SocialAvatarProxy
2
+ class Config
3
+ class << self
4
+ attr_accessor :default_image
5
+
6
+ def default_image_file
7
+ default_image && File.new(default_image)
8
+ end
9
+
10
+ def default_image_data
11
+ default_image_file.read
12
+ end
13
+
14
+ def default_image_content_type
15
+ case File.extname(default_image).downcase
16
+ when /^\.jpe?g$/
17
+ "image/jpeg"
18
+ when /^\.png$/
19
+ "image/png"
20
+ when /^\.gif$/
21
+ "image/gif"
22
+ when /^\.svg$/
23
+ "image/svg+xml"
24
+ else
25
+ "application/octet-stream"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module SocialAvatarProxy
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
Binary file
@@ -57,10 +57,22 @@ describe SocialAvatarProxy::App do
57
57
  end
58
58
 
59
59
  context "given an invalid path" do
60
+ let(:path) { "/unknown" }
61
+
60
62
  it "should return a 404 response" do
61
- path = "/unknown"
62
63
  expect(subject.get(path).status).to eq(404)
63
64
  end
65
+
66
+ context "with a custom image" do
67
+ before(:each) do
68
+ image_path = File.join(File.dirname(__FILE__), "../fixtures/image.jpg")
69
+ SocialAvatarProxy::Config.default_image = image_path
70
+ end
71
+
72
+ it "should render the image" do
73
+ expect(subject.get(path)["Content-Type"]).to eq("image/jpeg")
74
+ end
75
+ end
64
76
  end
65
77
 
66
78
  context "given a valid path" do
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ describe SocialAvatarProxy::Config do
4
+ subject { SocialAvatarProxy::Config }
5
+
6
+ after(:each) do
7
+ subject.default_image = nil
8
+ end
9
+
10
+ describe "::default_image" do
11
+ it "should default to nil" do
12
+ expect(subject.default_image).to be_nil
13
+ end
14
+
15
+ it "should store a path" do
16
+ subject.default_image = "/test.jpg"
17
+ expect(subject.default_image).to eq "/test.jpg"
18
+ end
19
+ end
20
+
21
+ describe "::default_image_content_type" do
22
+ context "with a JPEG" do
23
+ it "should return image/jpeg" do
24
+ subject.default_image = "/test.JPG"
25
+ expect(subject.default_image_content_type).to eq "image/jpeg"
26
+ end
27
+ end
28
+
29
+ context "with a PNG" do
30
+ it "should return image/png" do
31
+ subject.default_image = "/test.png"
32
+ expect(subject.default_image_content_type).to eq "image/png"
33
+ end
34
+ end
35
+
36
+ context "with a GIF" do
37
+ it "should return image/gif" do
38
+ subject.default_image = "/test.gif"
39
+ expect(subject.default_image_content_type).to eq "image/gif"
40
+ end
41
+ end
42
+
43
+ context "with a SVG" do
44
+ it "should return image/svg+xml" do
45
+ subject.default_image = "/test.svg"
46
+ expect(subject.default_image_content_type).to eq "image/svg+xml"
47
+ end
48
+ end
49
+
50
+ context "with an unknown type" do
51
+ it "should return application/octet-stream" do
52
+ subject.default_image = "/test"
53
+ expect(subject.default_image_content_type).to eq "application/octet-stream"
54
+ end
55
+ end
56
+ end
57
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: social-avatar-proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -126,6 +126,7 @@ files:
126
126
  - lib/social_avatar_proxy.rb
127
127
  - lib/social_avatar_proxy/app.rb
128
128
  - lib/social_avatar_proxy/avatar.rb
129
+ - lib/social_avatar_proxy/config.rb
129
130
  - lib/social_avatar_proxy/engine.rb
130
131
  - lib/social_avatar_proxy/facebook_avatar.rb
131
132
  - lib/social_avatar_proxy/path_helpers.rb
@@ -136,9 +137,11 @@ files:
136
137
  - lib/social_avatar_proxy/twitter_avatar.rb
137
138
  - lib/social_avatar_proxy/version.rb
138
139
  - social-avatar-proxy.gemspec
140
+ - spec/fixtures/image.jpg
139
141
  - spec/internal/config/routes.rb
140
142
  - spec/social_avatar_proxy/app_spec.rb
141
143
  - spec/social_avatar_proxy/avatar_spec.rb
144
+ - spec/social_avatar_proxy/config_spec.rb
142
145
  - spec/social_avatar_proxy/engine_spec.rb
143
146
  - spec/social_avatar_proxy/facebook_avatar_spec.rb
144
147
  - spec/social_avatar_proxy/path_helpers_spec.rb
@@ -173,9 +176,11 @@ signing_key:
173
176
  specification_version: 3
174
177
  summary: This gem acts as a proxy for avatars on Twitter & Facebook.
175
178
  test_files:
179
+ - spec/fixtures/image.jpg
176
180
  - spec/internal/config/routes.rb
177
181
  - spec/social_avatar_proxy/app_spec.rb
178
182
  - spec/social_avatar_proxy/avatar_spec.rb
183
+ - spec/social_avatar_proxy/config_spec.rb
179
184
  - spec/social_avatar_proxy/engine_spec.rb
180
185
  - spec/social_avatar_proxy/facebook_avatar_spec.rb
181
186
  - spec/social_avatar_proxy/path_helpers_spec.rb