forward-proxy 0.6.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/forward_proxy/server.rb +23 -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: e40f32962fa3503f6269cee6997a1288ad7921b7d24462ff4258947778850f21
|
4
|
+
data.tar.gz: c1330120ddf74e8e644b051c9b7c30986f0b6a1428d2420c92d8d02649acb846
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28ffbea37fa7cfa64e6cd40c56b4f9584d016f5b305567beb939b400e610592a79b7481a9e08171df210e454d37efa18848b7236cc720ffa79a18a001b020f5f
|
7
|
+
data.tar.gz: 054af3f071444d16b77c138e79cf616eef5096081805950cca99d4c0d1ca5352763c50482011b1c11f725dab78293949e3ec5ea678cea0ea782aa8c198a9f34a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.9.0
|
4
|
+
|
5
|
+
- bugfix chunked response behavior.
|
6
|
+
|
7
|
+
## 0.8.0
|
8
|
+
|
9
|
+
- add http `head` support.
|
10
|
+
- add http `501` not implemented status response.
|
11
|
+
|
12
|
+
## 0.7.0
|
13
|
+
|
14
|
+
- bugfix default threads from `4` to `128`.
|
15
|
+
|
3
16
|
## 0.6.0
|
4
17
|
|
5
18
|
- 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:
|
@@ -165,6 +166,16 @@ module ForwardProxy
|
|
165
166
|
# instead stream the body directly to an IO.
|
166
167
|
resp.read_body do |chunk|
|
167
168
|
client_conn << chunk
|
169
|
+
# The following comments are taken from:
|
170
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding#directives
|
171
|
+
|
172
|
+
# Data is sent in a series of chunks. The Content-Length header is omitted in this case and
|
173
|
+
# at the beginning of each chunk you need to add the length of the current chunk in
|
174
|
+
# hexadecimal format, followed by '\r\n' and then the chunk itself, followed by another
|
175
|
+
# '\r\n'. The terminating chunk is a regular chunk, with the exception that its length
|
176
|
+
# is zero. It is followed by the trailer, which consists of a (possibly empty) sequence of
|
177
|
+
# header fields.
|
178
|
+
client_conn << HTTP_EOP if resp['Transfer-Encoding'] == 'chunked'
|
168
179
|
end
|
169
180
|
end
|
170
181
|
end
|
@@ -173,6 +184,7 @@ module ForwardProxy
|
|
173
184
|
def handle_error(client_conn, err)
|
174
185
|
status_code = case err
|
175
186
|
when Errors::ConnectionTimeoutError then 504
|
187
|
+
when Errors::HTTPMethodNotImplemented then 501
|
176
188
|
else
|
177
189
|
502
|
178
190
|
end
|
@@ -180,7 +192,7 @@ module ForwardProxy
|
|
180
192
|
client_conn.puts <<~eos.chomp
|
181
193
|
HTTP/1.1 #{status_code}
|
182
194
|
Via: #{HEADER_VIA}
|
183
|
-
#{
|
195
|
+
#{HTTP_EOP}
|
184
196
|
eos
|
185
197
|
|
186
198
|
logger.error(err.message)
|
@@ -196,6 +208,7 @@ module ForwardProxy
|
|
196
208
|
|
197
209
|
klass = case req.request_method
|
198
210
|
when METHOD_GET then Net::HTTP::Get
|
211
|
+
when METHOD_HEAD then Net::HTTP::Head
|
199
212
|
when METHOD_POST then Net::HTTP::Post
|
200
213
|
else
|
201
214
|
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.0
|
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:
|