rack_direct 0.1.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/README +1 -0
- data/lib/rack_direct.rb +6 -0
- data/lib/rack_direct/active_resource.rb +51 -0
- data/lib/rack_direct/direct_handler.rb +100 -0
- data/lib/rack_direct/direct_response.rb +41 -0
- data/lib/rack_direct/guid.rb +237 -0
- data/lib/rack_direct/service.rb +103 -0
- metadata +82 -0
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
TBD
|
data/lib/rack_direct.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'active_resource'
|
2
|
+
require 'rack_direct/service'
|
3
|
+
require 'rack_direct/direct_response'
|
4
|
+
|
5
|
+
module RackDirect
|
6
|
+
|
7
|
+
class ActiveResource::Connection
|
8
|
+
|
9
|
+
def request_with_filtering_rack_direct(method, path, *arguments)
|
10
|
+
|
11
|
+
# passthrough anything we don't understand
|
12
|
+
return request_without_filtering_rack_direct(method, path, *arguments) unless site.scheme.match(/^rack-direct/)
|
13
|
+
|
14
|
+
# puts "#{method.to_s.upcase} #{site.scheme}://#{site.host}:#{site.port}#{path}" if logger
|
15
|
+
result = nil
|
16
|
+
|
17
|
+
headers = arguments.last
|
18
|
+
body = arguments.first if arguments.length > 1
|
19
|
+
|
20
|
+
payload = {
|
21
|
+
# Note: We can't pass through a site.scheme of 'rack-direct'
|
22
|
+
# because the Rack instance on the receiving end will freak
|
23
|
+
# out. So we use http in the URI here.
|
24
|
+
"uri" => "http://#{site.host}:#{site.port}#{path}",
|
25
|
+
"method" => method.to_s.upcase,
|
26
|
+
"body" => body.to_s,
|
27
|
+
"CONTENT_TYPE" => headers["Content-Type"] || "text/plain;charset=utf-8",
|
28
|
+
}
|
29
|
+
|
30
|
+
result = JSON.parse(Service.send_request(site.host, payload))
|
31
|
+
|
32
|
+
result = DirectResponse.new result["status"], result["headers"], result["body"]
|
33
|
+
|
34
|
+
if Service.verbose_logging
|
35
|
+
puts "***** #{result.code} #{result.message}"
|
36
|
+
result.each_header { |k,v| puts "***** #{k}: #{v}" }
|
37
|
+
puts "***** START BODY"
|
38
|
+
puts result.body
|
39
|
+
puts "***** END BODY"
|
40
|
+
end
|
41
|
+
|
42
|
+
handle_response(result)
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO: requiring this more than once will not do the right thing
|
46
|
+
alias_method :request_without_filtering_rack_direct, :request
|
47
|
+
alias_method :request, :request_with_filtering_rack_direct
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module RackDirect
|
5
|
+
class DirectHandler
|
6
|
+
def self.run(app, options=nil)
|
7
|
+
@@verbose = options[:verbose]
|
8
|
+
request = []
|
9
|
+
while true
|
10
|
+
line = STDIN.gets
|
11
|
+
if line.blank?
|
12
|
+
begin
|
13
|
+
break if request[0] == "EXIT" || request[0].blank?
|
14
|
+
payload = JSON.parse request[0]
|
15
|
+
uri = payload["uri"]
|
16
|
+
|
17
|
+
#
|
18
|
+
# Fix up names in the hash to match what MockRequest is looking for
|
19
|
+
payload[:input] = payload["body"]
|
20
|
+
payload[:method] = payload["method"]
|
21
|
+
payload[:params] = payload["params"]
|
22
|
+
|
23
|
+
rack_env = Rack::MockRequest.env_for(uri, payload)
|
24
|
+
rack_env["rack.errors"] = STDERR
|
25
|
+
|
26
|
+
self.serve app, rack_env
|
27
|
+
|
28
|
+
rescue => e
|
29
|
+
STDERR.puts "Exception: #{e}"
|
30
|
+
e.backtrace.each { |x| STDERR.puts x }
|
31
|
+
ensure
|
32
|
+
request = []
|
33
|
+
end
|
34
|
+
else
|
35
|
+
request << line.strip
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.serve(app, env)
|
41
|
+
if @@verbose
|
42
|
+
STDERR.puts "Calling serve"
|
43
|
+
STDERR.puts("Rack env:")
|
44
|
+
$> = STDERR
|
45
|
+
pp rack_env
|
46
|
+
$> = STDOUT
|
47
|
+
STDERR.puts("Body: #{rack_env["rack.input"].string}")
|
48
|
+
end
|
49
|
+
|
50
|
+
status, headers, body = app.call(env)
|
51
|
+
|
52
|
+
begin
|
53
|
+
body_string = ""
|
54
|
+
body.each { |part| body_string += part }
|
55
|
+
result = {
|
56
|
+
"status" => status,
|
57
|
+
"headers" => headers,
|
58
|
+
"body" => body_string
|
59
|
+
}
|
60
|
+
|
61
|
+
if @@verbose
|
62
|
+
STDERR.puts "Sending result (#{status})"
|
63
|
+
STDERR.puts result.to_json
|
64
|
+
end
|
65
|
+
|
66
|
+
unique_id = env["direct_request.unique_id"]
|
67
|
+
|
68
|
+
STDOUT.puts "BEGIN #{unique_id}"
|
69
|
+
STDOUT.puts result.to_json
|
70
|
+
STDOUT.puts "END #{unique_id}"
|
71
|
+
STDOUT.flush
|
72
|
+
|
73
|
+
if @@verbose
|
74
|
+
send_headers status, headers, STDERR
|
75
|
+
send_body body, STDERR
|
76
|
+
end
|
77
|
+
ensure
|
78
|
+
body.close if body.respond_to? :close
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.send_headers(status, headers, file = STDOUT)
|
83
|
+
file.print "Status: #{status}\r\n"
|
84
|
+
headers.each { |k, vs|
|
85
|
+
vs.each { |v|
|
86
|
+
file.print "#{k}: #{v}\r\n"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
file.print "\r\n"
|
90
|
+
file.flush
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.send_body(body, file = STDOUT)
|
94
|
+
body.each { |part|
|
95
|
+
file.print part
|
96
|
+
file.flush
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module RackDirect
|
4
|
+
|
5
|
+
class DirectResponse < Rack::MockResponse
|
6
|
+
|
7
|
+
include Net::HTTPHeader
|
8
|
+
|
9
|
+
def initialize(status, headers, body, errors=StringIO.new(""))
|
10
|
+
super(status, headers, body, errors)
|
11
|
+
# Set up @header to make methods in Net::HTTPHeader work
|
12
|
+
@header = {}
|
13
|
+
@headers.each do |k,v|
|
14
|
+
@header[k.downcase] = [v]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def code
|
19
|
+
self.status.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def message
|
23
|
+
if Net::HTTPResponse::CODE_TO_OBJ[self.code]
|
24
|
+
Net::HTTPResponse::CODE_TO_OBJ[self.code].to_s.match(/Net::HTTP(.*)/).captures[0].underscore.humanize.titleize
|
25
|
+
else
|
26
|
+
case self.code
|
27
|
+
when /^2/
|
28
|
+
'OK'
|
29
|
+
when /^4/
|
30
|
+
'Not Found'
|
31
|
+
when /^3/
|
32
|
+
'Redirect'
|
33
|
+
else
|
34
|
+
'Error'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
#
|
2
|
+
# Guid - Ruby library for portable GUID/UUID generation.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2004 David Garamond <davegaramond at icqmail com>
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or modify it
|
7
|
+
# under the same terms as Ruby itself.
|
8
|
+
#
|
9
|
+
|
10
|
+
if RUBY_PLATFORM =~ /mswin32|mingw|cygwin|bccwin32/i
|
11
|
+
module Guid_Win32_
|
12
|
+
require 'Win32API'
|
13
|
+
|
14
|
+
PROV_RSA_FULL = 1
|
15
|
+
CRYPT_VERIFYCONTEXT = 0xF0000000
|
16
|
+
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
|
17
|
+
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
18
|
+
|
19
|
+
CryptAcquireContext = Win32API.new("advapi32", "CryptAcquireContext",
|
20
|
+
'PPPII', 'L')
|
21
|
+
CryptGenRandom = Win32API.new("advapi32", "CryptGenRandom",
|
22
|
+
'LIP', 'L')
|
23
|
+
CryptReleaseContext = Win32API.new("advapi32", "CryptReleaseContext",
|
24
|
+
'LI', 'L')
|
25
|
+
GetLastError = Win32API.new("kernel32", "GetLastError", '', 'L')
|
26
|
+
FormatMessageA = Win32API.new("kernel32", "FormatMessageA",
|
27
|
+
'LPLLPLPPPPPPPP', 'L')
|
28
|
+
|
29
|
+
def lastErrorMessage
|
30
|
+
code = GetLastError.call
|
31
|
+
msg = "\0" * 1024
|
32
|
+
len = FormatMessageA.call(FORMAT_MESSAGE_IGNORE_INSERTS +
|
33
|
+
FORMAT_MESSAGE_FROM_SYSTEM, 0,
|
34
|
+
code, 0, msg, 1024, nil, nil,
|
35
|
+
nil, nil, nil, nil, nil, nil)
|
36
|
+
msg[0, len].tr("\r", '').chomp
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
hProvStr = " " * 4
|
41
|
+
if CryptAcquireContext.call(hProvStr, nil, nil, PROV_RSA_FULL,
|
42
|
+
CRYPT_VERIFYCONTEXT) == 0
|
43
|
+
raise SystemCallError, "CryptAcquireContext failed: #{lastErrorMessage}"
|
44
|
+
end
|
45
|
+
hProv, = hProvStr.unpack('L')
|
46
|
+
@bytes = " " * 16
|
47
|
+
if CryptGenRandom.call(hProv, 16, @bytes) == 0
|
48
|
+
raise SystemCallError, "CryptGenRandom failed: #{lastErrorMessage}"
|
49
|
+
end
|
50
|
+
if CryptReleaseContext.call(hProv, 0) == 0
|
51
|
+
raise SystemCallError, "CryptReleaseContext failed: #{lastErrorMessage}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module Guid_Unix_
|
58
|
+
@@random_device = nil
|
59
|
+
|
60
|
+
def initialize
|
61
|
+
if !@@random_device
|
62
|
+
if File.exists? "/dev/urandom"
|
63
|
+
@@random_device = File.open "/dev/urandom", "r"
|
64
|
+
elsif File.exists? "/dev/random"
|
65
|
+
@@random_device = File.open "/dev/random", "r"
|
66
|
+
else
|
67
|
+
raise RuntimeError, "Can't find random device"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@bytes = @@random_device.read(16)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Guid
|
76
|
+
if RUBY_PLATFORM =~ /mswin32|mingw|cygwin|bccwin32/
|
77
|
+
include Guid_Win32_
|
78
|
+
else
|
79
|
+
include Guid_Unix_
|
80
|
+
end
|
81
|
+
|
82
|
+
def hexdigest
|
83
|
+
@bytes.unpack("h*")[0]
|
84
|
+
end
|
85
|
+
|
86
|
+
alias_method :to_hex , :hexdigest
|
87
|
+
|
88
|
+
def to_s
|
89
|
+
@bytes.unpack("h8 h4 h4 h4 h12").join "-"
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect
|
93
|
+
to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
def raw
|
97
|
+
@bytes
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.from_s(s)
|
101
|
+
raise ArgumentError, "Invalid GUID hexstring" unless
|
102
|
+
s =~ /\A[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\z/i
|
103
|
+
guid = Guid.allocate
|
104
|
+
guid.instance_eval { @bytes = [s.gsub(/[^0-9a-f]+/i, '')].pack "h*" }
|
105
|
+
guid
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.from_raw(bytes)
|
109
|
+
raise ArgumentError, "Invalid GUID raw bytes, length must be 16 bytes" unless
|
110
|
+
bytes.length == 16
|
111
|
+
guid = Guid.allocate
|
112
|
+
guid.instance_eval { @bytes = bytes }
|
113
|
+
guid
|
114
|
+
end
|
115
|
+
|
116
|
+
def ==(other)
|
117
|
+
@bytes == other.raw
|
118
|
+
end
|
119
|
+
|
120
|
+
# ------------------------------------------------------------------------
|
121
|
+
# jambool updates from:
|
122
|
+
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/124607
|
123
|
+
@@d36 = ('a'..'z').to_a + ('0'..'9').to_a
|
124
|
+
@@rd36 = {}
|
125
|
+
@@d36.each_with_index {|d, i| @@rd36[d[0]] = i}
|
126
|
+
|
127
|
+
def Guid.from_base36(val)
|
128
|
+
val = val.downcase
|
129
|
+
raise ArgumentError unless val =~ /\A[a-z][a-z0-9]{24}\z/
|
130
|
+
n = 0
|
131
|
+
mult = 1
|
132
|
+
val.reverse.each_byte {|c|
|
133
|
+
n += @@rd36[c] * mult
|
134
|
+
mult *= 36
|
135
|
+
}
|
136
|
+
Guid.from_i(n)
|
137
|
+
end
|
138
|
+
|
139
|
+
def Guid.from_hex(s)
|
140
|
+
raise ArgumentError, "Invalid GUID hexstring" unless
|
141
|
+
s =~ /\A[0-9a-f]{32}\z/i
|
142
|
+
guid = Guid.allocate
|
143
|
+
guid.instance_eval { @bytes = [s.gsub(/[^0-9a-f]+/i, '')].pack "h*" }
|
144
|
+
guid
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def Guid.from_i(val)
|
149
|
+
bytes = [
|
150
|
+
(val & 0xffffffff000000000000000000000000) >> 96,
|
151
|
+
(val & 0x00000000ffffffff0000000000000000) >> 64,
|
152
|
+
(val & 0x0000000000000000ffffffff00000000) >> 32,
|
153
|
+
(val & 0x000000000000000000000000ffffffff)
|
154
|
+
].pack('NNNN')
|
155
|
+
guid = Guid.allocate
|
156
|
+
guid.instance_eval { @bytes = bytes }
|
157
|
+
guid
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_i
|
161
|
+
(@bytes[ 0 .. 3].unpack('N')[0] << 96) +
|
162
|
+
(@bytes[ 4 .. 7].unpack('N')[0] << 64) +
|
163
|
+
(@bytes[ 8 .. 11].unpack('N')[0] << 32) +
|
164
|
+
(@bytes[12 .. 15].unpack('N')[0])
|
165
|
+
end
|
166
|
+
|
167
|
+
def to_base36
|
168
|
+
self.to_i.to_s(36).tr('0-9a-z', 'a-z0-9').rjust(25, 'a')
|
169
|
+
# self.to_s.tr('0-9a-z', 'a-z0-9').rjust(25, 'a')
|
170
|
+
end
|
171
|
+
# ------------------------------------------------------------------------
|
172
|
+
end
|
173
|
+
|
174
|
+
if __FILE__ == $0
|
175
|
+
require 'test/unit'
|
176
|
+
|
177
|
+
class GuidTest < Test::Unit::TestCase
|
178
|
+
def test_new
|
179
|
+
g = Guid.new
|
180
|
+
|
181
|
+
# different representations of guid: hexdigest, hex+dashes, raw bytes
|
182
|
+
assert_equal(0, g.to_s =~ /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/)
|
183
|
+
assert_equal(16, g.raw.length)
|
184
|
+
assert_equal(0, g.hexdigest =~ /\A[0-9a-f]{32}\z/)
|
185
|
+
assert_equal(g.hexdigest, g.to_s.gsub(/-/, ''))
|
186
|
+
|
187
|
+
# must be different each time we produce (this is just a simple test)
|
188
|
+
g2 = Guid.new
|
189
|
+
assert_equal(true, g != g2)
|
190
|
+
assert_equal(true, g.to_s != g2.to_s)
|
191
|
+
assert_equal(true, g.raw != g2.raw)
|
192
|
+
assert_equal(true, g.hexdigest != g2.hexdigest)
|
193
|
+
assert_equal(1000, (1..1000).select { |i| g != Guid.new }.length)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_from_s
|
197
|
+
g = Guid.new
|
198
|
+
g2 = Guid.from_s(g.to_s)
|
199
|
+
assert_equal(g, g2)
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_from_raw
|
203
|
+
g = Guid.new
|
204
|
+
g2 = Guid.from_raw(g.raw)
|
205
|
+
assert_equal(g, g2)
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_from_i
|
209
|
+
g = Guid.new
|
210
|
+
g2 = Guid.from_i(g.to_i)
|
211
|
+
assert_equal(g, g2)
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_from_base36
|
215
|
+
g = Guid.new
|
216
|
+
g2 = Guid.from_base36(g.to_base36)
|
217
|
+
assert_equal(g, g2)
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_from_hex
|
221
|
+
g = Guid.new
|
222
|
+
g2 = Guid.from_hex(g.to_hex)
|
223
|
+
assert_equal(g, g2)
|
224
|
+
end
|
225
|
+
|
226
|
+
def test_harder
|
227
|
+
g1 = Guid.new
|
228
|
+
g2 = g1
|
229
|
+
assert_equal(g1, g2)
|
230
|
+
g1a = Guid.from_hex(Guid.from_s(Guid.from_i(g1.to_i).to_s).to_hex)
|
231
|
+
assert_equal(g1, g1a)
|
232
|
+
g2a = Guid.from_base36(Guid.from_i(g1.to_i).to_base36)
|
233
|
+
assert_equal(g2, g2a)
|
234
|
+
assert_equal(g1a, g2a)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rack_direct/guid'
|
2
|
+
require 'open3'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'rack_direct/active_resource'
|
5
|
+
|
6
|
+
RACK_DIRECT_ALIAS = 'rack-direct'
|
7
|
+
|
8
|
+
module RackDirect
|
9
|
+
|
10
|
+
class Service
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :verbose_logging
|
14
|
+
end
|
15
|
+
|
16
|
+
@@services = {}
|
17
|
+
def self.start name, path
|
18
|
+
unless @@services[name]
|
19
|
+
|
20
|
+
tmppath = generate_rackup_file
|
21
|
+
|
22
|
+
# TODO: check path to make sure a Rails app exists there
|
23
|
+
print "Starting service rack-direct://#{name}..."
|
24
|
+
cmd = "cd #{path} && rake db:test:prepare && rackup --server #{RACK_DIRECT_ALIAS} #{tmppath} 2>&1"
|
25
|
+
# puts cmd
|
26
|
+
@@services[name] = IO.popen cmd, "w+"
|
27
|
+
puts "done."
|
28
|
+
|
29
|
+
at_exit do
|
30
|
+
RackDirect::Service.stop name
|
31
|
+
File.unlink tmppath
|
32
|
+
end
|
33
|
+
end
|
34
|
+
"rack-direct://#{name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.send_request name, rack_request_env
|
38
|
+
|
39
|
+
if @@services[name]
|
40
|
+
|
41
|
+
rack_request_env["direct_request.unique_id"] = Guid.new.to_s
|
42
|
+
|
43
|
+
@@services[name].puts rack_request_env.to_json
|
44
|
+
@@services[name].puts ""
|
45
|
+
|
46
|
+
response = ""
|
47
|
+
in_response = false
|
48
|
+
while true
|
49
|
+
line = @@services[name].gets
|
50
|
+
if line.strip == "BEGIN #{rack_request_env["direct_request.unique_id"]}"
|
51
|
+
in_response = true
|
52
|
+
next
|
53
|
+
elsif line.strip == "END #{rack_request_env["direct_request.unique_id"]}"
|
54
|
+
break
|
55
|
+
elsif in_response
|
56
|
+
response += line
|
57
|
+
else
|
58
|
+
puts "rack-direct://#{name}: #{line.strip}" if self.verbose_logging
|
59
|
+
end
|
60
|
+
end
|
61
|
+
# puts "Final response: #{response}"
|
62
|
+
response
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.stop name
|
68
|
+
if @@services[name]
|
69
|
+
print "Stopping service rack-direct://#{name}..."
|
70
|
+
@@services[name].puts "EXIT"
|
71
|
+
@@services[name].puts ""
|
72
|
+
@@services[name] = nil
|
73
|
+
Process.waitall
|
74
|
+
puts "done."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def self.generate_rackup_file
|
81
|
+
rackup_file_contents = <<-EOF
|
82
|
+
$: << '~/src/rack-direct/lib'
|
83
|
+
require 'rack_direct/direct_handler'
|
84
|
+
Rack::Handler.register('#{RACK_DIRECT_ALIAS}', 'RackDirect::DirectHandler')
|
85
|
+
# puts "RackDirect::DirectHandler registered"
|
86
|
+
|
87
|
+
require "config/environment"
|
88
|
+
use Rails::Rack::LogTailer
|
89
|
+
use Rails::Rack::Static
|
90
|
+
run ActionController::Dispatcher.new
|
91
|
+
EOF
|
92
|
+
tmppath = nil
|
93
|
+
Tempfile.open("rack_direct") { |x| tmppath = x.path + ".ru" }
|
94
|
+
tmpfile = File.open tmppath, "w+"
|
95
|
+
tmpfile.write rackup_file_contents
|
96
|
+
tmpfile.close
|
97
|
+
|
98
|
+
tmppath
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack_direct
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Sharon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-06-09 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activeresource
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: |
|
36
|
+
RackDirect allows you to easily perform integration tests between multiple Rails websites, by launching your ActiveResource services in a standalone process and communicating with them via stdio instead of over a socket.
|
37
|
+
|
38
|
+
email: brian@floatplane.us
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- README
|
47
|
+
- lib/rack_direct/active_resource.rb
|
48
|
+
- lib/rack_direct/direct_handler.rb
|
49
|
+
- lib/rack_direct/direct_response.rb
|
50
|
+
- lib/rack_direct/guid.rb
|
51
|
+
- lib/rack_direct/service.rb
|
52
|
+
- lib/rack_direct.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://floatplane.us/
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.3.5
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: RackDirect allows you to easily perform integration tests between multiple Rails websites, by launching your ActiveResource services in a standalone process and communicating with them via stdio instead of over a socket.
|
81
|
+
test_files: []
|
82
|
+
|