gnip-stream 0.0.1
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/.gitignore +4 -0
- data/.pryrc +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +44 -0
- data/Rakefile +1 -0
- data/gnip-stream.gemspec +24 -0
- data/lib/gnip-stream/data_buffer.rb +22 -0
- data/lib/gnip-stream/error_reconnect.rb +25 -0
- data/lib/gnip-stream/facebook_client.rb +22 -0
- data/lib/gnip-stream/json_stream.rb +11 -0
- data/lib/gnip-stream/powertrack_authentication.rb +27 -0
- data/lib/gnip-stream/powertrack_client.rb +31 -0
- data/lib/gnip-stream/stream.rb +58 -0
- data/lib/gnip-stream/stream_delegate.rb +15 -0
- data/lib/gnip-stream/version.rb +3 -0
- data/lib/gnip-stream/xml_stream.rb +10 -0
- data/lib/gnip-stream.rb +12 -0
- data/spec/gnip-stream/data_buffer_spec.rb +26 -0
- data/spec/gnip-stream/error_reconnect_spec.rb +23 -0
- data/spec/gnip-stream/facebook_client_spec.rb +28 -0
- data/spec/gnip-stream/json_stream_spec.rb +31 -0
- data/spec/gnip-stream/powertrack_authentication_spec.rb +34 -0
- data/spec/gnip-stream/powertrack_client_spec.rb +57 -0
- data/spec/gnip-stream/stream_spec.rb +59 -0
- data/spec/gnip-stream/xml_stream_spec.rb +30 -0
- data/spec/spec_helper.rb +4 -0
- metadata +105 -0
data/.gitignore
ADDED
data/.pryrc
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@gnip-stream --create
|
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
script: "bundle exec rspec spec/"
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) Sharethrough
|
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.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# gnip-stream
|
2
|
+
[](http://travis-ci.org/rweald/gnip-stream)
|
3
|
+
|
4
|
+
gnip-stream is a ruby library to connect and stream data from [GNIP](http://gnip.com/).
|
5
|
+
It utilizes EventMachine and threads under the hood to provide a true streaming
|
6
|
+
experience without you having to worry about writing non blocking code.
|
7
|
+
|
8
|
+
##Installation
|
9
|
+
|
10
|
+
Installing gnip-stream is easy. Simply add the following line to your
|
11
|
+
```Gemfile```:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'gnip-stream', :git => "https://github.com/rweald/gnip-stream"
|
15
|
+
```
|
16
|
+
|
17
|
+
##Simple Usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'gnip-stream'
|
21
|
+
|
22
|
+
#To connect to the special twitter powertrack api
|
23
|
+
twitter_stream = GnipStream::PowertrackClient.new("http://yourstreamingurl.gnip.com", "someuser", "password")
|
24
|
+
twitter_stream.consume do |message|
|
25
|
+
#process the message however you want
|
26
|
+
puts message
|
27
|
+
end
|
28
|
+
|
29
|
+
#To Connect to the Facebook API
|
30
|
+
facebook_stream = GnipStream::FacebookClient.new("http://yourstreamingurl.gnip.com", "someuser", "password")
|
31
|
+
facebook_stream.consume do |message|
|
32
|
+
puts message
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
##Contributors
|
37
|
+
|
38
|
+
* [Ryan Weald](https://github.com/rweald)
|
39
|
+
* [Sharethrough Team](https://github.com/sharethrough)
|
40
|
+
|
41
|
+
##License
|
42
|
+
MIT. See [LICENSE](https://github.com/rweald/gnip-stream/blob/master/LICENSE) file for more details.
|
43
|
+
|
44
|
+
Special thanks to [Sharethrough](http://www.sharethrough.com/)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/gnip-stream.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "gnip-stream/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "gnip-stream"
|
7
|
+
s.version = GnipStream::VERSION
|
8
|
+
s.authors = ["Ryan Weald"]
|
9
|
+
s.email = ["ryan@weald.com"]
|
10
|
+
s.homepage = "https://github.com/rweald/gnip-stream"
|
11
|
+
s.summary = %q{}
|
12
|
+
s.description = %q{}
|
13
|
+
|
14
|
+
s.rubyforge_project = "gnip-stream"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
|
23
|
+
s.add_dependency "em-http-request", ">= 1.0.0"
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module GnipStream
|
2
|
+
class DataBuffer
|
3
|
+
attr_accessor :pattern
|
4
|
+
def initialize(pattern)
|
5
|
+
@pattern = pattern
|
6
|
+
@buffer = ""
|
7
|
+
end
|
8
|
+
|
9
|
+
def process(chunk)
|
10
|
+
@buffer.concat(chunk)
|
11
|
+
end
|
12
|
+
|
13
|
+
def complete_entries
|
14
|
+
entries = []
|
15
|
+
while (match_data = @buffer.match(@pattern))
|
16
|
+
entries << match_data.captures[0]
|
17
|
+
@buffer = match_data.captures[1]
|
18
|
+
end
|
19
|
+
entries
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GnipStream
|
2
|
+
class ErrorReconnect
|
3
|
+
def initialize(source_class, method_name)
|
4
|
+
@source_class = source_class
|
5
|
+
@method_name = method_name
|
6
|
+
@reconnect_attempts = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def attempt_to_reconnect(error_message)
|
10
|
+
@error_message = error_message
|
11
|
+
if @reconnect_attempts < 5
|
12
|
+
@reconnect_attempts +=1
|
13
|
+
sleep(2)
|
14
|
+
@source_class.send(@method_name)
|
15
|
+
else
|
16
|
+
reconnect_failed_raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def reconnect_failed_raise_error
|
21
|
+
raise @error_message
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'gnip-stream/xml_stream'
|
2
|
+
|
3
|
+
module GnipStream
|
4
|
+
class FacebookClient
|
5
|
+
def initialize(url, username, password)
|
6
|
+
@stream = XmlStream.new(url, "authorization" => [username, password])
|
7
|
+
@error_handler = ErrorReconnect.new(self, :consume)
|
8
|
+
@connection_close_handler = ErrorReconnect.new(self, :consume)
|
9
|
+
configure_handlers
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_handlers
|
13
|
+
@stream.on_error { |error| @error_handler.attempt_to_reconnect("Gnip Connection Error. Reason was: #{error.inspect}") }
|
14
|
+
@stream.on_connection_close { @connection_close_handler.attempt_to_reconnect("Gnip Connection Closed") }
|
15
|
+
end
|
16
|
+
|
17
|
+
def consume(&block)
|
18
|
+
@stream.on_message(&block)
|
19
|
+
@stream.connect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'gnip-stream/stream_delegate'
|
2
|
+
|
3
|
+
module GnipStream
|
4
|
+
class JsonStream
|
5
|
+
include StreamDelegate
|
6
|
+
def initialize(url, headers={})
|
7
|
+
json_processor = DataBuffer.new(Regexp.new(/^(\{.*\})\s\s(.*)/))
|
8
|
+
@stream = Stream.new(url, json_processor, headers)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module GnipStream
|
2
|
+
class PowertrackAuthentication
|
3
|
+
attr_accessor :cookies, :location
|
4
|
+
def initialize(url, username, password)
|
5
|
+
@url = url
|
6
|
+
@username = username
|
7
|
+
@password = password
|
8
|
+
end
|
9
|
+
|
10
|
+
def authenticate
|
11
|
+
EM.run do
|
12
|
+
http = EM::HttpRequest.new(@url).get(
|
13
|
+
:head => {"authorization" => [@username, @password]})
|
14
|
+
http.headers { |head| parse_response_header(head) }
|
15
|
+
http.callback { EM.stop }
|
16
|
+
http.error do
|
17
|
+
raise "Gnip Authentication Failed. Reason was #{http.error}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_response_header(header)
|
23
|
+
@location = header["LOCATION"]
|
24
|
+
@cookies = (header["SET_COOKIE"].first.split(";")[0..2].join(";"))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'gnip-stream/powertrack_authentication'
|
2
|
+
module GnipStream
|
3
|
+
class PowertrackClient
|
4
|
+
def initialize(url, username, password)
|
5
|
+
@authentication = PowertrackAuthentication.new(url, username, password)
|
6
|
+
@stream = JsonStream.new(url)
|
7
|
+
@error_handler = ErrorReconnect.new(self, :consume)
|
8
|
+
@connection_close_handler = ErrorReconnect.new(self, :consume)
|
9
|
+
configure_handlers
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_handlers
|
13
|
+
@stream.on_error { |error| @error_handler.attempt_to_reconnect("Gnip Connection Error. Reason was: #{error.inspect}") }
|
14
|
+
@stream.on_connection_close { @connection_close_handler.attempt_to_reconnect("Gnip Connection Closed") }
|
15
|
+
end
|
16
|
+
|
17
|
+
def consume(&block)
|
18
|
+
@client_callback = block
|
19
|
+
@stream.on_message(&@client_callback)
|
20
|
+
authenticate
|
21
|
+
@stream.connect
|
22
|
+
end
|
23
|
+
|
24
|
+
def authenticate
|
25
|
+
@authentication.authenticate
|
26
|
+
@stream.url = @authentication.location
|
27
|
+
@stream.headers = {"cookie" => @authentication.cookies}
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'em-http-request'
|
3
|
+
|
4
|
+
module GnipStream
|
5
|
+
class Stream
|
6
|
+
|
7
|
+
attr_accessor :headers, :options, :url, :username, :password
|
8
|
+
|
9
|
+
def initialize(url, processor, headers={})
|
10
|
+
@url = url
|
11
|
+
@headers = headers
|
12
|
+
@processor = processor
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_message(&block)
|
16
|
+
@on_message = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_connection_close(&block)
|
20
|
+
@on_connection_close = block
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_error(&block)
|
24
|
+
@on_error = block
|
25
|
+
end
|
26
|
+
|
27
|
+
def connect
|
28
|
+
EM.run do
|
29
|
+
http = EM::HttpRequest.new(@url, :inactivity_timeout => 0).get(:head => @headers)
|
30
|
+
http.stream { |chunk| process_chunk(chunk) }
|
31
|
+
http.callback {
|
32
|
+
handle_connection_close(http)
|
33
|
+
EM.stop
|
34
|
+
}
|
35
|
+
http.errback {
|
36
|
+
handle_error(http)
|
37
|
+
EM.stop
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_chunk(chunk)
|
43
|
+
@processor.process(chunk)
|
44
|
+
@processor.complete_entries.each do |entry|
|
45
|
+
EM.defer { @on_message.call(entry) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def handle_error(http_connection)
|
50
|
+
@on_error.call(http_connection)
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_connection_close(http_connection)
|
54
|
+
@on_connection_close.call(http_connection)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GnipStream
|
2
|
+
|
3
|
+
module StreamDelegate
|
4
|
+
#Magic Method that will delegate all
|
5
|
+
# method calls to underlying stream if possible
|
6
|
+
def method_missing(m, *args, &block)
|
7
|
+
if @stream.respond_to?(m)
|
8
|
+
@stream.send(m, *args, &block)
|
9
|
+
else
|
10
|
+
super(m, *args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'gnip-stream/stream_delegate'
|
2
|
+
module GnipStream
|
3
|
+
class XmlStream
|
4
|
+
include StreamDelegate
|
5
|
+
def initialize(url, headers={})
|
6
|
+
xml_processor = DataBuffer.new(Regexp.new(/^(\<entry.*?\<\/entry\>)(.*)/m))
|
7
|
+
@stream = Stream.new(url, xml_processor, headers)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/gnip-stream.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "gnip-stream/version"
|
2
|
+
|
3
|
+
require 'gnip-stream/stream'
|
4
|
+
require 'gnip-stream/data_buffer'
|
5
|
+
require 'gnip-stream/json_stream'
|
6
|
+
require 'gnip-stream/xml_stream'
|
7
|
+
require 'gnip-stream/powertrack_client'
|
8
|
+
require 'gnip-stream/facebook_client'
|
9
|
+
require 'gnip-stream/error_reconnect'
|
10
|
+
|
11
|
+
module GnipStream
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/data_buffer'
|
3
|
+
|
4
|
+
describe GnipStream::DataBuffer do
|
5
|
+
subject { GnipStream::DataBuffer.new(/(test)(.*)/) }
|
6
|
+
describe "#initialize" do
|
7
|
+
it "accepts a regex pattern that will be used to match complete entries" do
|
8
|
+
pattern = Regexp.new(/hello/)
|
9
|
+
GnipStream::DataBuffer.new(pattern).pattern.should == pattern
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#process" do
|
14
|
+
it "appends the data to the buffer" do
|
15
|
+
subject.process("hello")
|
16
|
+
subject.instance_variable_get(:@buffer).should == "hello"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#complete_entries" do
|
21
|
+
it "returns a list of complete entries" do
|
22
|
+
subject.process("test")
|
23
|
+
subject.complete_entries.should == ["test"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/error_reconnect'
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
describe GnipStream::ErrorReconnect do
|
7
|
+
let(:fake_stream) { double("fake stream that causes errors") }
|
8
|
+
subject { GnipStream::ErrorReconnect.new(fake_stream, :connect) }
|
9
|
+
before { subject.stub(:sleep) }
|
10
|
+
describe "#attempt_to_reconnect" do
|
11
|
+
it "should call the specified method on the class generating the error if reconnect count is less than 5" do
|
12
|
+
fake_stream.should_receive(:connect)
|
13
|
+
subject.attempt_to_reconnect("failed to reconnect")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise an error with the specified error_message if reconnect fails maximum number of times" do
|
17
|
+
subject.instance_variable_set(:@reconnect_attempts, 6)
|
18
|
+
lambda {subject.attempt_to_reconnect("failed to reconnect")}.should raise_error(/reconnect/)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/facebook_client'
|
3
|
+
|
4
|
+
describe GnipStream::FacebookClient do
|
5
|
+
let(:fake_stream) { double("GnipStream::XmlStream").as_null_object }
|
6
|
+
before { GnipStream::XmlStream.stub(:new => fake_stream) }
|
7
|
+
subject { GnipStream::FacebookClient.new("http://example.com", "user", "password") }
|
8
|
+
|
9
|
+
describe "#consume" do
|
10
|
+
it "setup the client callback" do
|
11
|
+
fake_stream.should_receive(:on_message)
|
12
|
+
subject.consume
|
13
|
+
end
|
14
|
+
|
15
|
+
it "connects to the stream" do
|
16
|
+
fake_stream.should_receive(:connect)
|
17
|
+
subject.consume
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "configure_handlers" do
|
22
|
+
it "sets up the appropriate error and close handlers" do
|
23
|
+
fake_stream.should_receive(:on_error).twice
|
24
|
+
fake_stream.should_receive(:on_connection_close).twice
|
25
|
+
subject.configure_handlers
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/json_stream'
|
3
|
+
|
4
|
+
describe GnipStream::JsonStream do
|
5
|
+
subject { GnipStream::JsonStream.new("http://example.com") }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
it "creates underlying stream object with a json specific data buffer" do
|
9
|
+
GnipStream::Stream.should_receive(:new) do |url, processor, headers|
|
10
|
+
url.should == "http://example.com"
|
11
|
+
end
|
12
|
+
GnipStream::JsonStream.new("http://example.com")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#method_missing" do
|
17
|
+
let(:underlying_stream) { double("GnipStream::Stream") }
|
18
|
+
before do
|
19
|
+
GnipStream::Stream.stub(:new => underlying_stream)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "delegates all available methods to the underlying stream class" do
|
23
|
+
underlying_stream.should_receive(:connect)
|
24
|
+
subject.connect
|
25
|
+
end
|
26
|
+
|
27
|
+
it "raises a method not found error on self if underlying stream can not respond to the method" do
|
28
|
+
lambda { subject.foobar }.should raise_error(NoMethodError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/powertrack_authentication'
|
3
|
+
|
4
|
+
describe GnipStream::PowertrackAuthentication do
|
5
|
+
subject { GnipStream::PowertrackAuthentication.new("http://example.com",
|
6
|
+
"user", "password") }
|
7
|
+
describe "#authenticate" do
|
8
|
+
let(:fake_request) { double("fake request") }
|
9
|
+
it "should make a request to the GNIP API to receive access cookie" do
|
10
|
+
EM::HttpRequest.should_receive(:new).with("http://example.com").and_return(fake_request)
|
11
|
+
fake_request.should_receive(:get) do |args|
|
12
|
+
args[:head].should == {'authorization' => ["user", "password"]}
|
13
|
+
EM.stop
|
14
|
+
double.as_null_object
|
15
|
+
end
|
16
|
+
|
17
|
+
subject.authenticate
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#parse_response_header" do
|
22
|
+
it "should set the stream url based on 'LOCATION' header" do
|
23
|
+
subject.parse_response_header({"SET_COOKIE" => ["session_token=foobar; domain=.gnip.com; path=/;
|
24
|
+
expires=Wed, 13-Jul-2011 22:10:10 GMT _base_session=hello; path=/; HttpOnly"]})
|
25
|
+
subject.cookies.should == "session_token=foobar; domain=.gnip.com; path=/"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should set the url that we can stream data from" do
|
29
|
+
subject.parse_response_header("LOCATION" => "http://example.com", "SET_COOKIE" => ["session_token=foobar; domain=.gnip.com; path=/;
|
30
|
+
expires=Wed, 13-Jul-2011 22:10:10 GMT _base_session=hello; path=/; HttpOnly"])
|
31
|
+
subject.location.should == "http://example.com"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/powertrack_client'
|
3
|
+
|
4
|
+
describe GnipStream::PowertrackClient do
|
5
|
+
let(:fake_stream) { double("GnipStream::JsonStream").as_null_object }
|
6
|
+
let(:fake_auth) { double("GnipStream::PowertrackAuthentication").as_null_object }
|
7
|
+
before do
|
8
|
+
GnipStream::JsonStream.stub(:new => fake_stream)
|
9
|
+
GnipStream::PowertrackAuthentication.stub(:new => fake_auth)
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { GnipStream::PowertrackClient.new("http://example.com", "user", "password") }
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "initializes a PowertrackAuthentication instance" do
|
16
|
+
GnipStream::PowertrackAuthentication.should_receive(:new)
|
17
|
+
subject
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes an instance JsonStream" do
|
21
|
+
GnipStream::JsonStream.should_receive(:new)
|
22
|
+
subject
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "configure_handlers" do
|
27
|
+
it "sets up the appropriate error and close handlers" do
|
28
|
+
fake_stream.should_receive(:on_error).twice
|
29
|
+
fake_stream.should_receive(:on_connection_close).twice
|
30
|
+
subject.configure_handlers
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#authenticate" do
|
35
|
+
it "performs the necessary authentication and passes appropriate credentials to stream" do
|
36
|
+
fake_auth.should_receive(:authenticate)
|
37
|
+
fake_auth.should_receive(:location).and_return("http://example.com")
|
38
|
+
fake_auth.should_receive(:cookies).and_return("some cookie")
|
39
|
+
|
40
|
+
fake_stream.should_receive(:url=).with("http://example.com")
|
41
|
+
fake_stream.should_receive(:headers=)
|
42
|
+
subject.authenticate
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#consume" do
|
47
|
+
it "setup the client callback" do
|
48
|
+
fake_stream.should_receive(:on_message)
|
49
|
+
subject.consume
|
50
|
+
end
|
51
|
+
|
52
|
+
it "connects to the stream" do
|
53
|
+
fake_stream.should_receive(:connect)
|
54
|
+
subject.consume
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'gnip-stream/stream'
|
4
|
+
|
5
|
+
describe GnipStream::Stream do
|
6
|
+
let(:fake_processor) { double("json processor", :process => self,
|
7
|
+
:complete_entries => ["hello"])}
|
8
|
+
subject { GnipStream::Stream.new("http://example.com", fake_processor) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "allows you to define custom headers" do
|
12
|
+
headers = {"keep-alive" => false}
|
13
|
+
stream = GnipStream::Stream.new("http://example.com", fake_processor, headers)
|
14
|
+
stream.headers.should == headers
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#on_message" do
|
19
|
+
let(:on_message_block) { proc{ puts "hello world" } }
|
20
|
+
it "accepts a block that will be called every time a message is received" do
|
21
|
+
subject.on_message(&on_message_block)
|
22
|
+
subject.instance_variable_get(:@on_message).should == on_message_block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#on_connection_close" do
|
27
|
+
let(:on_connection_close_block) { proc{ puts "hello world" } }
|
28
|
+
it "accepts a block that will be called every time a message is received" do
|
29
|
+
subject.on_connection_close(&on_connection_close_block)
|
30
|
+
subject.instance_variable_get(:@on_connection_close).should == on_connection_close_block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#on_error" do
|
35
|
+
let(:on_error_block) { proc{ puts "hello world" } }
|
36
|
+
it "accepts a block that will be called every time a message is received" do
|
37
|
+
subject.on_error(&on_error_block)
|
38
|
+
subject.instance_variable_get(:@on_error).should == on_error_block
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#process_chunk" do
|
43
|
+
let(:on_message_block) { proc{ |message| message.to_s } }
|
44
|
+
before do
|
45
|
+
subject.on_message(&on_message_block)
|
46
|
+
EM.stub(:defer)
|
47
|
+
end
|
48
|
+
it "passes the chunk of data off to the processor object for processing" do
|
49
|
+
fake_processor.should_receive(:process).with("hello world")
|
50
|
+
subject.process_chunk("hello world")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "calls the client supplied callback on a seperate thread for each message" do
|
54
|
+
EventMachine.should_receive(:defer)
|
55
|
+
subject.process_chunk("hello")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/xml_stream'
|
3
|
+
|
4
|
+
describe GnipStream::XmlStream do
|
5
|
+
subject { GnipStream::XmlStream.new("http://example.com") }
|
6
|
+
describe "#initialize" do
|
7
|
+
it "creates underlying stream object with a json specific data buffer" do
|
8
|
+
GnipStream::Stream.should_receive(:new) do |url, processor, headers|
|
9
|
+
url.should == "http://example.com"
|
10
|
+
end
|
11
|
+
GnipStream::XmlStream.new("http://example.com")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#method_missing" do
|
16
|
+
let(:underlying_stream) { double("GnipStream::Stream") }
|
17
|
+
before do
|
18
|
+
GnipStream::Stream.stub(:new => underlying_stream)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "delegates all available methods to the underlying stream class" do
|
22
|
+
underlying_stream.should_receive(:connect)
|
23
|
+
subject.connect
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises a method not found error on self if underlying stream can not respond to the method" do
|
27
|
+
lambda { subject.foobar }.should raise_error(NoMethodError)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gnip-stream
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Weald
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-21 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70139514960160 !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: *70139514960160
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: em-http-request
|
27
|
+
requirement: &70139514958620 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70139514958620
|
36
|
+
description: ''
|
37
|
+
email:
|
38
|
+
- ryan@weald.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .pryrc
|
45
|
+
- .rvmrc
|
46
|
+
- .travis.yml
|
47
|
+
- Gemfile
|
48
|
+
- LICENSE
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- gnip-stream.gemspec
|
52
|
+
- lib/gnip-stream.rb
|
53
|
+
- lib/gnip-stream/data_buffer.rb
|
54
|
+
- lib/gnip-stream/error_reconnect.rb
|
55
|
+
- lib/gnip-stream/facebook_client.rb
|
56
|
+
- lib/gnip-stream/json_stream.rb
|
57
|
+
- lib/gnip-stream/powertrack_authentication.rb
|
58
|
+
- lib/gnip-stream/powertrack_client.rb
|
59
|
+
- lib/gnip-stream/stream.rb
|
60
|
+
- lib/gnip-stream/stream_delegate.rb
|
61
|
+
- lib/gnip-stream/version.rb
|
62
|
+
- lib/gnip-stream/xml_stream.rb
|
63
|
+
- spec/gnip-stream/data_buffer_spec.rb
|
64
|
+
- spec/gnip-stream/error_reconnect_spec.rb
|
65
|
+
- spec/gnip-stream/facebook_client_spec.rb
|
66
|
+
- spec/gnip-stream/json_stream_spec.rb
|
67
|
+
- spec/gnip-stream/powertrack_authentication_spec.rb
|
68
|
+
- spec/gnip-stream/powertrack_client_spec.rb
|
69
|
+
- spec/gnip-stream/stream_spec.rb
|
70
|
+
- spec/gnip-stream/xml_stream_spec.rb
|
71
|
+
- spec/spec_helper.rb
|
72
|
+
homepage: https://github.com/rweald/gnip-stream
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: gnip-stream
|
92
|
+
rubygems_version: 1.8.10
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: ''
|
96
|
+
test_files:
|
97
|
+
- spec/gnip-stream/data_buffer_spec.rb
|
98
|
+
- spec/gnip-stream/error_reconnect_spec.rb
|
99
|
+
- spec/gnip-stream/facebook_client_spec.rb
|
100
|
+
- spec/gnip-stream/json_stream_spec.rb
|
101
|
+
- spec/gnip-stream/powertrack_authentication_spec.rb
|
102
|
+
- spec/gnip-stream/powertrack_client_spec.rb
|
103
|
+
- spec/gnip-stream/stream_spec.rb
|
104
|
+
- spec/gnip-stream/xml_stream_spec.rb
|
105
|
+
- spec/spec_helper.rb
|