rails-threaded-proxy 0.3.0 → 0.4.1
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.
- 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")
|