rails-threaded-proxy 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +46 -0
- data/VERSION +1 -1
- data/lib/threaded_proxy/client.rb +50 -14
- data/lib/threaded_proxy/controller.rb +2 -2
- data/rails-threaded-proxy.gemspec +6 -18
- metadata +5 -29
- data/bin/bundle +0 -109
- data/bin/htmldiff +0 -27
- data/bin/jeweler +0 -27
- data/bin/ldiff +0 -27
- data/bin/nokogiri +0 -27
- data/bin/racc +0 -27
- data/bin/rackup +0 -27
- data/bin/rake +0 -27
- data/bin/rdoc +0 -27
- data/bin/ri +0 -27
- data/bin/rspec +0 -27
- data/bin/rubocop +0 -27
- data/bin/semver +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 627edadeb8a4d381699398dcd596285b425994116b21393d5a1c4b61f91bf195
|
4
|
+
data.tar.gz: '0066744825548c505bf61585302e20a011761f7198f12cdb34fa9f79607317c4'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52d909c71d9657f8e0f5f601bb4478979dfb4971bbf93230067172cd0077fbfc77601b9a1bc76f27b94f01185f83e07c08540eacbea70c612e66211d0cca4bb3
|
7
|
+
data.tar.gz: 108158c59c1b87c72e6559cb7fdb535d1c05819a581f321feff8679ea4213491a37c7dd204fc55357dbdf9bfc6a3e7724fa4223c488036b53a20594c235a7d56
|
data/LICENSE
CHANGED
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# rails-threaded-proxy
|
2
|
+
|
3
|
+
Asynchronous high throughput reverse proxy for rails
|
4
|
+
|
5
|
+
*Warning: experimental. Use at your own risk.*
|
6
|
+
|
7
|
+
## About
|
8
|
+
|
9
|
+
Rails concurrency is often limited to running many processes, which can be memory-intensive. Even for servers that support threads, it can be difficult running dozens or hundreds of threads. But you may have backend services that are slow to respond, and/or return very large responses. It is useful to put these services behind rails for authentication, but slow responses can tie up your rails workers preventing them from serving other clients.
|
10
|
+
|
11
|
+
`rails-threaded-proxy` disconnects the proxying from the rack request/response cycle, freeing up workers to serve other clients. It does this by running the origin request in a thread. But running in a thread is not enough: we need to be able to respond to the rails request, but rack owns the socket. So it hijacks the request: rack completes immediately but dissociates from the socket. Then we're free to manage the socket ourselves. Copying between sockets, we can achieve high throughput (100MB/s+) with minimal CPU and memory overhead.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class MyController
|
17
|
+
include ThreadedProxy::Controller
|
18
|
+
|
19
|
+
def my_backend
|
20
|
+
proxy_fetch "http://backend.service/path/to/endpoint", method: :post do |config|
|
21
|
+
config.on_headers do |client_response|
|
22
|
+
# override some response headers coming from the backend
|
23
|
+
client_response['content-security-policy'] = "sandbox;"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
## Requirements
|
31
|
+
|
32
|
+
Tested with Rails 7, but probably works in Rails 6+. Needs an application server that supports `rack.hijack`. (only tested on [https://puma.io/](Puma) so far)
|
33
|
+
|
34
|
+
## Caveats
|
35
|
+
|
36
|
+
* There isn't currently a way to limit concurrency. It is possible to run your server out of file descriptors, memory, etc.
|
37
|
+
* Since the proxying happens in a thread, callbacks are also run inside of the thread. Don't do anything non-threadsafe in callbacks.
|
38
|
+
* There is currently probably not sufficient error handling for edge cases. This is experimental.
|
39
|
+
|
40
|
+
## Attribution
|
41
|
+
|
42
|
+
Inspired by [https://github.com/axsuul/rails-reverse-proxy](rails-reverse-proxy), and tries to use similar API structure where possible. If you don't care about the specific benefits of `rails-threaded-proxy`, you should consider using `rails-reverse-proxy` instead.
|
43
|
+
|
44
|
+
## License
|
45
|
+
|
46
|
+
See LICENSE
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.1
|
@@ -9,7 +9,7 @@ module ThreadedProxy
|
|
9
9
|
class Client
|
10
10
|
DISALLOWED_RESPONSE_HEADERS = %w[keep-alive].freeze
|
11
11
|
|
12
|
-
|
12
|
+
HTTP_METHODS = {
|
13
13
|
'get' => Net::HTTP::Get,
|
14
14
|
'post' => Net::HTTP::Post,
|
15
15
|
'put' => Net::HTTP::Put,
|
@@ -19,6 +19,20 @@ module ThreadedProxy
|
|
19
19
|
'trace' => Net::HTTP::Trace
|
20
20
|
}.freeze
|
21
21
|
|
22
|
+
CALLBACK_METHODS = %i[
|
23
|
+
on_response
|
24
|
+
on_headers
|
25
|
+
on_body
|
26
|
+
on_complete
|
27
|
+
on_error
|
28
|
+
].freeze
|
29
|
+
|
30
|
+
CALLBACK_METHODS.each do |method_name|
|
31
|
+
define_method(method_name) do |&block|
|
32
|
+
@callbacks[method_name] = block
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
22
36
|
DEFAULT_OPTIONS = {
|
23
37
|
headers: {},
|
24
38
|
debug: false,
|
@@ -28,6 +42,13 @@ module ThreadedProxy
|
|
28
42
|
def initialize(origin_url, options = {})
|
29
43
|
@origin_url = Addressable::URI.parse(origin_url)
|
30
44
|
@options = DEFAULT_OPTIONS.merge(options)
|
45
|
+
|
46
|
+
@callbacks = {}
|
47
|
+
CALLBACK_METHODS.each do |method_name|
|
48
|
+
@callbacks[method_name] = proc {}
|
49
|
+
end
|
50
|
+
|
51
|
+
yield(self) if block_given?
|
31
52
|
end
|
32
53
|
|
33
54
|
def log(message)
|
@@ -38,7 +59,7 @@ module ThreadedProxy
|
|
38
59
|
request_method = @options[:method].to_s.downcase
|
39
60
|
request_headers = @options[:headers].merge('Connection' => 'close')
|
40
61
|
|
41
|
-
request_class =
|
62
|
+
request_class = HTTP_METHODS[request_method]
|
42
63
|
http_request = request_class.new(@origin_url, request_headers)
|
43
64
|
if @options[:body].respond_to?(:read)
|
44
65
|
http_request.body_stream = @options[:body]
|
@@ -55,21 +76,15 @@ module ThreadedProxy
|
|
55
76
|
|
56
77
|
http.start do
|
57
78
|
http.request(http_request) do |client_response|
|
58
|
-
|
59
|
-
|
79
|
+
@callbacks[:on_response].call(client_response, socket)
|
80
|
+
break if socket.closed?
|
60
81
|
|
61
|
-
yield client_response if block_given?
|
62
|
-
|
63
|
-
# start writing response
|
64
82
|
log('Writing response status and headers')
|
65
|
-
|
66
|
-
|
67
|
-
client_response.each_header do |key, value|
|
68
|
-
socket.write "#{key}: #{value}\r\n" unless DISALLOWED_RESPONSE_HEADERS.include?(key.downcase)
|
69
|
-
end
|
83
|
+
write_headers(client_response, socket)
|
84
|
+
break if socket.closed?
|
70
85
|
|
71
|
-
|
72
|
-
socket.
|
86
|
+
@callbacks[:on_body].call(client_response, socket)
|
87
|
+
break if socket.closed?
|
73
88
|
|
74
89
|
# There may have been some existing data in client_response's read buffer, flush it out
|
75
90
|
# before we manually connect the raw sockets
|
@@ -79,11 +94,32 @@ module ThreadedProxy
|
|
79
94
|
# Copy the rest of the client response to the socket
|
80
95
|
log('Copying response body to client')
|
81
96
|
http.copy_to(socket)
|
97
|
+
|
98
|
+
@callbacks[:on_complete].call(client_response)
|
82
99
|
end
|
100
|
+
rescue StandardError => e
|
101
|
+
@callbacks[:on_error].call(e) or raise
|
83
102
|
end
|
84
103
|
end
|
85
104
|
end
|
86
105
|
|
106
|
+
def write_headers(client_response, socket)
|
107
|
+
socket.write "HTTP/1.1 #{client_response.code} #{client_response.message}\r\n"
|
108
|
+
|
109
|
+
# We don't support reusing connections once we have disconnected them from rack
|
110
|
+
client_response['connection'] = 'close'
|
111
|
+
|
112
|
+
@callbacks[:on_headers].call(client_response, socket)
|
113
|
+
return if socket.closed?
|
114
|
+
|
115
|
+
client_response.each_header do |key, value|
|
116
|
+
socket.write "#{key}: #{value}\r\n" unless DISALLOWED_RESPONSE_HEADERS.include?(key.downcase)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Done with headers
|
120
|
+
socket.write "\r\n"
|
121
|
+
end
|
122
|
+
|
87
123
|
def default_port(uri)
|
88
124
|
case uri.scheme
|
89
125
|
when 'http'
|
@@ -4,7 +4,7 @@ require_relative 'client'
|
|
4
4
|
|
5
5
|
module ThreadedProxy
|
6
6
|
module Controller
|
7
|
-
def proxy_fetch(origin_url, options = {})
|
7
|
+
def proxy_fetch(origin_url, options = {}, &block)
|
8
8
|
# hijack the response so we can take it outside of the rack request/response cycle
|
9
9
|
request.env['rack.hijack'].call
|
10
10
|
socket = request.env['rack.hijack_io']
|
@@ -25,7 +25,7 @@ module ThreadedProxy
|
|
25
25
|
options[:headers]['Content-Type'] = request.env['CONTENT_TYPE'] if request.env['CONTENT_TYPE']
|
26
26
|
end
|
27
27
|
|
28
|
-
client = Client.new(origin_url, options)
|
28
|
+
client = Client.new(origin_url, options, &block)
|
29
29
|
client.start(socket)
|
30
30
|
rescue Errno::EPIPE
|
31
31
|
# client disconnected before request finished; not an error
|
@@ -2,21 +2,21 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: rails-threaded-proxy 0.
|
5
|
+
# stub: rails-threaded-proxy 0.4.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "rails-threaded-proxy".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.4.1".freeze
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Michael Nutt".freeze]
|
14
|
-
s.date = "2024-10-
|
14
|
+
s.date = "2024-10-17"
|
15
15
|
s.description = "Threaded reverse proxy for Ruby on Rails".freeze
|
16
16
|
s.email = "michael@nuttnet.net".freeze
|
17
|
-
s.executables = ["bundle".freeze, "htmldiff".freeze, "jeweler".freeze, "ldiff".freeze, "nokogiri".freeze, "racc".freeze, "rackup".freeze, "rake".freeze, "rdoc".freeze, "ri".freeze, "rspec".freeze, "rubocop".freeze, "semver".freeze]
|
18
17
|
s.extra_rdoc_files = [
|
19
|
-
"LICENSE"
|
18
|
+
"LICENSE",
|
19
|
+
"README.md"
|
20
20
|
]
|
21
21
|
s.files = [
|
22
22
|
".bundle/config",
|
@@ -26,21 +26,9 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Gemfile",
|
27
27
|
"Gemfile.lock",
|
28
28
|
"LICENSE",
|
29
|
+
"README.md",
|
29
30
|
"Rakefile",
|
30
31
|
"VERSION",
|
31
|
-
"bin/bundle",
|
32
|
-
"bin/htmldiff",
|
33
|
-
"bin/jeweler",
|
34
|
-
"bin/ldiff",
|
35
|
-
"bin/nokogiri",
|
36
|
-
"bin/racc",
|
37
|
-
"bin/rackup",
|
38
|
-
"bin/rake",
|
39
|
-
"bin/rdoc",
|
40
|
-
"bin/ri",
|
41
|
-
"bin/rspec",
|
42
|
-
"bin/rubocop",
|
43
|
-
"bin/semver",
|
44
32
|
"lib/rails-threaded-proxy.rb",
|
45
33
|
"lib/threaded-proxy.rb",
|
46
34
|
"lib/threaded_proxy.rb",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-threaded-proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Nutt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -138,23 +138,11 @@ dependencies:
|
|
138
138
|
version: '0'
|
139
139
|
description: Threaded reverse proxy for Ruby on Rails
|
140
140
|
email: michael@nuttnet.net
|
141
|
-
executables:
|
142
|
-
- bundle
|
143
|
-
- htmldiff
|
144
|
-
- jeweler
|
145
|
-
- ldiff
|
146
|
-
- nokogiri
|
147
|
-
- racc
|
148
|
-
- rackup
|
149
|
-
- rake
|
150
|
-
- rdoc
|
151
|
-
- ri
|
152
|
-
- rspec
|
153
|
-
- rubocop
|
154
|
-
- semver
|
141
|
+
executables: []
|
155
142
|
extensions: []
|
156
143
|
extra_rdoc_files:
|
157
144
|
- LICENSE
|
145
|
+
- README.md
|
158
146
|
files:
|
159
147
|
- ".bundle/config"
|
160
148
|
- ".rspec"
|
@@ -163,21 +151,9 @@ files:
|
|
163
151
|
- Gemfile
|
164
152
|
- Gemfile.lock
|
165
153
|
- LICENSE
|
154
|
+
- README.md
|
166
155
|
- Rakefile
|
167
156
|
- VERSION
|
168
|
-
- bin/bundle
|
169
|
-
- bin/htmldiff
|
170
|
-
- bin/jeweler
|
171
|
-
- bin/ldiff
|
172
|
-
- bin/nokogiri
|
173
|
-
- bin/racc
|
174
|
-
- bin/rackup
|
175
|
-
- bin/rake
|
176
|
-
- bin/rdoc
|
177
|
-
- bin/ri
|
178
|
-
- bin/rspec
|
179
|
-
- bin/rubocop
|
180
|
-
- bin/semver
|
181
157
|
- lib/rails-threaded-proxy.rb
|
182
158
|
- lib/threaded-proxy.rb
|
183
159
|
- lib/threaded_proxy.rb
|
data/bin/bundle
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'bundle' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "rubygems"
|
12
|
-
|
13
|
-
m = Module.new do
|
14
|
-
module_function
|
15
|
-
|
16
|
-
def invoked_as_script?
|
17
|
-
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
-
end
|
19
|
-
|
20
|
-
def env_var_version
|
21
|
-
ENV["BUNDLER_VERSION"]
|
22
|
-
end
|
23
|
-
|
24
|
-
def cli_arg_version
|
25
|
-
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
-
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
-
bundler_version = nil
|
28
|
-
update_index = nil
|
29
|
-
ARGV.each_with_index do |a, i|
|
30
|
-
if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN)
|
31
|
-
bundler_version = a
|
32
|
-
end
|
33
|
-
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
-
bundler_version = $1
|
35
|
-
update_index = i
|
36
|
-
end
|
37
|
-
bundler_version
|
38
|
-
end
|
39
|
-
|
40
|
-
def gemfile
|
41
|
-
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
-
return gemfile if gemfile && !gemfile.empty?
|
43
|
-
|
44
|
-
File.expand_path("../Gemfile", __dir__)
|
45
|
-
end
|
46
|
-
|
47
|
-
def lockfile
|
48
|
-
lockfile =
|
49
|
-
case File.basename(gemfile)
|
50
|
-
when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
|
51
|
-
else "#{gemfile}.lock"
|
52
|
-
end
|
53
|
-
File.expand_path(lockfile)
|
54
|
-
end
|
55
|
-
|
56
|
-
def lockfile_version
|
57
|
-
return unless File.file?(lockfile)
|
58
|
-
lockfile_contents = File.read(lockfile)
|
59
|
-
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
-
Regexp.last_match(1)
|
61
|
-
end
|
62
|
-
|
63
|
-
def bundler_requirement
|
64
|
-
@bundler_requirement ||=
|
65
|
-
env_var_version ||
|
66
|
-
cli_arg_version ||
|
67
|
-
bundler_requirement_for(lockfile_version)
|
68
|
-
end
|
69
|
-
|
70
|
-
def bundler_requirement_for(version)
|
71
|
-
return "#{Gem::Requirement.default}.a" unless version
|
72
|
-
|
73
|
-
bundler_gem_version = Gem::Version.new(version)
|
74
|
-
|
75
|
-
bundler_gem_version.approximate_recommendation
|
76
|
-
end
|
77
|
-
|
78
|
-
def load_bundler!
|
79
|
-
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
80
|
-
|
81
|
-
activate_bundler
|
82
|
-
end
|
83
|
-
|
84
|
-
def activate_bundler
|
85
|
-
gem_error = activation_error_handling do
|
86
|
-
gem "bundler", bundler_requirement
|
87
|
-
end
|
88
|
-
return if gem_error.nil?
|
89
|
-
require_error = activation_error_handling do
|
90
|
-
require "bundler/version"
|
91
|
-
end
|
92
|
-
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
93
|
-
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
94
|
-
exit 42
|
95
|
-
end
|
96
|
-
|
97
|
-
def activation_error_handling
|
98
|
-
yield
|
99
|
-
nil
|
100
|
-
rescue StandardError, LoadError => e
|
101
|
-
e
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
m.load_bundler!
|
106
|
-
|
107
|
-
if m.invoked_as_script?
|
108
|
-
load Gem.bin_path("bundler", "bundle")
|
109
|
-
end
|
data/bin/htmldiff
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'htmldiff' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("diff-lcs", "htmldiff")
|
data/bin/jeweler
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'jeweler' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("jeweler", "jeweler")
|
data/bin/ldiff
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'ldiff' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("diff-lcs", "ldiff")
|
data/bin/nokogiri
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'nokogiri' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("nokogiri", "nokogiri")
|
data/bin/racc
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'racc' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("racc", "racc")
|
data/bin/rackup
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rackup' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("rack", "rackup")
|
data/bin/rake
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rake' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("rake", "rake")
|
data/bin/rdoc
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rdoc' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("rdoc", "rdoc")
|
data/bin/ri
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'ri' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("rdoc", "ri")
|
data/bin/rspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rspec' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rubocop' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path('bundle', __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require 'rubygems'
|
25
|
-
require 'bundler/setup'
|
26
|
-
|
27
|
-
load Gem.bin_path('rubocop', 'rubocop')
|
data/bin/semver
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'semver' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
-
|
13
|
-
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
-
|
15
|
-
if File.file?(bundle_binstub)
|
16
|
-
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
-
load(bundle_binstub)
|
18
|
-
else
|
19
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require "bundler/setup"
|
26
|
-
|
27
|
-
load Gem.bin_path("semver2", "semver")
|