forward-proxy 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccf19df114eeec55eaef8765999561904d8f5b6cd91b7ed2016053ec9e717408
4
- data.tar.gz: ce712f520c0ed32b93ea211ff658d330bef7eeb26c2ddfcea1246d955ce78175
3
+ metadata.gz: 3018291ebebbfa87a02ba1409fa3f0c0af9b5d0ffb8917636dd4f8e397d8a4fb
4
+ data.tar.gz: dd3420d19ee1ac89064d7fd965768072cc25ce100555a4dc59881530fc2b6d66
5
5
  SHA512:
6
- metadata.gz: b71608455b079161950b09521d8fd99496767463f3e2aa0f0d293f21e3955b03d7b0ba12f06f3b3df1ff6674d598ed2e7eec7492ffb8fd9047ebb19771625251
7
- data.tar.gz: '092035474f162e29d2c7d0735b43cd38e41580aadca7ae50e97e02dee8e6f3825f50393497c0a8db8a5e0b3622d3e44e25e69e03ae02b56eba1cad55abdc1388'
6
+ metadata.gz: c1676662f33627745b09c2049957a4232885862bac77ba4f1ecb48b085683ef832825d2a0b15c725bdf6553456bb710c1b847f4027e55e8ed31c1c31aa1b307f
7
+ data.tar.gz: '08652da6a675acfb0c371d571bad140d3a50673d76d2aae74ea6a33f2b4f1e21b07f3378fcaaf74099d6fe93de29cc923108c1d278a9364b885b80a405951643'
@@ -8,7 +8,7 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- ruby: [ '2.3', '2.7' ]
11
+ ruby: [ '2.5', '2.7' ]
12
12
 
13
13
  steps:
14
14
  - uses: actions/checkout@v2
@@ -8,7 +8,7 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- ruby: [ '2.3', '2.7' ]
11
+ ruby: [ '2.5', '2.7' ]
12
12
 
13
13
  steps:
14
14
  - uses: actions/checkout@v2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.6.0
4
+
5
+ - add connection timeout to stop tracking connection from saturating client threads.
6
+ - add cli flats for connection timeout `-t` and `--timeout`.
7
+ - change cli short flag `-t` to `-c` for `--threads`.
8
+
9
+ ## 0.5.0
10
+
11
+ - increase default threads from `32` to `128`.
12
+
3
13
  ## 0.2.0
4
14
 
5
15
  - Extract errors into module.
data/README.md CHANGED
@@ -38,7 +38,8 @@ forward-proxy
38
38
  Usage: forward-proxy [options]
39
39
  -p, --port=PORT Bind to specified port. Default: 9292
40
40
  -b, --binding=BINDING Bind to the specified ip. Default: 127.0.0.1
41
- -t, --threads=THREADS Specify the number of client threads. Default: 32
41
+ -t, --timeout=TIMEOUT Specify the connection timeout in seconds. Default: 300
42
+ -c, --threads=THREADS Specify the number of client threads. Default: 128
42
43
  -h, --help Prints this help.
