forward-proxy 0.1.4 → 0.1.5

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
  SHA1:
3
- metadata.gz: f0e621e13501a70783e49eb16c52fd937974bc7e
4
- data.tar.gz: 70488fc1e2147c6c181e1dbb102929fe81eb1ecb
3
+ metadata.gz: 3e94626ce91d870564fcbed5db9133ddee5a1167
4
+ data.tar.gz: 44c9c4e4ca3a4036a8c1e9698dac6a203c3fe367
5
5
  SHA512:
6
- metadata.gz: b5bd0ed7c697ea9ea8e3fb973e31f44947b2c9c5d1b7c23cc025580f82c3cdf16aaf238a9e0b831397c69bf803b5d04f02212553de968dfece8c52c5d1688104
7
- data.tar.gz: 9a0b6db5127d71f0351577232d744ff0497c04c35a6a6e70580894d109dd160910b7ec4144134c295bafd35add0c3a9d6e57c6c47f63ca7ec92f16c67fa10c67
6
+ metadata.gz: c13a9fa915fb77699702226408cbd160d61cd375789beb947299423c788594c7f5d7af3783624fcf5fb30e8521e8a5e98c4953e7f1b5c7e477a756bda153634b
7
+ data.tar.gz: 609126058336e8cc597c0df21b3a3cb65c4d1216d7af11d77dec09eda104c6277811d59b942d38c46f8776c0cf1b8f137d09778793343a88c138872f65b06b54
@@ -0,0 +1,25 @@
1
+ name: Command Line Interface
2
+
3
+ on: [pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+
9
+ strategy:
10
+ matrix:
11
+ ruby: [ '2.3', '2.7' ]
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: gem install forward-proxy
20
+ - run: |
21
+ exe/forward-proxy --h
22
+ exe/forward-proxy --help
23
+ exe/forward-proxy --binding 127.0.0.1 --port 3001 --threads 2 &
24
+ sleep 1
25
+ curl --fail -x http://127.0.0.1:3001 https://google.com/
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.1.5
4
+
5
+ - stream http proxy requests.
6
+ - call shutdown on `Interrupt`
7
+ - remove waiting for the thread-pool to finish on shutdown and just close the server conn.
8
+
3
9
  ## 0.1.4
4
10
 
5
11
  - `accept` connections via thread pool.
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
+ gem "yard", "~> 0.9"
7
8
  gem "minitest", "~> 5.0"
8
9
  gem "minitest-reporters", "~> 1.4"
9
10
  gem "simplecov", "~> 0.17"
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![Gem Version][3] ![Gem][1] ![Build Status][2]
4
4
 
5
- 100LOC Ruby forward proxy using just standard libraries.
5
+ 100 LOC Ruby forward proxy using only standard libraries.
6
6
 
7
7
  ```
8
8
  $ forward-proxy --binding 0.0.0.0 --port 3182 --threads 2
data/Rakefile CHANGED
@@ -1,5 +1,12 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require 'yard'
4
+
5
+ YARD::Rake::YardocTask.new do |t|
6
+ t.files = ['lib/**/*.rb', 'README', 'CHANGELOG', 'CODE_OF_CONDUCT']
7
+ t.options = []
8
+ t.stats_options = ['--list-undoc']
9
+ end
3
10
 
4
11
  Rake::TestTask.new(:test) do |t|
5
12
  t.libs << "test"
@@ -7,4 +14,16 @@ Rake::TestTask.new(:test) do |t|
7
14
  t.test_files = FileList["test/**/*_test.rb"]
8
15
  end
9
16
 
17
+ namespace :gh do
18
+ desc "Deploy yard docs to github pages"
19
+ task :pages => :yard do
20
+ `git add -f doc`
21
+ `git commit -am "update: $(date)"`
22
+ `git subtree split --prefix doc -b gh-pages`
23
+ `git push -f origin gh-pages:gh-pages`
24
+ `git branch -D gh-pages`
25
+ `git reset head~1`
26
+ end
27
+ end
28
+
10
29
  task :default => :test
@@ -24,13 +24,14 @@ module ForwardProxy
24
24
  log("Listening #{bind_address}:#{bind_port}")
25
25
 
26
26
  loop do
27
- # The following comments are from "man 2 accept"
27
+ # The following comments are from https://stackoverflow.com/q/5124320/273101
28
28
  #
29
- # The argument socket is a socket that has been created with socket(2), bound to an address with bind(2), and is listening for connections after a listen(2). accept() extracts the
30
- # first connection request on the queue of pending connections, creates a new socket with the same properties of socket, and allocates a new file descriptor for the socket. If no
31
- # pending connections are present on the queue, and the socket is not marked as non-blocking, accept() blocks the caller until a connection is present. If the socket is marked
32
- # non-blocking and no pending connections are present on the queue, accept() returns an error as described below. The accepted socket may not be used to accept more connections.
33
- # The original socket socket, remains open.
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.
34
35
  thread_pool.schedule(server.accept) do |client_conn|
35
36
  begin
36
37
  req = parse_req(client_conn)
@@ -44,9 +45,16 @@ module ForwardProxy
44
45
  raise HTTPMethodNotImplemented
45
46
  end
46
47
  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.
47
55
  client_conn.puts <<~eos.chomp
48
56
  HTTP/1.1 502
49
- Server: ForwardProxy
57
+ Via: #{HEADER_VIA}
50
58
  eos
51
59
 
52
60
  puts e.message
@@ -57,15 +65,12 @@ module ForwardProxy
57
65
  end
58
66
  end
59
67
  rescue Interrupt
60
- log("Exiting...")
61
- rescue Errno::EBADF => e
68
+ shutdown
69
+ rescue IOError, Errno::EBADF => e
62
70
  log(e.message, "ERROR")
63
71
  end
64
72
 
65
73
  def shutdown
66
- log("Closing client connections...")
67
- thread_pool.shutdown
68
-
69
74
  log("Stoping server...")
70
75
  server.close if server
71
76
  end
@@ -78,6 +83,17 @@ module ForwardProxy
78
83
  METHOD_GET = "GET"
79
84
  METHOD_POST = "POST"
80
85
 
86
+ # The following comments are from the IETF document
87
+ # "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"
88
+ # https://tools.ietf.org/html/rfc7231#section-4.3.6
89
+
90
+ # A proxy MUST send an appropriate Via header field, as described
91
+ # below, in each message that it forwards. An HTTP-to-HTTP gateway
92
+ # MUST send an appropriate Via header field in each inbound request
93
+ # message and MAY send a Via header field in forwarded response
94
+ # messages.
95
+ HEADER_VIA = "HTTP/1.1 ForwardProxy"
96
+
81
97
  def handle_tunnel(client_conn, req)
82
98
  # The following comments are from the IETF document
83
99
  # "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"
@@ -114,22 +130,19 @@ module ForwardProxy
114
130
  end
115
131
 
116
132
  def handle(client_conn, req)
117
- resp = Net::HTTP.start(req.host, req.port) do |http|
118
- http.request map_webrick_to_net_http_req(req)
133
+ Net::HTTP.start(req.host, req.port) do |http|
134
+ http.request(map_webrick_to_net_http_req(req)) do |resp|
135
+ client_conn.puts <<~eos.chomp
136
+ HTTP/1.1 #{resp.code}
137
+ Via: #{[HEADER_VIA, resp['Via']].compact.join(', ')}
138
+ #{resp.each.map { |header, value| "#{header}: #{value}" }.join("\n")}\n\n
139
+ eos
140
+
141
+ resp.read_body do |chunk|
142
+ client_conn << chunk
143
+ end
144
+ end
119
145
  end
120
-
121
- # A proxy MUST send an appropriate Via header field, as described
122
- # below, in each message that it forwards. An HTTP-to-HTTP gateway
123
- # MUST send an appropriate Via header field in each inbound request
124
- # message and MAY send a Via header field in forwarded response
125
- # messages.
126
- client_conn.puts <<~eos.chomp
127
- HTTP/1.1 #{resp.code}
128
- Via: #{["1.1 ForwardProxy", resp['Via']].compact.join(', ')}
129
- #{resp.each.map { |header, value| "#{header}: #{value}" }.join("\n")}
130
-
131
- #{resp.body}
132
- eos
133
146
  end
134
147
 
135
148
  def map_webrick_to_net_http_req(req)
@@ -1,3 +1,3 @@
1
1
  module ForwardProxy
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
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.4
4
+ version: 0.1.5
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-15 00:00:00.000000000 Z
11
+ date: 2021-01-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Forward proxy using just Ruby standard libraries.
14
14
  email:
@@ -19,6 +19,7 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - ".github/workflows/ci.yaml"
22
+ - ".github/workflows/cli.yaml"
22
23
  - ".gitignore"
23
24
  - CHANGELOG.md
24
25
  - CODE_OF_CONDUCT.md