request_visualizer 0.0.2

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/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'ey_api_hmac', '>= 0.4.0'
7
+ gem "sinatra"
8
+ gem 'rspec'
9
+ gem 'capybara'
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ request_visualizer (0.0.1)
5
+ colored
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ capybara (1.1.2)
11
+ mime-types (>= 1.16)
12
+ nokogiri (>= 1.3.3)
13
+ rack (>= 1.0.0)
14
+ rack-test (>= 0.5.4)
15
+ selenium-webdriver (~> 2.0)
16
+ xpath (~> 0.1.4)
17
+ childprocess (0.3.1)
18
+ ffi (~> 1.0.6)
19
+ colored (1.2)
20
+ diff-lcs (1.1.3)
21
+ ey_api_hmac (0.4.4)
22
+ json
23
+ rack-client
24
+ rack-idempotent (>= 0.0.3)
25
+ ffi (1.0.11)
26
+ json (1.6.5)
27
+ mime-types (1.17.2)
28
+ multi_json (1.1.0)
29
+ nokogiri (1.5.2)
30
+ rack (1.4.1)
31
+ rack-client (0.4.0)
32
+ rack (>= 1.0.0)
33
+ rack-idempotent (0.0.3)
34
+ rack-protection (1.2.0)
35
+ rack
36
+ rack-test (0.6.1)
37
+ rack (>= 1.0)
38
+ rspec (2.8.0)
39
+ rspec-core (~> 2.8.0)
40
+ rspec-expectations (~> 2.8.0)
41
+ rspec-mocks (~> 2.8.0)
42
+ rspec-core (2.8.0)
43
+ rspec-expectations (2.8.0)
44
+ diff-lcs (~> 1.1.2)
45
+ rspec-mocks (2.8.0)
46
+ rubyzip (0.9.6.1)
47
+ selenium-webdriver (2.20.0)
48
+ childprocess (>= 0.2.5)
49
+ ffi (~> 1.0)
50
+ multi_json (~> 1.0)
51
+ rubyzip
52
+ sinatra (1.3.2)
53
+ rack (~> 1.3, >= 1.3.6)
54
+ rack-protection (~> 1.2)
55
+ tilt (~> 1.3, >= 1.3.3)
56
+ tilt (1.3.3)
57
+ xpath (0.1.4)
58
+ nokogiri (~> 1.3)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ capybara
65
+ ey_api_hmac (>= 0.4.0)
66
+ request_visualizer!
67
+ rspec
68
+ sinatra
data/README ADDED
File without changes
@@ -0,0 +1,70 @@
1
+ require 'colored'
2
+ class RequestVisualizer
3
+ def initialize(app, &lookup)
4
+ @app = app
5
+ @lookup = lookup
6
+ end
7
+
8
+ def parse(string)
9
+ colorize((@lookup && @lookup.call(string.to_s)) || string.to_s)
10
+ end
11
+
12
+ def colorize(string)
13
+ @@colors ||= [:black_on_cyan, :black_on_magenta, :black_on_yellow, :black_on_green]
14
+ @@colorized_before ||= {}
15
+ @@colorized_before[string] ||= string.send(@@colors.pop || :black_on_white)
16
+ @@colorized_before[string]
17
+ end
18
+
19
+ def indent
20
+ " "*@@indent
21
+ end
22
+
23
+ def log_request(request)
24
+ from = parse(request.user_agent.to_s)
25
+ to = parse(request.url.to_s)
26
+ puts "#{self.indent}#{from} -> #{request.request_method.upcase.bold} (#{request.url.underline}) -> #{to}"
27
+ request.body.rewind
28
+ req_body = request.body.read
29
+ begin
30
+ json = JSON.parse(req_body)
31
+ indent_prefix = self.indent
32
+ puts indent_prefix + json.pretty_inspect.gsub("\n","\n#{indent_prefix}")
33
+ rescue => e
34
+ # puts "WARN: JSON request with non-json body! (#{req_body})"
35
+ end
36
+ request.body.rewind
37
+ [from, to]
38
+ end
39
+
40
+ def log_response(from, to, headers, body, status)
41
+ location = headers["Location"]
42
+ if location
43
+ puts "#{self.indent}#{from} <--#{status}-- #{location.underline} <- #{to}"
44
+ else
45
+ puts "#{self.indent}#{from} <--#{status}-- #{to}"
46
+ end
47
+ do_inspect = true
48
+ if headers["Content-Type"].to_s.match(/json/) && do_inspect
49
+ body.each do |bod|
50
+ begin
51
+ json = JSON.parse(bod)
52
+ indent_prefix = self.indent
53
+ puts indent_prefix + json.pretty_inspect.gsub("\n","\n#{indent_prefix}")
54
+ rescue => e
55
+ puts "WARN: JSON response with non-json body! (#{bod})"
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def call(env)
62
+ @@indent ||= 0
63
+ @@indent += 5
64
+ from, to = log_request(Rack::Request.new(env))
65
+ status, headers, body = @app.call(env)
66
+ log_response(from, to, headers, body, status)
67
+ @@indent -= 5
68
+ [status, headers, body]
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ class RequestVisualizer
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "request_visualizer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "request_visualizer"
7
+ s.version = RequestVisualizer::VERSION
8
+ s.authors = ["Jacob Burkhart"]
9
+ s.email = ["jacob@engineyard.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Rack middleware for visualizing HTTP/JSON requests}
12
+ s.description = %q{Rack middleware for visualizing HTTP/JSON requests, and stuff}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'colored'
20
+ end
data/spec/sample.rb ADDED
@@ -0,0 +1,93 @@
1
+ require 'ey_api_hmac'
2
+ class Connection < EY::ApiHMAC::BaseConnection
3
+
4
+ def initialize(user_agent, app)
5
+ super(user_agent)
6
+ self.backend = app
7
+ end
8
+
9
+ def get(url)
10
+ super(url) do |json_body, location|
11
+ json_body
12
+ end
13
+ end
14
+
15
+ def post(url, params)
16
+ super(url, params) do |json_body, location|
17
+ json_body
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ require 'sinatra/base'
24
+ class Service < Sinatra::Base
25
+ enable :raise_errors
26
+ disable :dump_errors
27
+ disable :show_exceptions
28
+
29
+ def conn
30
+ @conn ||= Connection.new(self.class.to_s, Capybara.app)
31
+ end
32
+ end
33
+
34
+ class Lookup
35
+ def self.services
36
+ @services ||= {}
37
+ end
38
+
39
+ def self.lookup(service_url)
40
+ services.each do |base_url, service|
41
+ if service_url.match base_url
42
+ return service.to_s
43
+ end
44
+ end
45
+ service_url
46
+ end
47
+
48
+ end
49
+
50
+ class SandwhichMaker < Service
51
+ BASE_URL = "https://sandwhichmaker.example.com/"
52
+ Lookup.services[BASE_URL] = self
53
+
54
+ get "/" do
55
+ bread = conn.get("#{Baker::BASE_URL}get_loaf")
56
+ conn.post("#{BreadSlicer::BASE_URL}slice", {:bread_url => bread["url"]})
57
+ content_type "application/json"
58
+ {:sandwhich => true}.to_json
59
+ end
60
+
61
+ end
62
+
63
+ class BreadSlicer < Service
64
+ BASE_URL = "https://breadslicer.example.com/"
65
+ Lookup.services[BASE_URL] = self
66
+
67
+ post "/slice" do
68
+ post_body = JSON.parse(request.body.read)
69
+ bread = conn.get(post_body["bread_url"])
70
+ content_type "application/json"
71
+ {:slices => ["heel","slice","slice","slice","heel"]}.to_json
72
+ end
73
+
74
+ end
75
+
76
+ class Baker < Service
77
+ BASE_URL = "https://bakery.example.com/"
78
+ Lookup.services[BASE_URL] = self
79
+
80
+ get "/loaves/1" do
81
+ content_type "application/json"
82
+ {:type => "sourdough"}.to_json
83
+ end
84
+
85
+ get "/get_loaf" do
86
+ content_type "application/json"
87
+ {:url => "#{BASE_URL}loaves/1"}.to_json
88
+ end
89
+
90
+ end
91
+
92
+
93
+
data/spec/spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ require File.expand_path("../sample", __FILE__)
2
+ require 'request_visualizer'
3
+ require 'capybara/rspec'
4
+
5
+ RSpec.configure do |config|
6
+ config.include(Capybara::RSpecMatchers)
7
+ config.include(Capybara::DSL)
8
+ end
9
+
10
+ describe "things" do
11
+ before do
12
+ Capybara.app = Rack::Builder.new do
13
+ use RequestVisualizer do |string|
14
+ Lookup.lookup(string.to_s)
15
+ end
16
+ Lookup.services.each do |url, service|
17
+ map url do
18
+ run service
19
+ end
20
+ end
21
+ end
22
+ page.driver.header 'User-Agent', "Capybara"
23
+ end
24
+
25
+ it "makes a sandwhich" do
26
+ visit SandwhichMaker::BASE_URL
27
+ end
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: request_visualizer
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Jacob Burkhart
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-16 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: colored
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: Rack middleware for visualizing HTTP/JSON requests, and stuff
35
+ email:
36
+ - jacob@engineyard.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - Gemfile
45
+ - Gemfile.lock
46
+ - README
47
+ - lib/request_visualizer.rb
48
+ - lib/request_visualizer/version.rb
49
+ - request_visualizer.gemspec
50
+ - spec/sample.rb
51
+ - spec/spec.rb
52
+ homepage: ""
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.10
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Rack middleware for visualizing HTTP/JSON requests
85
+ test_files:
86
+ - spec/sample.rb
87
+ - spec/spec.rb