CacheBar 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/CacheBar.gemspec +93 -0
- data/Gemfile +18 -0
- data/HISTORY +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +102 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/lib/cachebar.rb +38 -0
- data/lib/core_ext/hash/require_keys.rb +9 -0
- data/lib/httparty/httpcache.rb +142 -0
- data/test/fixtures/user_timeline.json +1 -0
- data/test/fixtures/vcr_cassettes/bad_response.yml +40 -0
- data/test/fixtures/vcr_cassettes/good_response.yml +204 -0
- data/test/fixtures/vcr_cassettes/unparsable.yml +162 -0
- data/test/helper.rb +70 -0
- data/test/test_cachebar.rb +216 -0
- data/test/twitter_api.rb +22 -0
- metadata +214 -0
data/.document
ADDED
data/CacheBar.gemspec
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{CacheBar}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brian Landau", "David Eisinger"]
|
12
|
+
s.date = %q{2011-06-01}
|
13
|
+
s.description = %q{A simple API caching layer built on top of HTTParty and Redis}
|
14
|
+
s.email = %q{brian.landau@viget.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"CacheBar.gemspec",
|
22
|
+
"Gemfile",
|
23
|
+
"HISTORY",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.md",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"lib/cachebar.rb",
|
29
|
+
"lib/core_ext/hash/require_keys.rb",
|
30
|
+
"lib/httparty/httpcache.rb",
|
31
|
+
"test/fixtures/user_timeline.json",
|
32
|
+
"test/fixtures/vcr_cassettes/bad_response.yml",
|
33
|
+
"test/fixtures/vcr_cassettes/good_response.yml",
|
34
|
+
"test/fixtures/vcr_cassettes/unparsable.yml",
|
35
|
+
"test/helper.rb",
|
36
|
+
"test/test_cachebar.rb",
|
37
|
+
"test/twitter_api.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/vigetlabs/cachebar}
|
40
|
+
s.licenses = ["MIT"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.6.2}
|
43
|
+
s.summary = %q{A simple API caching layer built on top of HTTParty and Redis}
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_runtime_dependency(%q<redis>, [">= 0"])
|
50
|
+
s.add_runtime_dependency(%q<redis-namespace>, [">= 0"])
|
51
|
+
s.add_runtime_dependency(%q<httparty>, ["~> 0.7.7"])
|
52
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
53
|
+
s.add_runtime_dependency(%q<SystemTimer>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
56
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6"])
|
57
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<webmock>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<vcr>, [">= 0"])
|
60
|
+
s.add_development_dependency(%q<mocha>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<redis>, [">= 0"])
|
64
|
+
s.add_dependency(%q<redis-namespace>, [">= 0"])
|
65
|
+
s.add_dependency(%q<httparty>, ["~> 0.7.7"])
|
66
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
67
|
+
s.add_dependency(%q<SystemTimer>, [">= 0"])
|
68
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
70
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6"])
|
71
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
72
|
+
s.add_dependency(%q<webmock>, [">= 0"])
|
73
|
+
s.add_dependency(%q<vcr>, [">= 0"])
|
74
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
75
|
+
s.add_dependency(%q<rake>, ["~> 0.8.7"])
|
76
|
+
end
|
77
|
+
else
|
78
|
+
s.add_dependency(%q<redis>, [">= 0"])
|
79
|
+
s.add_dependency(%q<redis-namespace>, [">= 0"])
|
80
|
+
s.add_dependency(%q<httparty>, ["~> 0.7.7"])
|
81
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
82
|
+
s.add_dependency(%q<SystemTimer>, [">= 0"])
|
83
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
84
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
85
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6"])
|
86
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
87
|
+
s.add_dependency(%q<webmock>, [">= 0"])
|
88
|
+
s.add_dependency(%q<vcr>, [">= 0"])
|
89
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
90
|
+
s.add_dependency(%q<rake>, ["~> 0.8.7"])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "redis"
|
4
|
+
gem "redis-namespace"
|
5
|
+
gem 'httparty', '~> 0.7.7'
|
6
|
+
gem 'activesupport'
|
7
|
+
gem 'SystemTimer', :platforms => :ruby_18
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem "shoulda"
|
11
|
+
gem "bundler", "~> 1.0"
|
12
|
+
gem "jeweler", "~> 1.6"
|
13
|
+
gem "rcov"
|
14
|
+
gem "webmock"
|
15
|
+
gem 'vcr'
|
16
|
+
gem 'mocha'
|
17
|
+
gem 'rake', '~> 0.8.7'
|
18
|
+
end
|
data/HISTORY
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
== 1.0.0 / 2011-05-26
|
2
|
+
* Cache API responses in Redis from HTTParty requests
|
3
|
+
* Only cache APIs that have been registered with CacheBar.
|
4
|
+
* Stores response body as Redis string data type that is set to expire.
|
5
|
+
* Store a backup of responses incase the API service goes down.
|
6
|
+
* If an exception or timeout occurs and there is no backup an exception is raised.
|
7
|
+
* If a bad response is received the backup will be used if available otherwise the bad response will be returned
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Brian Landau of Viget Labs
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# CacheBar
|
2
|
+
|
3
|
+
CacheBar is a simple API caching layer built on top of Redis and HTTParty.
|
4
|
+
|
5
|
+
When a good request is made to the API through an HTTParty module or class configured to be cached, it caches the response body in Redis. The cache is set to expire in the configured length of time. All following identical requests use the cache in Redis. When the cache expires it will attempt to refill the cache with a new good response. If though the response that comes back is bad (there was timeout, a 404, or some other problem), then CacheBar will fetch a backup response we also store in Redis (in a separate non-expiring hash). When it pulls this backup response out it inserts it into the standard cache and sets it to expire in 5 minutes. This way we won't look for a new good response for another 5 minutes.
|
6
|
+
|
7
|
+
Using this gem does not mean that all your HTTParty modules and requests will be automatically cached. You will have to configure them on a case by case basis. This means you can have some APIs that are cached and others that aren't.
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
gem install cachebar
|
12
|
+
|
13
|
+
If you're on Ruby 1.8 it is recommended that you also install the SystemTimer gem:
|
14
|
+
|
15
|
+
gem install SystemTimer
|
16
|
+
|
17
|
+
### Inside a Rails/Rack app:
|
18
|
+
|
19
|
+
Add this to your Gemfile:
|
20
|
+
|
21
|
+
gem 'SystemTimer', :platforms => :ruby_18
|
22
|
+
gem 'cachebar'
|
23
|
+
|
24
|
+
Follow the instructions below for configuring CacheBar.
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
Although you can use CacheBar in any type of application, the examples provided will be for using it inside a Rails application.
|
29
|
+
|
30
|
+
### 1. Configuring CacheBar
|
31
|
+
|
32
|
+
There's a few configuration options to CacheBar, the first is specifying a Redis connection to use.
|
33
|
+
|
34
|
+
If you have an initializer for defining your Redis connection already like this:
|
35
|
+
|
36
|
+
REDIS_CONFIG = YAML.load_file(Rails.root+'config/redis.yml')[Rails.env].freeze
|
37
|
+
redis = Redis.new(:host => REDIS_CONFIG['host'], :port => REDIS_CONFIG['port'],
|
38
|
+
:thread_safe => true, :db => REDIS_CONFIG['db'])
|
39
|
+
$redis = Redis::Namespace.new(REDIS_CONFIG['namespace'], :redis => redis)
|
40
|
+
|
41
|
+
Then you can just add this:
|
42
|
+
|
43
|
+
HTTParty::HTTPCache.redis = $redis
|
44
|
+
|
45
|
+
You'll then also want to turn on caching in the appropriate environments. For instance you'll want to add this to `config/environments/production.rb`:
|
46
|
+
|
47
|
+
HTTParty::HTTPCache.perform_caching = true
|
48
|
+
|
49
|
+
CacheBar can also log useful information to your log file if you configure a logger for it:
|
50
|
+
|
51
|
+
HTTParty::HTTPCache.logger = Rails.logger
|
52
|
+
|
53
|
+
By default we use a timeout of 5 seconds on all requests, this can be configured like so:
|
54
|
+
|
55
|
+
HTTParty::HTTPCache.timeout_length = 10 # seconds
|
56
|
+
|
57
|
+
By default when we fallback to using a backup response, we then hold off looking for a new fresh response for 5 minutes, this can be configured like so:
|
58
|
+
|
59
|
+
HTTParty::HTTPCache.cache_stale_backup_time = 120 # 2 minutes
|
60
|
+
|
61
|
+
### 2. Configuring an HTTParty module or class
|
62
|
+
|
63
|
+
If you already have HTTParty included then you just need to use the `caches_api_responses` method to register that API for caching, and your done. The `caches_api_responses` takes a hash of options:
|
64
|
+
|
65
|
+
* `host`* *optional*:
|
66
|
+
* This is used internally to decide which requests to try to cache responses for.
|
67
|
+
If it's not provided it will use the `base_uri` specified on the class/module that HTTParty is included into.
|
68
|
+
* `key_name`:
|
69
|
+
* This is the name used in Redis to create a part of the cache key to easily differentiate it from other API caches.
|
70
|
+
* `expire_in`:
|
71
|
+
* This determines how long the good API responses are cached for.
|
72
|
+
|
73
|
+
Here's an example using Twitter:
|
74
|
+
|
75
|
+
module TwitterAPI
|
76
|
+
include HTTParty
|
77
|
+
base_uri 'https://api.twitter.com/1'
|
78
|
+
format :json
|
79
|
+
|
80
|
+
caches_api_responses :key_name => "twitter", :expire_in => 3600
|
81
|
+
end
|
82
|
+
|
83
|
+
After that all Twitter API calls will be cached for an hour.
|
84
|
+
|
85
|
+
If you want to cache an API that uses HTTParty but never includes HTTParty into a class or module, you can register the API like this:
|
86
|
+
|
87
|
+
CacheBar.register_api_to_cache('api.example.com', {:key_name => "example", :expire_in => 7200})
|
88
|
+
|
89
|
+
|
90
|
+
## Contributing to CacheBar
|
91
|
+
|
92
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
93
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
94
|
+
* Fork the project
|
95
|
+
* Start a feature/bugfix branch
|
96
|
+
* Commit and push until you are happy with your contribution
|
97
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
98
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
99
|
+
|
100
|
+
## Copyright
|
101
|
+
|
102
|
+
Copyright (c) 2011 Brian Landau. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "CacheBar"
|
18
|
+
gem.homepage = "http://github.com/vigetlabs/cachebar"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{A simple API caching layer built on top of HTTParty and Redis}
|
21
|
+
gem.description = %Q{A simple API caching layer built on top of HTTParty and Redis}
|
22
|
+
gem.email = "brian.landau@viget.com"
|
23
|
+
gem.authors = ["Brian Landau", "David Eisinger"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
test.rcov_opts << '--exclude "gems/*"'
|
41
|
+
test.rcov_opts << '--sort coverage'
|
42
|
+
test.rcov_opts << '--only-uncovered'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/lib/cachebar.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'httparty'
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_support/core_ext/module/aliasing'
|
6
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
7
|
+
require 'active_support/core_ext/object/blank'
|
8
|
+
require 'core_ext/hash/require_keys'
|
9
|
+
if RUBY_VERSION.split('.')[1].to_i < 9
|
10
|
+
begin
|
11
|
+
require 'system_timer'
|
12
|
+
rescue LoadError
|
13
|
+
$stderr.puts "When running a Ruby version before 1.9 you should consider using SystemTimer with CacheBar"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
require 'httparty/httpcache'
|
17
|
+
|
18
|
+
module CacheBar
|
19
|
+
def self.register_api_to_cache(host, options)
|
20
|
+
raise ArgumentError, "You must provide a host that you are caching API responses for." if host.blank?
|
21
|
+
options.require_keys(:expire_in, :key_name)
|
22
|
+
HTTParty::HTTPCache.apis[host] = options
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
def caches_api_responses(options)
|
27
|
+
host = if base_uri.present?
|
28
|
+
URI.parse(base_uri).host
|
29
|
+
else
|
30
|
+
options.delete(:host)
|
31
|
+
end
|
32
|
+
CacheBar.register_api_to_cache(host, options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
HTTParty::ClassMethods.send(:include, CacheBar::ClassMethods)
|
38
|
+
HTTParty::Request.send(:include, HTTParty::HTTPCache)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Hash
|
2
|
+
def require_keys(*valid_keys)
|
3
|
+
unknown_keys = keys - [valid_keys].flatten
|
4
|
+
raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
5
|
+
|
6
|
+
missing_keys = [valid_keys].flatten - keys
|
7
|
+
raise(ArgumentError, "Missing some required keys: #{missing_keys.join(", ")}") unless missing_keys.empty?
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module HTTParty
|
2
|
+
module HTTPCache
|
3
|
+
class NoResponseError < StandardError; end
|
4
|
+
|
5
|
+
mattr_accessor :perform_caching,
|
6
|
+
:apis,
|
7
|
+
:logger,
|
8
|
+
:redis,
|
9
|
+
:timeout_length,
|
10
|
+
:cache_stale_backup_time
|
11
|
+
|
12
|
+
self.perform_caching = false
|
13
|
+
self.apis = {}
|
14
|
+
self.timeout_length = 5 # 5 seconds
|
15
|
+
self.cache_stale_backup_time = 300 # 5 minutes
|
16
|
+
|
17
|
+
def self.included(base)
|
18
|
+
base.class_eval do
|
19
|
+
alias_method_chain :perform, :caching
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def perform_with_caching
|
24
|
+
if HTTPCache.perform_caching && HTTPCache.apis.keys.include?(uri.host)
|
25
|
+
if response_in_cache?
|
26
|
+
log_message("Retrieving response from cache")
|
27
|
+
response_from(response_body_from_cache)
|
28
|
+
else
|
29
|
+
begin
|
30
|
+
httparty_response = timeout(timeout_length) do
|
31
|
+
perform_without_caching
|
32
|
+
end
|
33
|
+
if httparty_response.response.is_a?(Net::HTTPSuccess)
|
34
|
+
log_message("Storing good response in cache")
|
35
|
+
store_in_cache(httparty_response.body)
|
36
|
+
store_backup(httparty_response.body)
|
37
|
+
httparty_response
|
38
|
+
else
|
39
|
+
retrieve_and_store_backup(httparty_response)
|
40
|
+
end
|
41
|
+
rescue *exceptions
|
42
|
+
retrieve_and_store_backup
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
log_message("Caching off")
|
47
|
+
perform_without_caching
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def response_from(response_body)
|
54
|
+
HTTParty::Response.new(self, OpenStruct.new(:body => response_body), parse_response(response_body))
|
55
|
+
end
|
56
|
+
|
57
|
+
def retrieve_and_store_backup(httparty_response = nil)
|
58
|
+
if backup_exists?
|
59
|
+
log_message('using backup')
|
60
|
+
response_body = backup_response
|
61
|
+
store_in_cache(response_body, cache_stale_backup_time)
|
62
|
+
response_from(response_body)
|
63
|
+
elsif httparty_response
|
64
|
+
httparty_response
|
65
|
+
else
|
66
|
+
log_message('No backup and bad response')
|
67
|
+
raise NoResponseError, 'Bad response from API server or timeout occured and no backup was in the cache'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def normalized_uri
|
72
|
+
return @normalized_uri if @normalized_uri
|
73
|
+
normalized_uri = uri.dup
|
74
|
+
normalized_uri.query = sort_query_params(normalized_uri.query)
|
75
|
+
normalized_uri.path.chop! if (normalized_uri.path =~ /\/$/)
|
76
|
+
normalized_uri.scheme = normalized_uri.scheme.downcase
|
77
|
+
@normalized_uri = normalized_uri.normalize.to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
def sort_query_params(query)
|
81
|
+
query.split('&').sort.join('&') unless query.blank?
|
82
|
+
end
|
83
|
+
|
84
|
+
def cache_key_name
|
85
|
+
@cache_key_name ||= "api-cache:#{HTTPCache.apis[uri.host][:key_name]}:#{uri_hash}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def uri_hash
|
89
|
+
@uri_hash ||= Digest::MD5.hexdigest(normalized_uri)
|
90
|
+
end
|
91
|
+
|
92
|
+
def response_in_cache?
|
93
|
+
redis.exists(cache_key_name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def backup_key
|
97
|
+
"api-cache:#{HTTPCache.apis[uri.host][:key_name]}"
|
98
|
+
end
|
99
|
+
|
100
|
+
def backup_response
|
101
|
+
redis.hget(backup_key, uri_hash)
|
102
|
+
end
|
103
|
+
|
104
|
+
def backup_exists?
|
105
|
+
redis.exists(backup_key) && redis.hexists(backup_key, uri_hash)
|
106
|
+
end
|
107
|
+
|
108
|
+
def response_body_from_cache
|
109
|
+
redis.get(cache_key_name)
|
110
|
+
end
|
111
|
+
|
112
|
+
def store_in_cache(response_body, expires = nil)
|
113
|
+
redis.set(cache_key_name, response_body)
|
114
|
+
redis.expire(cache_key_name, (expires || HTTPCache.apis[uri.host][:expire_in]))
|
115
|
+
end
|
116
|
+
|
117
|
+
def store_backup(response_body)
|
118
|
+
redis.hset(backup_key, uri_hash, response_body)
|
119
|
+
end
|
120
|
+
|
121
|
+
def log_message(message)
|
122
|
+
logger.info("[HTTPCache]: #{message} for #{normalized_uri} - #{uri_hash.inspect}") if logger
|
123
|
+
end
|
124
|
+
|
125
|
+
def timeout(seconds, &block)
|
126
|
+
if defined?(SystemTimer)
|
127
|
+
SystemTimer.timeout_after(seconds, &block)
|
128
|
+
else
|
129
|
+
options[:timeout] = seconds
|
130
|
+
yield
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def exceptions
|
135
|
+
if (RUBY_VERSION.split('.')[1].to_i >= 9) && defined?(Psych::SyntaxError)
|
136
|
+
[StandardError, Timeout::Error, Psych::SyntaxError]
|
137
|
+
else
|
138
|
+
[StandardError, Timeout::Error]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"in_reply_to_status_id_str":"72755187852382209","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"prasadvx","in_reply_to_user_id_str":"46685588","in_reply_to_status_id":72755187852382209,"contributors":null,"retweeted":false,"text":"@prasadvx http:\/\/www.viget.com\/blog\/studying-salutations2\/ :-)","created_at":"Mon May 23 20:07:35 +0000 2011","place":null,"id_str":"72755573317320704","coordinates":null,"geo":null,"in_reply_to_user_id":46685588,"id":72755573317320704,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"text":"Why We\u2019re Covering Kids (by @barn) http:\/\/goo.gl\/fb\/HioS4","place":null,"favorited":false,"truncated":false,"in_reply_to_status_id_str":null,"retweet_count":3,"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"source":"\u003Ca href=\"http:\/\/www.google.com\/support\/youtube\/bin\/answer.py?hl=en&answer=164577\" rel=\"nofollow\"\u003EGoogle\u003C\/a\u003E","contributors":null,"retweeted":false,"id_str":"72721638638092288","coordinates":null,"geo":null,"user":{"lang":"en","profile_background_tile":false,"favourites_count":0,"followers_count":1883,"follow_request_sent":false,"notifications":false,"friends_count":42,"description":"We design \/ build \/ market web sites \/ products \/ ideas.","is_translator":false,"statuses_count":719,"profile_link_color":"2776a1","profile_sidebar_border_color":"dad74e","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","time_zone":"Eastern Time (US & Canada)","listed_count":217,"following":true,"profile_use_background_image":true,"screen_name":"viget","verified":false,"profile_background_color":"14537f","location":"Wash DC, Durham NC, Boulder CO","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","protected":false,"url":"http:\/\/viget.com","name":"Viget Labs","id_str":"14171594","default_profile_image":false,"contributors_enabled":false,"profile_text_color":"333333","id":14171594,"default_profile":false,"show_all_inline_media":false,"geo_enabled":false,"utc_offset":-18000,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_sidebar_fill_color":"fdfab7"},"in_reply_to_user_id":null,"id":72721638638092288,"created_at":"Mon May 23 17:52:44 +0000 2011"},{"in_reply_to_status_id_str":"71229887637225473","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"EliVZ","in_reply_to_user_id_str":"14080974","in_reply_to_status_id":71229887637225473,"contributors":null,"retweeted":false,"text":"@EliVZ @trek Thanks guys! It helps that puma's stuff looks fantastic to start with. Makes for fun work.","created_at":"Thu May 19 17:01:06 +0000 2011","place":null,"id_str":"71259093393874947","coordinates":null,"geo":null,"in_reply_to_user_id":14080974,"id":71259093393874947,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":"70321047060221952","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"woley","in_reply_to_user_id_str":"15689271","in_reply_to_status_id":70321047060221952,"contributors":null,"retweeted":false,"text":"@woley Jeans are okay with us! We're very casual at Viget.","created_at":"Tue May 17 03:38:39 +0000 2011","place":null,"id_str":"70332373421658112","coordinates":null,"geo":null,"in_reply_to_user_id":15689271,"id":70332373421658112,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"charliepark","in_reply_to_user_id_str":"3225381","in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"@charliepark Alas, we don't -- too busy this year! Would love to chat, though. Let's connect ...","created_at":"Mon May 16 18:32:01 +0000 2011","place":null,"id_str":"70194809083674625","coordinates":null,"geo":null,"in_reply_to_user_id":3225381,"id":70194809083674625,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":1,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"Thanks! RT @klaustsen: Had a little talk with @viget at We the Creatives. Go read. Brilliant people. http:\/\/wethecreatives.com\/viget","created_at":"Mon May 16 18:27:15 +0000 2011","place":null,"id_str":"70193609277849600","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":70193609277849600,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":"69943614880481280","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"cdulude","in_reply_to_user_id_str":"1665611","in_reply_to_status_id":69943614880481280,"contributors":null,"retweeted":false,"text":"@cdulude @jasonalley :-)","created_at":"Mon May 16 10:29:45 +0000 2011","place":null,"id_str":"70073442803777536","coordinates":null,"geo":null,"in_reply_to_user_id":1665611,"id":70073442803777536,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"RT @refreshdc: New meetup! @robleto moderates a panel on Data-Driven Design. It's 7pm on 5\/19 at @viget. Register: http:\/\/bit.ly\/lSFOtw","created_at":"Fri May 13 16:58:42 +0000 2011","place":null,"id_str":"69084162224697345","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":69084162224697345,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":1,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"An Unreal Redesign: Epic Games Advances to the Next Level http:\/\/goo.gl\/fb\/V4zHb","created_at":"Fri May 06 16:15:44 +0000 2011","place":null,"id_str":"66536635411607553","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":66536635411607553,"source":"\u003Ca href=\"http:\/\/www.google.com\/support\/youtube\/bin\/answer.py?hl=en&answer=164577\" rel=\"nofollow\"\u003EGoogle\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"RT @emmerblue: I am going to be in Boulder, CO mid-May to mid-August helping to plant Viget West roots. Can't wait","created_at":"Fri May 06 12:04:38 +0000 2011","place":null,"id_str":"66473441385127936","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":66473441385127936,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":"65951045720879104","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"amwilkison","in_reply_to_user_id_str":"54078493","in_reply_to_status_id":65951045720879104,"contributors":null,"retweeted":false,"text":"@amwilkison @sbwilk In Latin viget means \"flourish\" ... or at least that's what someone told us once ... http:\/\/www.viget.com\/about\/","created_at":"Thu May 05 01:34:18 +0000 2011","place":null,"id_str":"65952425646882816","coordinates":null,"geo":null,"in_reply_to_user_id":54078493,"id":65952425646882816,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":"65539714400268289","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"jasonalley","in_reply_to_user_id_str":"9684092","in_reply_to_status_id":65539714400268289,"contributors":null,"retweeted":false,"text":"@jasonalley Oops -- thanks for the heads-up. Fixed!","created_at":"Wed May 04 03:10:36 +0000 2011","place":null,"id_str":"65614274487259136","coordinates":null,"geo":null,"in_reply_to_user_id":9684092,"id":65614274487259136,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"CrowChick","in_reply_to_user_id_str":"9550352","in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"@CrowChick Thank you, Rachel! Glad you enjoy them.","created_at":"Tue May 03 21:22:46 +0000 2011","place":null,"id_str":"65526737689264128","coordinates":null,"geo":null,"in_reply_to_user_id":9550352,"id":65526737689264128,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":"65515140048617473","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"CrowChick","in_reply_to_user_id_str":"9550352","in_reply_to_status_id":65515140048617473,"contributors":null,"retweeted":false,"text":"@CrowChick Ha -- thanks! We have fun with them.","created_at":"Tue May 03 20:50:29 +0000 2011","place":null,"id_str":"65518615293739009","coordinates":null,"geo":null,"in_reply_to_user_id":9550352,"id":65518615293739009,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"We're very pleased to welcome Rosalyn Metz to our stellar PM team! http:\/\/www.viget.com\/about\/team\/rmetz\/","created_at":"Tue May 03 20:30:30 +0000 2011","place":null,"id_str":"65513583827628032","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":65513583827628032,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":"65493558563586048","retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":"jakelear","in_reply_to_user_id_str":"20272317","in_reply_to_status_id":65493558563586048,"contributors":null,"retweeted":false,"text":"@jakelear Thank you. He was too good to pass up. He's already doing some awesome work over here.","created_at":"Tue May 03 19:12:38 +0000 2011","place":null,"id_str":"65493989465403392","coordinates":null,"geo":null,"in_reply_to_user_id":20272317,"id":65493989465403392,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":0,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"Good to see our friends @gofivo on @dcist -- GoFivo: Craft Beer On The Cheap http:\/\/t.co\/l9W2wKQ","created_at":"Tue May 03 02:09:20 +0000 2011","place":null,"id_str":"65236466015551488","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":65236466015551488,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":5,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"7 Ways Google Analytics Can Help Inform Design Decisions (by @anjalimerchant) #marketing http:\/\/goo.gl\/fb\/3n6gW","created_at":"Sun May 01 00:27:25 +0000 2011","place":null,"id_str":"64486042811641857","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":64486042811641857,"source":"\u003Ca href=\"http:\/\/www.google.com\/support\/youtube\/bin\/answer.py?hl=en&answer=164577\" rel=\"nofollow\"\u003EGoogle\u003C\/a\u003E","favorited":false,"truncated":false},{"in_reply_to_status_id_str":null,"retweet_count":1,"user":{"show_all_inline_media":false,"geo_enabled":false,"profile_link_color":"2776a1","protected":false,"location":"Wash DC, Durham NC, Boulder CO","profile_sidebar_border_color":"dad74e","name":"Viget Labs","follow_request_sent":null,"time_zone":"Eastern Time (US & Canada)","friends_count":42,"url":"http:\/\/viget.com","is_translator":false,"default_profile":false,"statuses_count":719,"profile_use_background_image":true,"utc_offset":-18000,"verified":false,"created_at":"Tue Mar 18 18:42:47 +0000 2008","profile_background_color":"14537f","description":"We design \/ build \/ market web sites \/ products \/ ideas.","lang":"en","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/3226205\/Untitled-1.jpg","listed_count":217,"id_str":"14171594","profile_text_color":"333333","id":14171594,"profile_sidebar_fill_color":"fdfab7","profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/62482819\/logo_normal.jpg","profile_background_tile":false,"favourites_count":0,"followers_count":1887,"default_profile_image":false,"contributors_enabled":false,"following":null,"notifications":null,"screen_name":"viget"},"in_reply_to_screen_name":null,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"retweeted":false,"text":"Cloning our PM is taking too long: http:\/\/yfrog.com\/h283esqpj So instead, we're trying this: http:\/\/bit.ly\/lQXBbD #recruiting","created_at":"Fri Apr 29 19:41:23 +0000 2011","place":null,"id_str":"64051672191729664","coordinates":null,"geo":null,"in_reply_to_user_id":null,"id":64051672191729664,"source":"\u003Ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003ETweetDeck\u003C\/a\u003E","favorited":false,"truncated":false}]
|
@@ -0,0 +1,40 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: https://api.twitter.com:443/1/statuses/bogus_timeline.json?screen_name=viget
|
6
|
+
body: !!null
|
7
|
+
headers: !!null
|
8
|
+
response: !ruby/struct:VCR::Response
|
9
|
+
status: !ruby/struct:VCR::ResponseStatus
|
10
|
+
code: 401
|
11
|
+
message: Unauthorized
|
12
|
+
headers:
|
13
|
+
date:
|
14
|
+
- Tue, 24 May 2011 20:54:42 GMT
|
15
|
+
server:
|
16
|
+
- hi
|
17
|
+
status:
|
18
|
+
- 401 Unauthorized
|
19
|
+
www-authenticate:
|
20
|
+
- OAuth realm="https://api.twitter.com"
|
21
|
+
x-runtime:
|
22
|
+
- '0.00250'
|
23
|
+
content-type:
|
24
|
+
- application/json; charset=utf-8
|
25
|
+
content-length:
|
26
|
+
- '104'
|
27
|
+
cache-control:
|
28
|
+
- no-cache, max-age=300
|
29
|
+
set-cookie:
|
30
|
+
- _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCAHCySMwAToHaWQiJWY5NjUwZDk2OGZjYzM5%250AMmNhNjIxYjAxZmEyZTc5OWNmIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--129022f5c334f13f162696a32a2af8bd1cd29313;
|
31
|
+
domain=.twitter.com; path=/; HttpOnly
|
32
|
+
- guest_id=13062704829444930; path=/; expires=Thu, 23 Jun 2011 20:54:42 GMT
|
33
|
+
- k=96.10.0.146.1306270482941465; path=/; expires=Tue, 31-May-11 20:54:42 GMT;
|
34
|
+
domain=.twitter.com
|
35
|
+
expires:
|
36
|
+
- Tue, 24 May 2011 20:59:42 GMT
|
37
|
+
vary:
|
38
|
+
- Accept-Encoding
|
39
|
+
body: ! '{"error":"Could not authenticate you.","request":"\/1\/statuses\/bogus_timeline.json?screen_name=viget"}'
|
40
|
+
http_version: '1.1'
|