forward-proxy 0.6.2 → 0.9.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/CHANGELOG.md +17 -0
- data/lib/forward_proxy/server.rb +24 -10
- data/lib/forward_proxy/thread_pool.rb +9 -4
- data/lib/forward_proxy/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebb420c1a9dd1e13e77b0884f0349e3bb9f78150a9e00004bb6db86a95c3766d
|
4
|
+
data.tar.gz: 3186ebd3f6f1beadc466aeb81f1f427f43f62960dab3680ce9be8ed1efd5e0d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fc1d9053270cda730bd7ca85a5e08fa4a42105fe8a2a7d17cbfa0ac8b29d437a6dde6c5d884b336a5295c1ebaa842bc5c0e15cded11f309148e5253f1a7fd12
|
7
|
+
data.tar.gz: ee39eb4f082d8ba7e4bd7f7d0bf5233b763e0ce6ff787b531a549e8b3ab4caf1fd03831c71244a73e0ab570988e13762373d437bd42632effafcb4f783eebacc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.9.1
|
4
|
+
|
5
|
+
- bugfix chunked length.
|
6
|
+
|
7
|
+
## 0.9.0
|
8
|
+
|
9
|
+
- bugfix chunked response behavior.
|
10
|
+
|
11
|
+
## 0.8.0
|
12
|
+
|
13
|
+
- add http `head` support.
|
14
|
+
- add http `501` not implemented status response.
|
15
|
+
|
16
|
+
## 0.7.0
|
17
|
+
|
18
|
+
- bugfix default threads from `4` to `128`.
|
19
|
+
|
3
20
|
## 0.6.0
|
4
21
|
|
5
22
|
- add connection timeout to stop tracking connection from saturating client threads.
|
data/lib/forward_proxy/server.rb
CHANGED
@@ -12,7 +12,7 @@ module ForwardProxy
|
|
12
12
|
class Server
|
13
13
|
attr_reader :bind_address, :bind_port, :logger, :timeout
|
14
14
|
|
15
|
-
def initialize(bind_address: "127.0.0.1", bind_port: 9292, threads:
|
15
|
+
def initialize(bind_address: "127.0.0.1", bind_port: 9292, threads: 128, timeout: 300, logger: default_logger)
|
16
16
|
@bind_address = bind_address
|
17
17
|
@bind_port = bind_port
|
18
18
|
@logger = logger
|
@@ -37,7 +37,7 @@ module ForwardProxy
|
|
37
37
|
|
38
38
|
case req.request_method
|
39
39
|
when METHOD_CONNECT then handle_tunnel(client_conn, req)
|
40
|
-
when METHOD_GET, METHOD_POST then handle(client_conn, req)
|
40
|
+
when METHOD_GET, METHOD_HEAD, METHOD_POST then handle(client_conn, req)
|
41
41
|
else
|
42
42
|
raise Errors::HTTPMethodNotImplemented
|
43
43
|
end
|
@@ -67,17 +67,18 @@ module ForwardProxy
|
|
67
67
|
|
68
68
|
attr_reader :socket, :thread_pool
|
69
69
|
|
70
|
-
# The following comments are from the IETF document
|
71
|
-
# "Hypertext Transfer Protocol -- HTTP/1.1: Basic Rules"
|
72
|
-
# https://datatracker.ietf.org/doc/html/rfc2616#section-2.2
|
73
|
-
|
74
70
|
METHOD_CONNECT = "CONNECT"
|
75
71
|
METHOD_GET = "GET"
|
72
|
+
METHOD_HEAD = "HEAD"
|
76
73
|
METHOD_POST = "POST"
|
77
74
|
|
75
|
+
# The following comments are from the IETF document
|
76
|
+
# "Hypertext Transfer Protocol -- HTTP/1.1: Basic Rules"
|
77
|
+
# https://datatracker.ietf.org/doc/html/rfc2616#section-2.2
|
78
|
+
|
78
79
|
# HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
|
79
80
|
# protocol elements except the entity-body.
|
80
|
-
|
81
|
+
HTTP_EOP = "\r\n"
|
81
82
|
|
82
83
|
# The following comments are from the IETF document
|
83
84
|
# "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"
|
@@ -113,7 +114,7 @@ module ForwardProxy
|
|
113
114
|
# the request-target.
|
114
115
|
client_conn.write <<~eos.chomp
|
115
116
|
HTTP/1.1 200 OK
|
116
|
-
#{
|
117
|
+
#{HTTP_EOP}
|
117
118
|
eos
|
118
119
|
|
119
120
|
# The CONNECT method requests that the recipient establish a tunnel to
|
@@ -154,7 +155,7 @@ module ForwardProxy
|
|
154
155
|
client_conn.puts <<~eos.chomp
|
155
156
|
HTTP/1.1 #{resp.code}
|
156
157
|
#{headers.map { |header, value| "#{header}: #{value}" }.join("\n")}
|
157
|
-
#{
|
158
|
+
#{HTTP_EOP}
|
158
159
|
eos
|
159
160
|
|
160
161
|
# The following comments are taken from:
|
@@ -164,6 +165,17 @@ module ForwardProxy
|
|
164
165
|
# handling large files or wish to implement a progress bar you can
|
165
166
|
# instead stream the body directly to an IO.
|
166
167
|
resp.read_body do |chunk|
|
168
|
+
# The following comments are taken from:
|
169
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding#directives
|
170
|
+
|
171
|
+
# Data is sent in a series of chunks. The Content-Length header is omitted in this case and
|
172
|
+
# at the beginning of each chunk you need to add the length of the current chunk in
|
173
|
+
# hexadecimal format, followed by '\r\n' and then the chunk itself, followed by another
|
174
|
+
# '\r\n'. The terminating chunk is a regular chunk, with the exception that its length
|
175
|
+
# is zero. It is followed by the trailer, which consists of a (possibly empty) sequence of
|
176
|
+
# header fields.
|
177
|
+
client_conn << chunk.bytesize.to_s(16) + HTTP_EOP if resp['Transfer-Encoding'] == 'chunked'
|
178
|
+
|
167
179
|
client_conn << chunk
|
168
180
|
end
|
169
181
|
end
|
@@ -173,6 +185,7 @@ module ForwardProxy
|
|
173
185
|
def handle_error(client_conn, err)
|
174
186
|
status_code = case err
|
175
187
|
when Errors::ConnectionTimeoutError then 504
|
188
|
+
when Errors::HTTPMethodNotImplemented then 501
|
176
189
|
else
|
177
190
|
502
|
178
191
|
end
|
@@ -180,7 +193,7 @@ module ForwardProxy
|
|
180
193
|
client_conn.puts <<~eos.chomp
|
181
194
|
HTTP/1.1 #{status_code}
|
182
195
|
Via: #{HEADER_VIA}
|
183
|
-
#{
|
196
|
+
#{HTTP_EOP}
|
184
197
|
eos
|
185
198
|
|
186
199
|
logger.error(err.message)
|
@@ -196,6 +209,7 @@ module ForwardProxy
|
|
196
209
|
|
197
210
|
klass = case req.request_method
|
198
211
|
when METHOD_GET then Net::HTTP::Get
|
212
|
+
when METHOD_HEAD then Net::HTTP::Head
|
199
213
|
when METHOD_POST then Net::HTTP::Post
|
200
214
|
else
|
201
215
|
raise Errors::HTTPMethodNotImplemented
|
@@ -1,24 +1,29 @@
|
|
1
1
|
module ForwardProxy
|
2
2
|
class ThreadPool
|
3
|
-
attr_reader :queue, :size
|
3
|
+
attr_reader :queue, :size, :threads
|
4
4
|
|
5
5
|
def initialize(size)
|
6
|
-
@
|
7
|
-
@
|
6
|
+
@queue = Queue.new
|
7
|
+
@size = size
|
8
|
+
@threads = []
|
8
9
|
end
|
9
10
|
|
10
11
|
def start
|
11
12
|
size.times do
|
12
|
-
Thread.new do
|
13
|
+
thread = Thread.new do
|
13
14
|
loop do
|
14
15
|
job, args = queue.pop
|
15
16
|
job.call(*args)
|
16
17
|
end
|
17
18
|
end
|
19
|
+
|
20
|
+
threads.push(thread)
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
21
24
|
def schedule(*args, &block)
|
25
|
+
raise Exception, "no threads" unless threads.any?(&:alive?)
|
26
|
+
|
22
27
|
queue.push([block, args])
|
23
28
|
end
|
24
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forward-proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Moriarty
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Forward proxy using just Ruby standard libraries.
|
14
14
|
email:
|