gumdrop 0.3.10 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.md +3 -0
- data/lib/gumdrop.rb +2 -1
- data/lib/gumdrop/proxy_handler.rb +153 -0
- data/lib/gumdrop/server.rb +63 -5
- data/lib/gumdrop/version.rb +1 -1
- metadata +18 -17
data/ChangeLog.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# v0.4
|
2
|
+
- Added support for special dev proxy at /-proxy/ENDPOINT_URL -- Useful for working with external (non-CORS) apis/websites. Enabled by default. To disable, set Gumdrop.config.proxy_enabled= false
|
3
|
+
|
1
4
|
# v0.3.10
|
2
5
|
- Added 'ignore' dsl command -- keeps the node in the memory, but doesn't render/copy it on build.
|
3
6
|
|
data/lib/gumdrop.rb
CHANGED
@@ -0,0 +1,153 @@
|
|
1
|
+
#
|
2
|
+
# Based on code from MiddleMan Proxy:
|
3
|
+
# https://github.com/middleman/middleman-proxy/blob/master/lib/middleman-proxy.rb
|
4
|
+
#
|
5
|
+
# Which in turn looks to be based on Apple Code:
|
6
|
+
# # ===========================================================================
|
7
|
+
# # Original Project: Abbot - SproutCore Build Tools
|
8
|
+
# # Copyright: ©2009 Apple Inc.
|
9
|
+
# # portions copyright @2006-2011 Strobe Inc.
|
10
|
+
# # and contributors
|
11
|
+
# # ===========================================================================
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'net/https'
|
15
|
+
HTTPS_ENABLED = true
|
16
|
+
rescue LoadError => e
|
17
|
+
require 'net/http'
|
18
|
+
HTTPS_ENABLED = false
|
19
|
+
end
|
20
|
+
|
21
|
+
#require "net/http"
|
22
|
+
require "uri"
|
23
|
+
|
24
|
+
module Gumdrop
|
25
|
+
|
26
|
+
def self.handle_proxy(proxy, proxy_url, env)
|
27
|
+
if proxy[:secure] && !HTTPS_ENABLED
|
28
|
+
$stderr.puts "~ WARNING: HTTPS is not supported on your system, using HTTP instead.\n"
|
29
|
+
$stderr.puts" If you are using Ubuntu, you can run `apt-get install libopenssl-ruby`\n"
|
30
|
+
proxy[:secure] = false
|
31
|
+
end
|
32
|
+
|
33
|
+
origin_host = env['SERVER_NAME'] # capture the origin host for cookies
|
34
|
+
http_method = env['REQUEST_METHOD'].to_s.downcase
|
35
|
+
url = proxy[:path_info] #proxy_url #env['PATH_INFO']
|
36
|
+
params = env['QUERY_STRING']
|
37
|
+
|
38
|
+
puts "PROXY: -> #{url}"
|
39
|
+
|
40
|
+
# collect headers...
|
41
|
+
headers = {}
|
42
|
+
env.each do |key, value|
|
43
|
+
next unless key =~ /^HTTP_/
|
44
|
+
key = key.gsub(/^HTTP_/,'').downcase.sub(/^\w/){|l| l.upcase}.gsub(/_(\w)/){|l| "-#{$1.upcase}"} # remove HTTP_, dasherize and titleize
|
45
|
+
if !key.eql? "Version"
|
46
|
+
headers[key] = value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Rack documentation says CONTENT_TYPE and CONTENT_LENGTH aren't prefixed by HTTP_
|
51
|
+
headers['Content-Type'] = env['CONTENT_TYPE'] if env['CONTENT_TYPE']
|
52
|
+
|
53
|
+
length = env['CONTENT_LENGTH']
|
54
|
+
headers['Content-Length'] = length if length
|
55
|
+
|
56
|
+
http_host, http_port = proxy[:to].split(':')
|
57
|
+
http_port = proxy[:secure] ? '443' : '80' if http_port.nil?
|
58
|
+
|
59
|
+
# added 4/23/09 per Charles Jolley, corrects problem
|
60
|
+
# when making requests to virtual hosts
|
61
|
+
headers['Host'] = "#{http_host}:#{http_port}"
|
62
|
+
|
63
|
+
if proxy[:url]
|
64
|
+
url = url.sub(/^#{Regexp.escape proxy_url}/, proxy[:url])
|
65
|
+
end
|
66
|
+
|
67
|
+
http_path = [url]
|
68
|
+
http_path << params if params && params.size>0
|
69
|
+
http_path = http_path.join('?')
|
70
|
+
|
71
|
+
response = nil
|
72
|
+
no_body_method = %w(get copy head move options trace)
|
73
|
+
|
74
|
+
done = false
|
75
|
+
tries = 0
|
76
|
+
until done
|
77
|
+
http = ::Net::HTTP.new(http_host, http_port)
|
78
|
+
|
79
|
+
if proxy[:secure]
|
80
|
+
http.use_ssl = true
|
81
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
82
|
+
end
|
83
|
+
|
84
|
+
http.start do |web|
|
85
|
+
if no_body_method.include?(http_method)
|
86
|
+
response = web.send(http_method, http_path, headers)
|
87
|
+
else
|
88
|
+
http_body = env['rack.input']
|
89
|
+
http_body.rewind # May not be necessary but can't hurt
|
90
|
+
|
91
|
+
req = Net::HTTPGenericRequest.new(http_method.upcase,
|
92
|
+
true, true, http_path, headers)
|
93
|
+
req.body_stream = http_body if length.to_i > 0
|
94
|
+
response = web.request(req)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
status = response.code # http status code
|
99
|
+
protocol = proxy[:secure] ? 'https' : 'http'
|
100
|
+
|
101
|
+
$stderr.puts "~ PROXY: #{http_method.upcase} #{status} #{url} -> #{protocol}://#{http_host}:#{http_port}#{http_path}\n"
|
102
|
+
|
103
|
+
# display and construct specific response headers
|
104
|
+
response_headers = {}
|
105
|
+
ignore_headers = ['transfer-encoding', 'keep-alive', 'connection']
|
106
|
+
response.each do |key, value|
|
107
|
+
next if ignore_headers.include?(key.downcase)
|
108
|
+
# If this is a cookie, strip out the domain. This technically may
|
109
|
+
# break certain scenarios where services try to set cross-domain
|
110
|
+
# cookies, but those services should not be doing that anyway...
|
111
|
+
value.gsub!(/domain=[^\;]+\;? ?/,'') if key.downcase == 'set-cookie'
|
112
|
+
# Location headers should rewrite the hostname if it is included.
|
113
|
+
value.gsub!(/^http:\/\/#{http_host}(:[0-9]+)?\//, "http://#{http_host}/") if key.downcase == 'location'
|
114
|
+
# content-length is returning char count not bytesize
|
115
|
+
if key.downcase == 'content-length'
|
116
|
+
if response.body.respond_to?(:bytesize)
|
117
|
+
value = response.body.bytesize.to_s
|
118
|
+
elsif response.body.respond_to?(:size)
|
119
|
+
value = response.body.size.to_s
|
120
|
+
else
|
121
|
+
value = '0'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
$stderr << " #{key}: #{value}\n"
|
126
|
+
response_headers[key] = value
|
127
|
+
end
|
128
|
+
|
129
|
+
if [301, 302, 303, 307].include?(status.to_i) && proxy[:redirect] != false
|
130
|
+
$stderr.puts '~ REDIRECTING: '+response_headers['location']+"\n"
|
131
|
+
|
132
|
+
uri = URI.parse(response_headers['location']);
|
133
|
+
http_host = uri.host
|
134
|
+
http_port = uri.port
|
135
|
+
http_path = uri.path
|
136
|
+
http_path += '?'+uri.query if uri.query
|
137
|
+
|
138
|
+
tries += 1
|
139
|
+
if tries > 10
|
140
|
+
raise "Too many redirects!"
|
141
|
+
end
|
142
|
+
else
|
143
|
+
done = true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Thin doesn't like null bodies
|
148
|
+
response_body = response.body || ''
|
149
|
+
#::Rack::Utils::HeaderHash.new(response_headers)
|
150
|
+
return [status.to_i, response_headers, response_body.to_s]
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
data/lib/gumdrop/server.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'sinatra/base'
|
4
4
|
require 'logger'
|
5
5
|
|
6
|
-
|
7
6
|
module Gumdrop
|
8
7
|
|
9
8
|
class Server < Sinatra::Base
|
@@ -18,6 +17,48 @@ module Gumdrop
|
|
18
17
|
# end
|
19
18
|
|
20
19
|
Gumdrop.run dry_run:true, log:server_log
|
20
|
+
|
21
|
+
if Gumdrop.config.proxy_enabled
|
22
|
+
require 'gumdrop/proxy_handler'
|
23
|
+
Gumdrop.report 'Enabled proxy at /-proxy/*', :info
|
24
|
+
get '/-proxy/*' do
|
25
|
+
proxy_to= params[:splat][0]
|
26
|
+
proxy_parts= proxy_to.split('/')
|
27
|
+
host= proxy_parts.shift
|
28
|
+
path_info= "/#{proxy_parts.join('/')}"
|
29
|
+
#puts "HOST: #{host} PATH_INFO: #{path_info}"
|
30
|
+
opts={ :to=>host, :path_info=>path_info }
|
31
|
+
Gumdrop.handle_proxy opts, proxy_to, env
|
32
|
+
end
|
33
|
+
post '/-proxy/*' do
|
34
|
+
proxy_to= params[:splat][0]
|
35
|
+
proxy_parts= proxy_to.split('/')
|
36
|
+
host= proxy_parts.shift
|
37
|
+
path_info= "/#{proxy_parts.join('/')}"
|
38
|
+
#puts "HOST: #{host} PATH_INFO: #{path_info}"
|
39
|
+
opts={ :to=>host, :path_info=>path_info }
|
40
|
+
Gumdrop.handle_proxy opts, proxy_to, env
|
41
|
+
end
|
42
|
+
delete '/-proxy/*' do
|
43
|
+
proxy_to= params[:splat][0]
|
44
|
+
proxy_parts= proxy_to.split('/')
|
45
|
+
host= proxy_parts.shift
|
46
|
+
path_info= "/#{proxy_parts.join('/')}"
|
47
|
+
#puts "HOST: #{host} PATH_INFO: #{path_info}"
|
48
|
+
opts={ :to=>host, :path_info=>path_info }
|
49
|
+
Gumdrop.handle_proxy opts, proxy_to, env
|
50
|
+
end
|
51
|
+
put '/-proxy/*' do
|
52
|
+
proxy_to= params[:splat][0]
|
53
|
+
proxy_parts= proxy_to.split('/')
|
54
|
+
host= proxy_parts.shift
|
55
|
+
path_info= "/#{proxy_parts.join('/')}"
|
56
|
+
#puts "HOST: #{host} PATH_INFO: #{path_info}"
|
57
|
+
opts={ :to=>host, :path_info=>path_info }
|
58
|
+
Gumdrop.handle_proxy opts, proxy_to, env
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
21
62
|
|
22
63
|
get '/*' do
|
23
64
|
file_path= get_content_path params[:splat].join('/')
|
@@ -50,9 +91,26 @@ module Gumdrop
|
|
50
91
|
send_file File.join( source_base_path, file_path)
|
51
92
|
end
|
52
93
|
else
|
53
|
-
|
54
|
-
puts "
|
55
|
-
|
94
|
+
# uri_path= params[:splat].join('/')
|
95
|
+
# puts "LOOKING FOR: #{uri_path}"
|
96
|
+
# if uri_path =~ /^\-proxy\/(.*)$/
|
97
|
+
# uri= URI.parse "http://#{$1}"
|
98
|
+
#
|
99
|
+
# puts "PROXY TO: #{uri}"
|
100
|
+
#
|
101
|
+
# http = Net::HTTP.new(uri.host, uri.port)
|
102
|
+
# response = http.request(Net::HTTP::Get.new(uri.request_uri))
|
103
|
+
#
|
104
|
+
# #[response.code, response.body]
|
105
|
+
# #halt response.code, {}, response.body.to_s
|
106
|
+
# puts "Responded with: #{response.body.to_s}"
|
107
|
+
# #response
|
108
|
+
# [response.code.to_i, {}, response.body.to_s]
|
109
|
+
# else
|
110
|
+
Gumdrop.log.error "[#{$$}] *Missing: #{file_path}"
|
111
|
+
puts "NOT FOUND: #{file_path}"
|
112
|
+
"#{file_path} Not Found"
|
113
|
+
# end
|
56
114
|
end
|
57
115
|
end
|
58
116
|
|
@@ -71,7 +129,7 @@ module Gumdrop
|
|
71
129
|
end
|
72
130
|
|
73
131
|
if Gumdrop.config.auto_run
|
74
|
-
Gumdrop.run dry_run:true
|
132
|
+
#Gumdrop.run dry_run:true
|
75
133
|
run!
|
76
134
|
end
|
77
135
|
|
data/lib/gumdrop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gumdrop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-07-22 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: &
|
16
|
+
requirement: &70152000645980 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70152000645980
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: tilt
|
27
|
-
requirement: &
|
27
|
+
requirement: &70152000645100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70152000645100
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: active_support
|
38
|
-
requirement: &
|
38
|
+
requirement: &70152000644420 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70152000644420
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: trollop
|
49
|
-
requirement: &
|
49
|
+
requirement: &70152000632300 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70152000632300
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: haml
|
60
|
-
requirement: &
|
60
|
+
requirement: &70152000631540 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70152000631540
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sass
|
71
|
-
requirement: &
|
71
|
+
requirement: &70152000631100 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70152000631100
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: i18n
|
82
|
-
requirement: &
|
82
|
+
requirement: &70152000630680 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70152000630680
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: bundle
|
93
|
-
requirement: &
|
93
|
+
requirement: &70152000630200 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70152000630200
|
102
102
|
description: A simple cms/prototyping tool.
|
103
103
|
email: matt@elucidata.net
|
104
104
|
executables:
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- lib/gumdrop/hash_object.rb
|
149
149
|
- lib/gumdrop/logging.rb
|
150
150
|
- lib/gumdrop/pager.rb
|
151
|
+
- lib/gumdrop/proxy_handler.rb
|
151
152
|
- lib/gumdrop/server.rb
|
152
153
|
- lib/gumdrop/stitch_compilers.rb
|
153
154
|
- lib/gumdrop/stitch_ex.rb
|