forward-proxy 0.6.2 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|