async-http 0.52.3 → 0.52.4
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 +4 -4
- data/examples/licenses/gemspect.rb +71 -0
- data/examples/licenses/list.rb +90 -0
- data/lib/async/http/body/slowloris.rb +2 -2
- data/lib/async/http/endpoint.rb +2 -2
- data/lib/async/http/internet.rb +4 -0
- data/lib/async/http/protocol/http1/server.rb +3 -2
- data/lib/async/http/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99b5cbef0cb74dedeea089ac42ff1aa5315e1089079f812ff4120e9147ab22ec
|
4
|
+
data.tar.gz: dda68448abfa958e9a98814f35482bda367990191f9742292512c8f242745fe8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74ddbd13c0e1b3c5bae03ded50129ab73fac1285d480bef0ff8a944c1163651037d6a258f36757b8969f72ea7e63eaf145384b346aa7733f2a51430c85cba642
|
7
|
+
data.tar.gz: e1036b972800356861167204b1ecfbab6e164dbe51351bd15a2881214d5e437f1cda9bd53a75715bd41c74f91ea6911d438b2ebcc04adceede636d0814e79e1f
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'json'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
require 'protocol/http/header/authorization'
|
8
|
+
|
9
|
+
class RateLimitingError < StandardError; end
|
10
|
+
|
11
|
+
@user = ENV['GITHUB_USER']
|
12
|
+
@token = ENV['GITHUB_TOKEN']
|
13
|
+
|
14
|
+
unless @user && @token
|
15
|
+
fail "export GITHUB_USER and GITHUB_TOKEN!"
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_github_license(homepage_uri)
|
19
|
+
%r{github.com/(?<owner>.+?)/(?<repo>.+)} =~ homepage_uri
|
20
|
+
return nil unless repo
|
21
|
+
|
22
|
+
url = URI.parse("https://api.github.com/repos/#{owner}/#{repo}/license")
|
23
|
+
request = Net::HTTP::Get.new(url)
|
24
|
+
|
25
|
+
request['user-agent'] = 'fetch-github-licenses'
|
26
|
+
request['authorization'] = Protocol::HTTP::Header::Authorization.basic(@user, @token)
|
27
|
+
|
28
|
+
response = Net::HTTP.start(url.hostname) do |http|
|
29
|
+
http.request(request)
|
30
|
+
end
|
31
|
+
|
32
|
+
case response
|
33
|
+
when Net::HTTPOK
|
34
|
+
JSON.parse(response.body).dig('license', 'spdx_id')
|
35
|
+
when Net::HTTPNotFound, Net::HTTPMovedPermanently, Net::HTTPForbidden
|
36
|
+
nil
|
37
|
+
else
|
38
|
+
raise response.body
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch_rubygem_license(name, version)
|
43
|
+
url = URI.parse("https://rubygems.org/api/v2/rubygems/#{name}/versions/#{version}.json")
|
44
|
+
response = Net::HTTP.get_response(url)
|
45
|
+
|
46
|
+
case response
|
47
|
+
when Net::HTTPOK
|
48
|
+
body = JSON.parse(response.body)
|
49
|
+
[name, body.dig('licenses', 0) || fetch_github_license(body['homepage_uri'])]
|
50
|
+
when Net::HTTPNotFound
|
51
|
+
[name, nil] # from a non rubygems remote
|
52
|
+
when Net::HTTPTooManyRequests
|
53
|
+
raise RateLimitingError
|
54
|
+
else
|
55
|
+
raise response.body
|
56
|
+
end
|
57
|
+
rescue RateLimitingError
|
58
|
+
sleep 1
|
59
|
+
|
60
|
+
retry
|
61
|
+
end
|
62
|
+
|
63
|
+
threads = ARGF.map do |line|
|
64
|
+
if line == "GEM\n" .. line.chomp.empty?
|
65
|
+
/\A\s{4}(?<name>[a-z].+?) \((?<version>.+)\)\n\z/ =~ line
|
66
|
+
|
67
|
+
Thread.new { fetch_rubygem_license(name, version) } if name
|
68
|
+
end
|
69
|
+
end.compact
|
70
|
+
|
71
|
+
puts CSV.generate { |csv| threads.each { csv << _1.value } }
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'json'
|
5
|
+
require 'async/http/internet'
|
6
|
+
|
7
|
+
class RateLimitingError < StandardError; end
|
8
|
+
|
9
|
+
@internet = Async::HTTP::Internet.new
|
10
|
+
|
11
|
+
@user = ENV['GITHUB_USER']
|
12
|
+
@token = ENV['GITHUB_TOKEN']
|
13
|
+
|
14
|
+
unless @user && @token
|
15
|
+
fail "export GITHUB_USER and GITHUB_TOKEN!"
|
16
|
+
end
|
17
|
+
|
18
|
+
GITHUB_HEADERS = {
|
19
|
+
'user-agent' => 'fetch-github-licenses',
|
20
|
+
'authorization' => Protocol::HTTP::Header::Authorization.basic(@user, @token)
|
21
|
+
}
|
22
|
+
|
23
|
+
RUBYGEMS_HEADERS = {
|
24
|
+
'user-agent' => 'fetch-github-licenses'
|
25
|
+
}
|
26
|
+
|
27
|
+
def fetch_github_license(homepage_uri)
|
28
|
+
%r{github.com/(?<owner>.+?)/(?<repo>.+)} =~ homepage_uri
|
29
|
+
return nil unless repo
|
30
|
+
|
31
|
+
response = @internet.get("https://api.github.com/repos/#{owner}/#{repo}/license", GITHUB_HEADERS)
|
32
|
+
|
33
|
+
case response.status
|
34
|
+
when 200
|
35
|
+
return JSON.parse(response.read).dig('license', 'spdx_id')
|
36
|
+
when 404
|
37
|
+
return nil
|
38
|
+
else
|
39
|
+
raise response.read
|
40
|
+
end
|
41
|
+
ensure
|
42
|
+
response.finish
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_rubygem_license(name, version)
|
46
|
+
response = @internet.get("https://rubygems.org/api/v2/rubygems/#{name}/versions/#{version}.json", RUBYGEMS_HEADERS)
|
47
|
+
|
48
|
+
case response.status
|
49
|
+
when 200
|
50
|
+
body = JSON.parse(response.read)
|
51
|
+
[name, body.dig('licenses', 0) || fetch_github_license(body['homepage_uri'])]
|
52
|
+
when 404
|
53
|
+
[name, nil] # from a non rubygems remote
|
54
|
+
when 429
|
55
|
+
raise RateLimitingError
|
56
|
+
else
|
57
|
+
raise response.read
|
58
|
+
end
|
59
|
+
rescue RateLimitingError
|
60
|
+
response.finish
|
61
|
+
|
62
|
+
Async.logger.warn(name) {"Rate limited..."}
|
63
|
+
Async::Task.current.sleep(1.0)
|
64
|
+
|
65
|
+
retry
|
66
|
+
ensure
|
67
|
+
response.finish
|
68
|
+
end
|
69
|
+
|
70
|
+
Sync do |parent|
|
71
|
+
output = CSV.new($stdout)
|
72
|
+
|
73
|
+
tasks = ARGF.map do |line|
|
74
|
+
if line == "GEM\n" .. line.chomp.empty?
|
75
|
+
/\A\s{4}(?<name>[a-z].+?) \((?<version>.+)\)\n\z/ =~ line
|
76
|
+
|
77
|
+
parent.async do
|
78
|
+
fetch_rubygem_license(name, version)
|
79
|
+
end if name
|
80
|
+
end
|
81
|
+
end.compact
|
82
|
+
|
83
|
+
tasks.each do |task|
|
84
|
+
output << task.wait
|
85
|
+
end
|
86
|
+
|
87
|
+
@internet.instance_variable_get(:@clients).each do |name, client|
|
88
|
+
puts client.pool
|
89
|
+
end
|
90
|
+
end
|
@@ -37,8 +37,8 @@ module Async
|
|
37
37
|
|
38
38
|
# In order for this implementation to work correctly, you need to use a LimitedQueue.
|
39
39
|
# @param minimum_throughput [Integer] the minimum bytes per second otherwise this body will be forcefully closed.
|
40
|
-
def initialize(*
|
41
|
-
super(*
|
40
|
+
def initialize(*arguments, minimum_throughput: 1024, **options)
|
41
|
+
super(*arguments, **options)
|
42
42
|
|
43
43
|
@minimum_throughput = minimum_throughput
|
44
44
|
|
data/lib/async/http/endpoint.rb
CHANGED
data/lib/async/http/internet.rb
CHANGED
@@ -56,7 +56,7 @@ module Async
|
|
56
56
|
|
57
57
|
# Server loop.
|
58
58
|
def each(task: Task.current)
|
59
|
-
task.annotate("Reading #{version} requests for #{self.class}.")
|
59
|
+
task.annotate("Reading #{self.version} requests for #{self.class}.")
|
60
60
|
|
61
61
|
while request = next_request
|
62
62
|
response = yield(request, self)
|
@@ -90,11 +90,12 @@ module Async
|
|
90
90
|
body.call(stream)
|
91
91
|
else
|
92
92
|
head = request.head?
|
93
|
+
version = request.version
|
93
94
|
|
94
95
|
request = nil unless body
|
95
96
|
response = nil
|
96
97
|
|
97
|
-
write_body(
|
98
|
+
write_body(version, body, head, trailers)
|
98
99
|
end
|
99
100
|
else
|
100
101
|
# If the request failed to generate a response, it was an internal server error:
|
data/lib/async/http/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: async-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.52.
|
4
|
+
version: 0.52.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-05-
|
11
|
+
date: 2020-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -219,6 +219,8 @@ files:
|
|
219
219
|
- examples/fetch/public/index.html
|
220
220
|
- examples/fetch/public/stream.js
|
221
221
|
- examples/google/search.rb
|
222
|
+
- examples/licenses/gemspect.rb
|
223
|
+
- examples/licenses/list.rb
|
222
224
|
- examples/request.rb
|
223
225
|
- examples/stream/stop.rb
|
224
226
|
- examples/trenni/Gemfile
|