forward-proxy 0.3.0 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2f3ade2ec039aaadb19726b347d6cddb7db0f2590b91ab5d6eb69b8fd5c0aee
4
- data.tar.gz: 0733602e8b7bab9e95df20cff04bc11981964260db17242460a2c26341a9032b
3
+ metadata.gz: 1d2b9dbd7abcfa81bcdbd29b6dd2045e6d2210e92b303f7cfcdc4ab35ab0b868
4
+ data.tar.gz: 729d4b7d964c8a5a3bec860f6bceb669a12225900a01b4737de8fdf6ba02a049
5
5
  SHA512:
6
- metadata.gz: 9c25af1d60872d711a475028eddc06bc54ee7dd609cd3cbd1858ff667a1facb5e1cfb7ca38889ab7a8603d018a6c69e4b56ee11eaba525818f2cd0bf0a7b59c5
7
- data.tar.gz: d105d9a16183951129e62ed1b905a12e12f251541154e90869bb9a74449c10925ec19e3f3fce8d9300f7af38a00dcf6aa26e0a4f2d37ca9882a1bc64a494cba8
6
+ metadata.gz: 70c0b51f0313e4ffedd1146ae93035db45bc8fe3a7cee647ea11cb0397d6862e99047befbc39aee6a08b17fd1e3d16394eb59ad9ad092140ea9354da10feadf6
7
+ data.tar.gz: b0f3587f3c08b255be222f8f59530e19b5fcc6e589f93eafb1eaa21fac832a0f01847dfcf309ed443e51fdafd96a516241143c1a75795b3d09f0ce7088eedac0
@@ -1,3 +1,4 @@
1
+ require 'logger'
1
2
  require 'socket'
2
3
  require 'webrick'
3
4
  require 'net/http'
@@ -7,9 +8,10 @@ require 'forward_proxy/thread_pool'
7
8
 
8
9
  module ForwardProxy
9
10
  class Server
10
- attr_reader :bind_address, :bind_port
11
+ attr_reader :bind_address, :bind_port, :logger
11
12
 
12
- def initialize(bind_address: "127.0.0.1", bind_port: 9292, threads: 32)
13
+ def initialize(bind_address: "127.0.0.1", bind_port: 9292, threads: 32, logger: Logger.new(STDOUT, level: :info))
14
+ @logger = logger
13
15
  @thread_pool = ThreadPool.new(threads)
14
16
  @bind_address = bind_address
15
17
  @bind_port = bind_port
@@ -20,14 +22,14 @@ module ForwardProxy
20
22
 
21
23
  @socket = TCPServer.new(bind_address, bind_port)
22
24
 
23
- log("Listening #{bind_address}:#{bind_port}")
25
+ logger.info("Listening #{bind_address}:#{bind_port}")
24
26
 
25
27
  loop do
26
28
  thread_pool.schedule(socket.accept) do |client_conn|
27
29
  begin
28
30
  req = parse_req(client_conn)
29
31
 
30
- log(req.request_line)
32
+ logger.info(req.request_line)
31
33
 
32
34
  case req.request_method
33
35
  when METHOD_CONNECT then handle_tunnel(client_conn, req)
@@ -45,12 +47,12 @@ module ForwardProxy
45
47
  rescue Interrupt
46
48
  shutdown
47
49
  rescue IOError, Errno::EBADF => e
48
- log(e.message, "ERROR")
50
+ logger.error(e.message)
49
51
  end
50
52
 
51
53
  def shutdown
52
54
  if socket
53
- log("Shutting down")
55
+ logger.info("Shutting down")
54
56
 
55
57
  socket.close
56
58
  end
@@ -60,10 +62,18 @@ module ForwardProxy
60
62
 
61
63
  attr_reader :socket, :thread_pool
62
64
 
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
+
63
69
  METHOD_CONNECT = "CONNECT"
64
70
  METHOD_GET = "GET"
65
71
  METHOD_POST = "POST"
66
72
 
