http_tracker 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/mongodb.rb +46 -0
- data/examples/simple_tracker.rb +20 -0
- data/lib/http_tracker/class_methods.rb +32 -0
- data/lib/http_tracker/manager.rb +50 -0
- data/lib/http_tracker.rb +2 -0
- data/spec/helpers/request_helper.rb +26 -0
- data/spec/http_tracker/manager_spec.rb +149 -0
- data/spec/spec_helper.rb +18 -0
- metadata +105 -0
data/examples/mongodb.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "http_tracker"
|
3
|
+
require "sinatra"
|
4
|
+
require "pp"
|
5
|
+
require "mongo"
|
6
|
+
|
7
|
+
class MongoTracker
|
8
|
+
include Mongo
|
9
|
+
|
10
|
+
def valid?(env); true; end
|
11
|
+
|
12
|
+
def on_request(env)
|
13
|
+
storage.save \
|
14
|
+
"ip" => env["REMOTE_ADDR"],
|
15
|
+
"path_info" => env["PATH_INFO"],
|
16
|
+
"method" => env["REQUEST_METHOD"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_response(env, status, headers, body)
|
20
|
+
puts "Total requests made: #{storage.count}"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def storage
|
25
|
+
@storage ||= begin
|
26
|
+
db_name, collection_name = "http_tracker_examples", "test"
|
27
|
+
|
28
|
+
connection = Connection.new.db(db_name)
|
29
|
+
unless connection.collection_names.include?(collection_name)
|
30
|
+
connection.create_collection(collection_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
connection.collection(collection_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
HTTPTracker::Manager.add(:mongo, MongoTracker)
|
39
|
+
|
40
|
+
use HTTPTracker::Manager
|
41
|
+
|
42
|
+
get "/foo" do
|
43
|
+
":-)"
|
44
|
+
end
|
45
|
+
|
46
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "http_tracker"
|
3
|
+
require "sinatra"
|
4
|
+
require "pp"
|
5
|
+
|
6
|
+
HTTPTracker::Manager.add(:simple) do
|
7
|
+
def valid?(env); true; end
|
8
|
+
|
9
|
+
def on_request(env)
|
10
|
+
pp env
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
use HTTPTracker::Manager
|
15
|
+
|
16
|
+
get "/foo" do
|
17
|
+
":-)"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module HTTPTracker
|
2
|
+
module ClassMethods
|
3
|
+
def add(label, klass = nil, &block)
|
4
|
+
if label.is_a?(Class) || (klass.nil? && !block_given?)
|
5
|
+
raise ArgumentError,
|
6
|
+
"A class or a block should be passed along with the tracker label."
|
7
|
+
end
|
8
|
+
|
9
|
+
klass ||= Class.new
|
10
|
+
if block_given?
|
11
|
+
klass.class_eval(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
tracker = klass.new
|
15
|
+
|
16
|
+
if !tracker.respond_to?(:on_request) && !tracker.respond_to?(:on_response)
|
17
|
+
raise ArgumentError,
|
18
|
+
"You should implement one of the following methods: on_response, on_request."
|
19
|
+
end
|
20
|
+
|
21
|
+
trackers[label] = klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def trackers
|
25
|
+
@trackers ||= {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear!
|
29
|
+
@trackers = {}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module HTTPTracker
|
2
|
+
class Manager
|
3
|
+
extend ClassMethods
|
4
|
+
|
5
|
+
def initialize(app, options = {})
|
6
|
+
@app, @options = app, options
|
7
|
+
initialize_trackers
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
run_on_request_callbacks!(env)
|
12
|
+
|
13
|
+
status, headers, body = @app.call(env)
|
14
|
+
|
15
|
+
run_on_response_callbacks!(env, status, headers, body)
|
16
|
+
|
17
|
+
[status, headers, body]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def initialize_trackers
|
22
|
+
trackers.each_pair do |label, tracker_klass|
|
23
|
+
trackers[label] = tracker_klass.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def trackers
|
28
|
+
self.class.trackers
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_on_request_callbacks!(env)
|
32
|
+
run_callbacks(:request, env)
|
33
|
+
end
|
34
|
+
|
35
|
+
def run_on_response_callbacks!(env, status, headers, body)
|
36
|
+
run_callbacks(:response, env, status, headers, body)
|
37
|
+
end
|
38
|
+
|
39
|
+
def run_callbacks(name, *args)
|
40
|
+
env = args.first
|
41
|
+
method = "on_#{name}"
|
42
|
+
|
43
|
+
trackers.each_pair do |label, tracker|
|
44
|
+
if tracker.valid?(env) && tracker.respond_to?(method)
|
45
|
+
tracker.send(method, *args)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/http_tracker.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module HTTPTracker::Spec
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
# Stolen from Warden http://github.com/hassox/warden
|
5
|
+
def env_with_params(path = "/", params = {}, env = {})
|
6
|
+
method = params.delete(:method) || "GET"
|
7
|
+
env = { 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => "#{method}" }.merge(env)
|
8
|
+
Rack::MockRequest.env_for("#{path}?#{Rack::Utils.build_query(params)}", env)
|
9
|
+
end
|
10
|
+
|
11
|
+
def basic_app
|
12
|
+
lambda do |env|
|
13
|
+
[200, { "Content-Type" => "text/html" }, "yes!"]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_rack(middleware_class, options = {}, &block)
|
18
|
+
app ||= block_given? ? block : basic_app
|
19
|
+
Rack::Builder.new do
|
20
|
+
use middleware_class, options
|
21
|
+
run app
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Manager do
|
4
|
+
after do
|
5
|
+
HTTPTracker::Manager.clear!
|
6
|
+
end
|
7
|
+
|
8
|
+
context "when adding new trackers" do
|
9
|
+
it "should be able to add trackers passing blocks" do
|
10
|
+
HTTPTracker::Manager.add(:foo) do
|
11
|
+
def valid?; end
|
12
|
+
def on_request; end
|
13
|
+
def on_response; end
|
14
|
+
end
|
15
|
+
|
16
|
+
HTTPTracker::Manager.trackers.should have(1).trackers
|
17
|
+
klass = HTTPTracker::Manager.trackers[:foo]
|
18
|
+
|
19
|
+
tracker = klass.new
|
20
|
+
tracker.respond_to?(:valid?).should be_true
|
21
|
+
tracker.respond_to?(:on_request).should be_true
|
22
|
+
tracker.respond_to?(:on_response).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be able to add trackers using classes" do
|
26
|
+
klass = Class.new do
|
27
|
+
def valid?; end
|
28
|
+
def on_request; end
|
29
|
+
def on_response; end
|
30
|
+
end
|
31
|
+
HTTPTracker::Manager.add(:foo, klass)
|
32
|
+
|
33
|
+
klass = HTTPTracker::Manager.trackers[:foo]
|
34
|
+
|
35
|
+
tracker = klass.new
|
36
|
+
tracker.respond_to?(:valid?).should be_true
|
37
|
+
tracker.respond_to?(:on_request).should be_true
|
38
|
+
tracker.respond_to?(:on_response).should be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should raise an error if a name and a class aren't provided" do
|
42
|
+
lambda {
|
43
|
+
HTTPTracker::Manager.add(Class.new)
|
44
|
+
}.should raise_error
|
45
|
+
|
46
|
+
lambda {
|
47
|
+
HTTPTracker::Manager.add("foo")
|
48
|
+
}.should raise_error
|
49
|
+
end
|
50
|
+
|
51
|
+
it "it should make the #valid? method obligatory" do
|
52
|
+
lambda {
|
53
|
+
HTTPTracker::Manager.add(:foo) do
|
54
|
+
def valid?; end
|
55
|
+
end
|
56
|
+
}.should raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should be obligatory to implement on of the following methods: #on_request, #on_response" do
|
60
|
+
lambda {
|
61
|
+
HTTPTracker::Manager.add(:foo) do
|
62
|
+
def valid?; end
|
63
|
+
def on_request; end
|
64
|
+
end
|
65
|
+
}.should_not raise_error
|
66
|
+
|
67
|
+
lambda {
|
68
|
+
HTTPTracker::Manager.add(:foo) do
|
69
|
+
def valid?; end
|
70
|
+
def on_response; end
|
71
|
+
end
|
72
|
+
}.should_not raise_error
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when processing a request" do
|
78
|
+
before do
|
79
|
+
HTTPTracker::Manager.add(:foo) do
|
80
|
+
def valid?(env)
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
def on_request(env)
|
85
|
+
@x = 5
|
86
|
+
end
|
87
|
+
|
88
|
+
def on_response(env, status, headers, body)
|
89
|
+
@y = 10
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
HTTPTracker::Manager.add(:invalid) do
|
94
|
+
def valid?(env)
|
95
|
+
false
|
96
|
+
end
|
97
|
+
|
98
|
+
def on_request(env)
|
99
|
+
@NOT = 666
|
100
|
+
end
|
101
|
+
|
102
|
+
def on_response(env, status, headers, body)
|
103
|
+
@SHOULD_NOT_BE_SET = "SERIOUSLY"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
@app = setup_rack(HTTPTracker::Manager)
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when in middle of resquests" do
|
111
|
+
it "should initialize its trackers before processing the request" do
|
112
|
+
foo_tracker = HTTPTracker::Manager.trackers[:foo]
|
113
|
+
|
114
|
+
[:valid?, :on_request, :on_response].each do |method|
|
115
|
+
foo_tracker.respond_to?(method).should be_false
|
116
|
+
end
|
117
|
+
|
118
|
+
@app.call(env_with_params)
|
119
|
+
|
120
|
+
foo_tracker = HTTPTracker::Manager.trackers[:foo]
|
121
|
+
[:valid?, :on_request, :on_response].each do |method|
|
122
|
+
foo_tracker.respond_to?(method).should be_true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should never initialize its trackers more than once"
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should should run its before callbacks before processing the request" do
|
131
|
+
@app.call(env_with_params)
|
132
|
+
foo_tracker = HTTPTracker::Manager.trackers[:foo]
|
133
|
+
foo_tracker.instance_variable_get("@x").should == 5
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should should run its after callbacks before processing the request" do
|
137
|
+
@app.call(env_with_params)
|
138
|
+
foo_tracker = HTTPTracker::Manager.trackers[:foo]
|
139
|
+
foo_tracker.instance_variable_get("@y").should == 10
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should only execute the callbacks if the tracker is valid the environment" do
|
143
|
+
@app.call(env_with_params)
|
144
|
+
invalid_tracker = HTTPTracker::Manager.trackers[:invalid]
|
145
|
+
invalid_tracker.instance_variable_get("@SHOULD_NOT_BE_SET").should be_nil
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "http_tracker"
|
6
|
+
require "rspec"
|
7
|
+
require "rack"
|
8
|
+
require "pp"
|
9
|
+
|
10
|
+
Dir[File.join(File.dirname(__FILE__), "helpers", "**/*.rb")].each do |f|
|
11
|
+
require f
|
12
|
+
end
|
13
|
+
|
14
|
+
include HTTPTracker
|
15
|
+
|
16
|
+
Rspec.configure do |config|
|
17
|
+
config.include(HTTPTracker::Spec::Helpers)
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: http_tracker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dalto Curvelano Junior
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-07 00:00:00 -03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rack
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description:
|
50
|
+
email:
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- lib/http_tracker/class_methods.rb
|
59
|
+
- lib/http_tracker/manager.rb
|
60
|
+
- lib/http_tracker.rb
|
61
|
+
- spec/helpers/request_helper.rb
|
62
|
+
- spec/http_tracker/manager_spec.rb
|
63
|
+
- spec/spec_helper.rb
|
64
|
+
- examples/mongodb.rb
|
65
|
+
- examples/simple_tracker.rb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/dlt/request_tracker
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 3
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.5.2
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: A simple and modular rack middleware to track http requests
|
100
|
+
test_files:
|
101
|
+
- spec/helpers/request_helper.rb
|
102
|
+
- spec/http_tracker/manager_spec.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
- examples/mongodb.rb
|
105
|
+
- examples/simple_tracker.rb
|