forward-proxy 0.1.5 → 0.2.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 +5 -5
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/exe/forward-proxy +1 -2
- data/lib/forward_proxy/errors/http_method_not_implemented.rb +5 -0
- data/lib/forward_proxy/errors/http_parse_error.rb +5 -0
- data/lib/forward_proxy/server.rb +21 -28
- data/lib/forward_proxy/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 628359d25536c4190014c9e082fff41b2adef209f04a62d8a6b217c078f3b58b
|
4
|
+
data.tar.gz: 7834932b7242fd66c120d270a922e385a6a58ab63c65e8ce2b7957da43ba5a11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c47ab1d691807a23ba779f1ae8d4feecd32300f8d840044f66a5cc2f40ccd33c095db60ca9e3f99fb3c8fd60c02ae46d5d8d07b6a4de6298bef24731fb57cb4
|
7
|
+
data.tar.gz: 609a35651496d98e4977f3691c7834efd58fe736615b3b4594e0bc61d11dad0088f11f535f6b287db85f95c1cc8ab55ea2a536447028b690d92ffd0aa3e60669
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
![Gem Version][3] ![Gem][1] ![Build Status][2]
|
4
4
|
|
5
|
-
|
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"
|
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
|
data/lib/forward_proxy/server.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
|
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
|
-
|
75
|
-
|
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 :
|
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(
|
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')
|
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.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-
|
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
|
-
|
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.
|