43
44
  ```
44
45
 
data/exe/forward-proxy CHANGED
@@ -15,7 +15,12 @@ OptionParser.new do |parser|
15
15
  options[:bind_address] = bind_address
16
16
  end
17
17
 
18
- parser.on("-tTHREADS", "--threads=THREADS", Integer,
18
+ parser.on("-tTIMEOUT", "--timeout=TIMEOUT", Integer,
19
+ "Specify the connection timeout in seconds. Default: 300") do |threads|
20
+ options[:timeout] = threads
21
+ end
22
+
23
+ parser.on("-cTHREADS", "--threads=THREADS", Integer,
19
24
  "Specify the number of client threads. Default: 128") do |threads|
20
25
  options[:threads] = threads
21
26
  end
@@ -0,0 +1,5 @@
1
+ module ForwardProxy
2
+ module Errors
3
+ class ConnectionTimeoutError < StandardError; end
4
+ end
5
+ end
@@ -1,20 +1,23 @@
1
1
  require 'logger'
2
2
  require 'socket'
3
- require 'webrick'
3
+ require 'timeout'
4
4
  require 'net/http'
5
+ require 'webrick'
6
+ require 'forward_proxy/errors/connection_timeout_error'
5
7
  require 'forward_proxy/errors/http_method_not_implemented'
6
8
  require 'forward_proxy/errors/http_parse_error'
7
9
  require 'forward_proxy/thread_pool'
8
10
 
9
11
  module ForwardProxy
10
12
  class Server
11
- attr_reader :bind_address, :bind_port, :logger
13
+ attr_reader :bind_address, :bind_port, :logger, :timeout
12
14
 
13
- def initialize(bind_address: "127.0.0.1", bind_port: 9292, threads: 128, logger: default_logger)
15
+ def initialize(bind_address: "127.0.0.1", bind_port: 9292, threads: 128, timeout: 300, logger: default_logger)
14
16
  @bind_address = bind_address
15
17
  @bind_port = bind_port
16
18
  @logger = logger
17
19
  @thread_pool = ThreadPool.new(threads)
20
+ @timeout = timeout
18
21
  end
19
22
 
20
23
  def start
@@ -27,18 +30,20 @@ module ForwardProxy
27
30
  loop do
28
31
  thread_pool.schedule(socket.accept) do |client_conn|
29
32
  begin
30
- req = parse_req(client_conn)
33
+ Timeout::timeout(timeout, Errors::ConnectionTimeoutError, "connection exceeded #{timeout} seconds") do
34
+ req = parse_req(client_conn)
31
35
 
32
- logger.info(req.request_line.strip)
36
+ logger.info(req.request_line.strip)
33
37
 
34
- case req.request_method
35
- when METHOD_CONNECT then handle_tunnel(client_conn, req)
36
- when METHOD_GET, METHOD_POST then handle(client_conn, req)
37
- else
38
- raise Errors::HTTPMethodNotImplemented
38
+ case req.request_method
39
+ when METHOD_CONNECT then handle_tunnel(client_conn, req)
40
+ when METHOD_GET, METHOD_POST then handle(client_conn, req)
41
+ else
42
+ raise Errors::HTTPMethodNotImplemented
43
+ end
39
44
  end
40
45
  rescue => e
41
- handle_error(e, client_conn)
46
+ handle_error(client_conn, e)
42
47
  ensure
43
48
  client_conn.close
44
49
  end
@@ -62,14 +67,14 @@ module ForwardProxy
62
67
 
63
68
  attr_reader :socket, :thread_pool
64
69
 
65
- # The following comments are from the IETF document
66
- # "Hypertext Transfer Protocol -- HTTP/1.1: Basic Rules"
67
- # https://datatracker.ietf.org/doc/html/rfc2616#section-2.2
68
-
69
70
  METHOD_CONNECT = "CONNECT"
70
71
  METHOD_GET = "GET"
71
72
  METHOD_POST = "POST"
72
73
 
74
+ # The following comments are from the IETF document
75
+ # "Hypertext Transfer Protocol -- HTTP/1.1: Basic Rules"
76
+ # https://datatracker.ietf.org/doc/html/rfc2616#section-2.2
77
+
73
78
  # HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
74
79
  # protocol elements except the entity-body.
75
80
  HEADER_EOP = "\r\n"
@@ -165,9 +170,15 @@ module ForwardProxy
165
170
  end
166
171
  end
167
172
 
168
- def handle_error(err, client_conn)
173
+ def handle_error(client_conn, err)
174
+ status_code = case err
175
+ when Errors::ConnectionTimeoutError then 504
176
+ else
177
+ 502
178
+ end
179
+
169
180
  client_conn.puts <<~eos.chomp
170
- HTTP/1.1 502
181
+ HTTP/1.1 #{status_code}
171
182
  Via: #{HEADER_VIA}
172
183
  #{HEADER_EOP}
173
184
  eos
@@ -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
- @size = size
7
- @queue = Queue.new
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
@@ -1,3 +1,3 @@
1
1
  module ForwardProxy
2
- VERSION = "0.5.0"
2
+ VERSION = "0.7.0"
3
3
  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.5.0
4
+ version: 0.7.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-07-13 00:00:00.000000000 Z
11
+ date: 2021-07-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Forward proxy using just Ruby standard libraries.
14
14
  email:
@@ -32,6 +32,7 @@ files:
32
32
  - exe/forward-proxy
33
33
  - forward-proxy.gemspec
34
34
  - lib/forward_proxy.rb
35
+ - lib/forward_proxy/errors/connection_timeout_error.rb
35
36
  - lib/forward_proxy/errors/http_method_not_implemented.rb
36
37
  - lib/forward_proxy/errors/http_parse_error.rb
37
38
  - lib/forward_proxy/server.rb