73
+ # HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
74
+ # protocol elements except the entity-body.
75
+ HEADER_EOP = "\r\n"
76
+
67
77
  # The following comments are from the IETF document
68
78
  # "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"
69
79
  # https://tools.ietf.org/html/rfc7231#section-4.3.6
@@ -96,7 +106,10 @@ module ForwardProxy
96
106
  # blank line that concludes the successful response's header section;
97
107
  # data received after that blank line is from the server identified by
98
108
  # the request-target.
99
- client_conn.write "HTTP/1.1 200 OK\n\n"
109
+ client_conn.write <<~eos.chomp
110
+ HTTP/1.1 200 OK
111
+ #{HEADER_EOP}
112
+ eos
100
113
 
101
114
  # The CONNECT method requests that the recipient establish a tunnel to
102
115
  # the destination origin server identified by the request-target and,
@@ -113,11 +126,30 @@ module ForwardProxy
113
126
  def handle(client_conn, req)
114
127
  Net::HTTP.start(req.host, req.port) do |http|
115
128
  http.request(map_webrick_to_net_http_req(req)) do |resp|
116
- headers= resp.to_hash.merge(Via: [HEADER_VIA, resp['Via']].compact.join(', '))
129
+ # The following comments are from the IETF document
130
+ # "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"
131
+ # https://tools.ietf.org/html/rfc7231#section-4.3.6
132
+
133
+ # An intermediary MAY combine an ordered subsequence of Via header
134
+ # field entries into a single such entry if the entries have identical
135
+ # received-protocol values. For example,
136
+ #
137
+ # Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
138
+ #
139
+ # could be collapsed to
140
+ #
141
+ # Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
142
+ #
143
+ # A sender SHOULD NOT combine multiple entries unless they are all
144
+ # under the same organizational control and the hosts have already been
145
+ # replaced by pseudonyms. A sender MUST NOT combine entries that have
146
+ # different received-protocol values.
147
+ headers = resp.to_hash.merge(Via: [HEADER_VIA, resp['Via']].compact.join(', '))
117
148
 
118
149
  client_conn.puts <<~eos.chomp
119
150
  HTTP/1.1 #{resp.code}
120
- #{headers.map { |header, value| "#{header}: #{value}" }.join("\n")}\n\n
151
+ #{headers.map { |header, value| "#{header}: #{value}" }.join("\n")}
152
+ #{HEADER_EOP}
121
153
  eos
122
154
 
123
155
  # The following comments are taken from:
@@ -137,10 +169,12 @@ module ForwardProxy
137
169
  client_conn.puts <<~eos.chomp
138
170
  HTTP/1.1 502
139
171
  Via: #{HEADER_VIA}
172
+ #{HEADER_EOP}
140
173
  eos
141
174
 
142
- log(err.message, "ERROR")
143
- puts err.backtrace.map { |line| " #{line}" }
175
+ logger.error(err.message)
176
+
177
+ logger.debug(err.backtrace.join("\n"))
144
178
  end
145
179
 
146
180
  def map_webrick_to_net_http_req(req)
@@ -159,7 +193,7 @@ module ForwardProxy
159
193
  def transfer(src_conn, dest_conn)
160
194
  IO.copy_stream(src_conn, dest_conn)
161
195
  rescue => e
162
- log(e.message, "WARNING")
196
+ logger.warn(e.message)
163
197
  end
164
198
 
165
199
  def parse_req(client_conn)
@@ -169,9 +203,5 @@ module ForwardProxy
169
203
  rescue => e
170
204
  throw Errors::HTTPParseError.new(e.message)
171
205
  end
172
-
173
- def log(str, level = 'INFO')
174
- puts "[#{Time.now}] #{level} #{str}"
175
- end
176
206
  end
177
207
  end
@@ -1,3 +1,3 @@
1
1
  module ForwardProxy
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.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.3.0
4
+ version: 0.4.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-06-27 00:00:00.000000000 Z
11
+ date: 2021-07-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Forward proxy using just Ruby standard libraries.
14
14
  email: