forward-proxy 0.1.5 → 0.2.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
- SHA1:
3
- metadata.gz: 3e94626ce91d870564fcbed5db9133ddee5a1167
4
- data.tar.gz: 44c9c4e4ca3a4036a8c1e9698dac6a203c3fe367
2
+ SHA256:
3
+ metadata.gz: 628359d25536c4190014c9e082fff41b2adef209f04a62d8a6b217c078f3b58b
4
+ data.tar.gz: 7834932b7242fd66c120d270a922e385a6a58ab63c65e8ce2b7957da43ba5a11
5
5
  SHA512:
6
- metadata.gz: c13a9fa915fb77699702226408cbd160d61cd375789beb947299423c788594c7f5d7af3783624fcf5fb30e8521e8a5e98c4953e7f1b5c7e477a756bda153634b
7
- data.tar.gz: 609126058336e8cc597c0df21b3a3cb65c4d1216d7af11d77dec09eda104c6277811d59b942d38c46f8776c0cf1b8f137d09778793343a88c138872f65b06b54
6
+ metadata.gz: 8c47ab1d691807a23ba779f1ae8d4feecd32300f8d840044f66a5cc2f40ccd33c095db60ca9e3f99fb3c8fd60c02ae46d5d8d07b6a4de6298bef24731fb57cb4
7
+ data.tar.gz: 609a35651496d98e4977f3691c7834efd58fe736615b3b4594e0bc61d11dad0088f11f535f6b287db85f95c1cc8ab55ea2a536447028b690d92ffd0aa3e60669
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.2.0
4
+
5
+ - Extract errors into module.
6
+
3
7
  ## 0.1.5
4
8
 
5
9
  - stream http proxy requests.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![Gem Version][3] ![Gem][1] ![Build Status][2]
4
4
 
5
- 100 LOC Ruby forward proxy using only standard libraries.
5
+ Minimal forward proxy using 150LOC and only standard libraries. Useful for development, testing, and learning.
6
6
 
7
7
  ```
8
8
  $ forward-proxy --binding 0.0.0.0 --port 3182 --threads 2
data/exe/forward-proxy CHANGED
@@ -7,7 +7,7 @@ options = {}
7
7
  OptionParser.new do |parser|
8
8
  parser.banner = "Usage: forward-proxy [options]"
9
9
 
10
- parser.on("-pPORT", "--port=PORT", "Bind to specified port. Default: 9292", String) do |bind_port|
10
+ parser.on("-pPORT", "--port=PORT", String, "Bind to specified port. Default: 9292") do |bind_port|
11
11
  options[:bind_port] = bind_port
12
12
  end
13
13
 
@@ -26,6 +26,5 @@ OptionParser.new do |parser|
26
26
  end.parse!
27
27
 
28
28
  require_relative '../lib/forward_proxy'
29
-
30
29
  server = ForwardProxy::Server.new(options)
31
30
  server.start
@@ -0,0 +1,5 @@
1
+ module ForwardProxy
2
+ module Errors
3
+ class HTTPMethodNotImplemented < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module ForwardProxy
2
+ module Errors
3
+ class HTTPParseError < StandardError; end
4
+ end
5
+ end
@@ -1,12 +1,11 @@
1
- require 'forward_proxy/thread_pool'
2
1
  require 'socket'
3
2
  require 'webrick'
4
3
  require 'net/http'
4
+ require 'forward_proxy/errors/http_method_not_implemented'
5
+ require 'forward_proxy/errors/http_parse_error'
6
+ require 'forward_proxy/thread_pool'
5
7
 
6
8
  module ForwardProxy
7
- class HTTPMethodNotImplemented < StandardError; end
8
- class HTTPParseError < StandardError; end
9
-
10
9
  class Server
11
10
  attr_reader :bind_address, :bind_port
12
11
 
@@ -19,20 +18,12 @@ module ForwardProxy
19
18
  def start
20
19
  thread_pool.start
21
20
 
22
- @server = TCPServer.new(bind_address, bind_port)
21
+ @socket = TCPServer.new(bind_address, bind_port)
23
22
 
24
23
  log("Listening #{bind_address}:#{bind_port}")
25
24
 
26
25
  loop do
27
- # The following comments are from https://stackoverflow.com/q/5124320/273101
28
- #
29
- # accept(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (accept() first appeared in 4.2BSD).
30
- #
31
- # We see that POSIX.1-2008 is a viable reference (check this for a description of relevant
32
- # standards for Linux systems). As already said in other answers, POSIX.1 standard specifies
33
- # accept function as (POSIX-)thread safe (as defined in Base Definitions, section 3.399 Thread Safe)
34
- # by not listing it on System Interfaces, section 2.9.1 Thread Safety.
35
- thread_pool.schedule(server.accept) do |client_conn|
26
+ thread_pool.schedule(socket.accept) do |client_conn|
36
27
  begin
37
28
  req = parse_req(client_conn)
38
29
 
@@ -42,16 +33,9 @@ module ForwardProxy
42
33
  when METHOD_CONNECT then handle_tunnel(client_conn, req)
43
34
  when METHOD_GET, METHOD_POST then handle(client_conn, req)
44
35
  else
45
- raise HTTPMethodNotImplemented
36
+ raise Errors::HTTPMethodNotImplemented
46
37
  end
47
38
  rescue => e
48
- # The following comments are from the IETF document
49
- # "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"
50
- # https://tools.ietf.org/html/rfc7231#section-6.6.3
51
-
52
- # The 502 (Bad Gateway) status code indicates that the server, while
53
- # acting as a gateway or proxy, received an invalid response from an
54
- # inbound server it accessed while attempting to fulfill the request.
55
39
  client_conn.puts <<~eos.chomp
56
40
  HTTP/1.1 502
57
41
  Via: #{HEADER_VIA}
@@ -71,13 +55,16 @@ module ForwardProxy
71
55
  end
72
56
 
73
57
  def shutdown
74
- log("Stoping server...")
75
- server.close if server
58
+ if socket
59
+ log("Shutting down")
60
+
61
+ socket.close
62
+ end
76
63
  end
77
64
 
78
65
  private
79
66
 
80
- attr_reader :server, :thread_pool
67
+ attr_reader :socket, :thread_pool
81
68
 
82
69
  METHOD_CONNECT = "CONNECT"
83
70
  METHOD_GET = "GET"
@@ -138,6 +125,12 @@ module ForwardProxy
138
125
  #{resp.each.map { |header, value| "#{header}: #{value}" }.join("\n")}\n\n
139
126
  eos
140
127
 
128
+ # The following comments are taken from:
129
+ # https://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html#class-Net::HTTP-label-Streaming+Response+Bodies
130
+
131
+ # By default Net::HTTP reads an entire response into memory. If you are
132
+ # handling large files or wish to implement a progress bar you can
133
+ # instead stream the body directly to an IO.
141
134
  resp.read_body do |chunk|
142
135
  client_conn << chunk
143
136
  end
@@ -152,13 +145,13 @@ module ForwardProxy
152
145
  when METHOD_GET then Net::HTTP::Get
153
146
  when METHOD_POST then Net::HTTP::Post
154
147
  else
155
- raise HTTPMethodNotImplemented
148
+ raise Errors::HTTPMethodNotImplemented
156
149
  end
157
150
 
158
151
  klass.new(req.path, req_headers)
159
152
  end
160
153
 
161
- def transfer(dest_conn, src_conn)
154
+ def transfer(src_conn, dest_conn)
162
155
  IO.copy_stream(src_conn, dest_conn)
163
156
  rescue => e
164
157
  log(e.message, "WARNING")
@@ -169,7 +162,7 @@ module ForwardProxy
169
162
  req.parse(client_conn)
170
163
  end
171
164
  rescue => e
172
- throw HTTPParseError.new(e.message)
165
+ throw Errors::HTTPParseError.new(e.message)
173
166
  end
174
167
 
175
168
  def log(str, level = 'INFO')
@@ -1,3 +1,3 @@
1
1
  module ForwardProxy
2
- VERSION = "0.1.5"
2
+ VERSION = "0.2.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.1.5
4
+ version: 0.2.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-01-20 00:00:00.000000000 Z
11
+ date: 2021-05-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Forward proxy using just Ruby standard libraries.
14
14
  email:
@@ -32,6 +32,8 @@ files:
32
32
  - exe/forward-proxy
33
33
  - forward-proxy.gemspec
34
34
  - lib/forward_proxy.rb
35
+ - lib/forward_proxy/errors/http_method_not_implemented.rb
36
+ - lib/forward_proxy/errors/http_parse_error.rb
35
37
  - lib/forward_proxy/server.rb
36
38
  - lib/forward_proxy/thread_pool.rb
37
39
  - lib/forward_proxy/version.rb
@@ -57,8 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
59
  - !ruby/object:Gem::Version
58
60
  version: '0'
59
61
  requirements: []
60
- rubyforge_project:
61
- rubygems_version: 2.5.2.3
62
+ rubygems_version: 3.0.3
62
63
  signing_key:
63
64
  specification_version: 4
64
65
  summary: Forward proxy.