middleman-proxy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in middleman-proxy.gemspec
4
+ gemspec
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,204 @@
1
+ # ===========================================================================
2
+ # Original Project: Abbot - SproutCore Build Tools
3
+ # Copyright: ©2009 Apple Inc.
4
+ # portions copyright @2006-2011 Strobe Inc.
5
+ # and contributors
6
+ # ===========================================================================
7
+
8
+ begin
9
+ require 'net/https'
10
+ Middleman::HTTPS_ENABLED = true
11
+ rescue LoadError => e
12
+ require 'net/http'
13
+ Middleman::HTTPS_ENABLED = false
14
+ end
15
+
16
+ module Middleman
17
+ module Features
18
+ module Proxy
19
+
20
+ class << self
21
+ def registered(app)
22
+ app.extend ClassMethods
23
+ app.use Middleman::Features::Proxy::Rack
24
+ end
25
+ alias :included :registered
26
+ end
27
+
28
+ class Collection
29
+ def initialize(app)
30
+ @app = app
31
+ end
32
+
33
+ def self.proxies
34
+ @@proxies ||= {}
35
+ end
36
+
37
+ def self.add(path, options={})
38
+ @@proxies ||= {}
39
+ @@proxies[path] = options
40
+ end
41
+ end
42
+
43
+ module ClassMethods
44
+ # Proxies requests to the path
45
+ #
46
+ #
47
+ # require 'middleman-proxy'
48
+ # activate :proxy
49
+ #
50
+ # proxy '/an_api_path', :to => "your-api-hostname.com"
51
+ # proxy '/ssl_api_path', :to => "your-other-api-hostname.com", :secure => true
52
+ def proxy(path, options={})
53
+ Middleman::Features::Proxy::Collection.add(path, options)
54
+ end
55
+ end
56
+
57
+ # Rack application proxies requests as needed for the given project.
58
+ class Rack
59
+
60
+ def initialize(app)
61
+ @app = app
62
+ end
63
+
64
+ def call(env)
65
+ url = env['PATH_INFO']
66
+
67
+ @proxies = Middleman::Features::Proxy::Collection.proxies
68
+ @proxies.each do |proxy, value|
69
+ if url.match(/^#{Regexp.escape(proxy.to_s)}/)
70
+ return handle_proxy(value, proxy.to_s, env)
71
+ end
72
+ end
73
+
74
+ @app.call(env)
75
+ end
76
+
77
+ def handle_proxy(proxy, proxy_url, env)
78
+ if proxy[:secure] && !Middleman::HTTPS_ENABLED
79
+ $stderr.puts "~ WARNING: HTTPS is not supported on your system, using HTTP instead.\n"
80
+ $stderr.puts" If you are using Ubuntu, you can run `apt-get install libopenssl-ruby`\n"
81
+ proxy[:secure] = false
82
+ end
83
+
84
+ origin_host = env['SERVER_NAME'] # capture the origin host for cookies
85
+ http_method = env['REQUEST_METHOD'].to_s.downcase
86
+ url = env['PATH_INFO']
87
+ params = env['QUERY_STRING']
88
+
89
+ # collect headers...
90
+ headers = {}
91
+ env.each do |key, value|
92
+ next unless key =~ /^HTTP_/
93
+ key = key.gsub(/^HTTP_/,'').downcase.sub(/^\w/){|l| l.upcase}.gsub(/_(\w)/){|l| "-#{$1.upcase}"} # remove HTTP_, dasherize and titleize
94
+ if !key.eql? "Version"
95
+ headers[key] = value
96
+ end
97
+ end
98
+
99
+ # Rack documentation says CONTENT_TYPE and CONTENT_LENGTH aren't prefixed by HTTP_
100
+ headers['Content-Type'] = env['CONTENT_TYPE'] if env['CONTENT_TYPE']
101
+
102
+ length = env['CONTENT_LENGTH']
103
+ headers['Content-Length'] = length if length
104
+
105
+ http_host, http_port = proxy[:to].split(':')
106
+ http_port = proxy[:secure] ? '443' : '80' if http_port.nil?
107
+
108
+ # added 4/23/09 per Charles Jolley, corrects problem
109
+ # when making requests to virtual hosts
110
+ headers['Host'] = "#{http_host}:#{http_port}"
111
+
112
+ if proxy[:url]
113
+ url = url.sub(/^#{Regexp.escape proxy_url}/, proxy[:url])
114
+ end
115
+
116
+ http_path = [url]
117
+ http_path << params if params && params.size>0
118
+ http_path = http_path.join('?')
119
+
120
+ response = nil
121
+ no_body_method = %w(get copy head move options trace)
122
+
123
+ done = false
124
+ tries = 0
125
+ until done
126
+ http = ::Net::HTTP.new(http_host, http_port)
127
+
128
+ if proxy[:secure]
129
+ http.use_ssl = true
130
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
131
+ end
132
+
133
+ http.start do |web|
134
+ if no_body_method.include?(http_method)
135
+ response = web.send(http_method, http_path, headers)
136
+ else
137
+ http_body = env['rack.input']
138
+ http_body.rewind # May not be necessary but can't hurt
139
+
140
+ req = Net::HTTPGenericRequest.new(http_method.upcase,
141
+ true, true, http_path, headers)
142
+ req.body_stream = http_body if length.to_i > 0
143
+ response = web.request(req)
144
+ end
145
+ end
146
+
147
+ status = response.code # http status code
148
+ protocol = proxy[:secure] ? 'https' : 'http'
149
+
150
+ $stderr.puts "~ PROXY: #{http_method.upcase} #{status} #{url} -> #{protocol}://#{http_host}:#{http_port}#{http_path}\n"
151
+
152
+ # display and construct specific response headers
153
+ response_headers = {}
154
+ ignore_headers = ['transfer-encoding', 'keep-alive', 'connection']
155
+ response.each do |key, value|
156
+ next if ignore_headers.include?(key.downcase)
157
+ # If this is a cookie, strip out the domain. This technically may
158
+ # break certain scenarios where services try to set cross-domain
159
+ # cookies, but those services should not be doing that anyway...
160
+ value.gsub!(/domain=[^\;]+\;? ?/,'') if key.downcase == 'set-cookie'
161
+ # Location headers should rewrite the hostname if it is included.
162
+ value.gsub!(/^http:\/\/#{http_host}(:[0-9]+)?\//, "http://#{http_host}/") if key.downcase == 'location'
163
+ # content-length is returning char count not bytesize
164
+ if key.downcase == 'content-length'
165
+ if response.body.respond_to?(:bytesize)
166
+ value = response.body.bytesize.to_s
167
+ elsif response.body.respond_to?(:size)
168
+ value = response.body.size.to_s
169
+ else
170
+ value = '0'
171
+ end
172
+ end
173
+
174
+ $stderr << " #{key}: #{value}\n"
175
+ response_headers[key] = value
176
+ end
177
+
178
+ if [301, 302, 303, 307].include?(status.to_i) && proxy[:redirect] != false
179
+ $stderr.puts '~ REDIRECTING: '+response_headers['location']+"\n"
180
+
181
+ uri = URI.parse(response_headers['location']);
182
+ http_host = uri.host
183
+ http_port = uri.port
184
+ http_path = uri.path
185
+ http_path += '?'+uri.query if uri.query
186
+
187
+ tries += 1
188
+ if tries > 10
189
+ raise "Too many redirects!"
190
+ end
191
+ else
192
+ done = true
193
+ end
194
+ end
195
+
196
+ # Thin doesn't like null bodies
197
+ response_body = response.body || ''
198
+
199
+ return [status, ::Rack::Utils::HeaderHash.new(response_headers), [response_body]]
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,5 @@
1
+ module Middleman
2
+ module Proxy
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "middleman-proxy/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "middleman-proxy"
7
+ s.version = Middleman::Proxy::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Thomas Reynolds"]
10
+ s.email = ["me@tdreyno.com"]
11
+ s.homepage = "https://github.com/tdreyno/middleman-proxy"
12
+ s.summary = %q{Remote Data for your Middleman Project}
13
+
14
+ s.rubyforge_project = "middleman-proxy"
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_runtime_dependency("middleman", ["~> 2.0.0"])
22
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-proxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Thomas Reynolds
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-10 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: middleman
16
+ requirement: &70172523644140 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70172523644140
25
+ description:
26
+ email:
27
+ - me@tdreyno.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - Rakefile
35
+ - lib/middleman-proxy.rb
36
+ - lib/middleman-proxy/.DS_Store
37
+ - lib/middleman-proxy/version.rb
38
+ - middleman-proxy.gemspec
39
+ homepage: https://github.com/tdreyno/middleman-proxy
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project: middleman-proxy
59
+ rubygems_version: 1.8.10
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Remote Data for your Middleman Project
63
+ test_files: []