pax_global_header 0000666 0000000 0000000 00000000064 14365153164 0014522 g ustar 00root root 0000000 0000000 52 comment=e26d685db121dd6b9e1e5e9f600512ab7d7f3b71 ruby-async-http-0.59.5/ 0000775 0000000 0000000 00000000000 14365153164 0014673 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/.editorconfig 0000664 0000000 0000000 00000000064 14365153164 0017350 0 ustar 00root root 0000000 0000000 root = true [*] indent_style = tab indent_size = 2 ruby-async-http-0.59.5/.github/ 0000775 0000000 0000000 00000000000 14365153164 0016233 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/.github/workflows/ 0000775 0000000 0000000 00000000000 14365153164 0020270 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/.github/workflows/documentation.yaml 0000664 0000000 0000000 00000001413 14365153164 0024024 0 ustar 00root root 0000000 0000000 name: Documentation permissions: contents: write on: push: branches: - main permissions: contents: write env: CONSOLE_OUTPUT: XTerm BUNDLE_WITH: maintenance jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: "3.1" bundler-cache: true - name: Installing packages run: sudo apt-get install wget - name: Prepare GitHub Pages run: bundle exec bake github:pages:prepare --directory docs - name: Generate documentation timeout-minutes: 5 run: bundle exec bake utopia:project:static --force no - name: Deploy GitHub Pages run: bundle exec bake github:pages:commit --directory docs ruby-async-http-0.59.5/.github/workflows/test-async-head.yaml 0000664 0000000 0000000 00000001040 14365153164 0024140 0 ustar 00root root 0000000 0000000 name: Test Async HEAD on: [push, pull_request] permissions: contents: read env: CONSOLE_OUTPUT: XTerm BUNDLE_GEMFILE: gems/async-head.rb jobs: test: runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu ruby: - head steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 10 run: bundle exec bake test ruby-async-http-0.59.5/.github/workflows/test-async-v1.yaml 0000664 0000000 0000000 00000001033 14365153164 0023567 0 ustar 00root root 0000000 0000000 name: Test Async v1 on: [push, pull_request] permissions: contents: read env: CONSOLE_OUTPUT: XTerm BUNDLE_GEMFILE: gems/async-v1.rb jobs: test: runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu ruby: - 2.7 steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 10 run: bundle exec bake test ruby-async-http-0.59.5/.github/workflows/test-external.yaml 0000664 0000000 0000000 00000001146 14365153164 0023755 0 ustar 00root root 0000000 0000000 name: Test External on: [push, pull_request] permissions: contents: read env: CONSOLE_OUTPUT: XTerm jobs: test: name: ${{matrix.ruby}} on ${{matrix.os}} runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu - macos ruby: - "2.7" - "3.0" - "3.1" steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 10 run: bundle exec bake test:external ruby-async-http-0.59.5/.github/workflows/test.yaml 0000664 0000000 0000000 00000002054 14365153164 0022134 0 ustar 00root root 0000000 0000000 name: Test on: [push, pull_request] permissions: contents: read env: CONSOLE_OUTPUT: XTerm jobs: test: name: ${{matrix.ruby}} on ${{matrix.os}} runs-on: ${{matrix.os}}-latest continue-on-error: ${{matrix.experimental}} strategy: matrix: os: - ubuntu - macos ruby: - "2.7" - "3.0" - "3.1" experimental: [false] include: - os: ubuntu ruby: truffleruby experimental: true - os: ubuntu ruby: jruby experimental: true - os: ubuntu ruby: head experimental: true steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Installing packages (ubuntu) if: matrix.os == 'ubuntu' run: sudo apt-get install apache2-utils - name: Run tests timeout-minutes: 10 run: bundle exec bake test ruby-async-http-0.59.5/.gitignore 0000664 0000000 0000000 00000000200 14365153164 0016653 0 ustar 00root root 0000000 0000000 .tags /.bundle/ /.yardoc /gems.locked /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ .rspec_status .covered.db /h2spec ruby-async-http-0.59.5/.rspec 0000664 0000000 0000000 00000000067 14365153164 0016013 0 ustar 00root root 0000000 0000000 --format documentation --warnings --require spec_helper ruby-async-http-0.59.5/async-http.gemspec 0000664 0000000 0000000 00000002603 14365153164 0020333 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true require_relative "lib/async/http/version" Gem::Specification.new do |spec| spec.name = "async-http" spec.version = Async::HTTP::VERSION spec.summary = "A HTTP client and server library." spec.authors = ["Samuel Williams", "Brian Morearty", "Bruno Sutic", "Janko Marohnić", "Adam Daniels", "Cyril Roelandt", "Denis Talakevich", "Ian Ker-Seymer", "Igor Sidorov", "Marco Concetto Rudilosso", "Olle Jonsson", "Orgad Shaneh", "Stefan Wrobel", "TheAthlete", "Trevor Turk", "samshadwell"] spec.license = "MIT" spec.cert_chain = ['release.cert'] spec.signing_key = File.expand_path('~/.gem/release.pem') spec.homepage = "https://github.com/socketry/async-http" spec.files = Dir.glob('{bake,lib}/**/*', File::FNM_DOTMATCH, base: __dir__) spec.add_dependency "async", ">= 1.25" spec.add_dependency "async-io", ">= 1.28" spec.add_dependency "async-pool", ">= 0.2" spec.add_dependency "protocol-http", "~> 0.23" spec.add_dependency "protocol-http1", "~> 0.14.0" spec.add_dependency "protocol-http2", "~> 0.14.0" spec.add_dependency "traces", ">= 0.8.0" spec.add_development_dependency "async-container", "~> 0.14" spec.add_development_dependency "async-rspec", "~> 1.10" spec.add_development_dependency "covered" spec.add_development_dependency "localhost" spec.add_development_dependency "rack-test" spec.add_development_dependency "rspec", "~> 3.6" end ruby-async-http-0.59.5/bake/ 0000775 0000000 0000000 00000000000 14365153164 0015575 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/bake/async/ 0000775 0000000 0000000 00000000000 14365153164 0016712 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/bake/async/http.rb 0000664 0000000 0000000 00000004105 14365153164 0020216 0 ustar 00root root 0000000 0000000 # Fetch the specified URL and print the response. # @param url [String] the URL to parse and fetch. # @param method [String] the HTTP method to use. def fetch(url, method:) require 'async/http/internet' require 'kernel/sync' terminal = Console::Terminal.for($stdout) terminal[:request] = terminal.style(:blue, nil, :bold) terminal[:response] = terminal.style(:green, nil, :bold) terminal[:length] = terminal.style(nil, nil, :bold) terminal[:key] = terminal.style(nil, nil, :bold) terminal[:chunk_0] = terminal.style(:blue) terminal[:chunk_1] = terminal.style(:cyan) align = 20 format_body = proc do |body, terminal| if body if length = body.length terminal.print(:body, "body with length ", :length, length, "B") else terminal.print(:body, "body without length") end else terminal.print(:body, "no body") end end.curry Sync do internet = Async::HTTP::Internet.new response = internet.send(method.downcase.to_sym, url) terminal.print_line( :request, method.rjust(align), :reset, ": ", url ) terminal.print_line( :response, "version".rjust(align), :reset, ": ", response.version ) terminal.print_line( :response, "status".rjust(align), :reset, ": ", response.status, ) terminal.print_line( :response, "body".rjust(align), :reset, ": ", format_body[response.body], ) response.headers.each do |key, value| terminal.print_line( :key, key.rjust(align), :reset, ": ", :value, value.inspect ) end if body = response.body index = 0 style = [:chunk_0, :chunk_1] response.body.each do |chunk| terminal.print(style[index % 2], chunk) index += 1 end end response.finish if trailer = response.headers.trailer trailer.each do |key, value| terminal.print_line( :key, key.rjust(align), :reset, ": ", :value, value.inspect ) end end internet.close end end # GET the specified URL and print the response. def get(url) self.fetch(url, method: "GET") end # HEAD the specified URL and print the response. def head(url) self.fetch(url, method: "HEAD") end ruby-async-http-0.59.5/bake/async/http/ 0000775 0000000 0000000 00000000000 14365153164 0017671 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/bake/async/http/h2spec.rb 0000664 0000000 0000000 00000001623 14365153164 0021404 0 ustar 00root root 0000000 0000000 def build # Fetch the code: system "go get github.com/spf13/cobra" system "go get github.com/summerwind/h2spec" # This builds `h2spec` into the current directory system "go build ~/go/src/github.com/summerwind/h2spec/cmd/h2spec/h2spec.go" end def test server do system("./h2spec", "-p", "7272") end end private def server require 'async' require 'async/container' require 'async/http/server' require 'async/io/host_endpoint' endpoint = Async::IO::Endpoint.tcp('127.0.0.1', 7272) container = Async::Container.new Console.logger.info(self){"Starting server..."} container.run(count: 1) do server = Async::HTTP::Server.for(endpoint, protocol: Async::HTTP::Protocol::HTTP2, scheme: "https") do |request| Protocol::HTTP::Response[200, {'content-type' => 'text/plain'}, ["Hello World"]] end Async do server.run end end yield if block_given? ensure container&.stop end ruby-async-http-0.59.5/config/ 0000775 0000000 0000000 00000000000 14365153164 0016140 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/config/external.yaml 0000664 0000000 0000000 00000000751 14365153164 0020651 0 ustar 00root root 0000000 0000000 falcon: url: https://github.com/socketry/falcon.git command: bundle exec rspec async-rest: url: https://github.com/socketry/async-rest.git command: bundle exec rspec async-websocket: url: https://github.com/socketry/async-websocket.git command: bundle exec sus async-http-faraday: url: https://github.com/socketry/async-http-faraday.git command: bundle exec rspec # async-http-cache: # url: https://github.com/socketry/async-http-cache.git # command: bundle exec rspec ruby-async-http-0.59.5/examples/ 0000775 0000000 0000000 00000000000 14365153164 0016511 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/examples/compare/ 0000775 0000000 0000000 00000000000 14365153164 0020137 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/examples/compare/benchmark.rb 0000775 0000000 0000000 00000002330 14365153164 0022417 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby require 'benchmark' require 'httpx' require 'async' require 'async/barrier' require 'async/semaphore' require 'async/http/internet' URL = "https://www.codeotaku.com/index" REPEATS = 10 Benchmark.bmbm do |x| x.report("async-http") do Async do internet = Async::HTTP::Internet.new i = 0 while i < REPEATS response = internet.get(URL) response.read i += 1 end ensure internet&.close end end x.report("async-http (pipelined)") do Async do |task| internet = Async::HTTP::Internet.new semaphore = Async::Semaphore.new(100, parent: task) barrier = Async::Barrier.new(parent: semaphore) # Warm up the connection pool... response = internet.get(URL) response.read i = 0 while i < REPEATS barrier.async do response = internet.get(URL) response.read end i += 1 end barrier.wait ensure internet&.close end end x.report("httpx") do i = 0 while i < REPEATS response = HTTPX.get(URL) response.read i += 1 end end x.report("httpx (pipelined)") do urls = [URL] * REPEATS responses = HTTPX.get(*urls) responses.each do |response| response.read end end end ruby-async-http-0.59.5/examples/compare/gems.rb 0000664 0000000 0000000 00000000137 14365153164 0021420 0 ustar 00root root 0000000 0000000 source "https://rubygems.org" gem "benchmark-ips" gem "async" gem "async-http" gem "httpx" ruby-async-http-0.59.5/examples/download/ 0000775 0000000 0000000 00000000000 14365153164 0020320 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/examples/download/chunked.rb 0000775 0000000 0000000 00000004155 14365153164 0022276 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby require 'async' require 'async/clock' require 'async/barrier' require 'async/semaphore' require_relative '../../lib/async/http/endpoint' require_relative '../../lib/async/http/client' Async do url = "https://static.openfoodfacts.org/data/en.openfoodfacts.org.products.csv" endpoint = Async::HTTP::Endpoint.parse(url) client = Async::HTTP::Client.new(endpoint) headers = {'user-agent' => 'curl/7.69.1', 'accept' => '*/*'} file = File.open("products.csv", "w") Console.logger.info(self) {"Saving download to #{Dir.pwd}"} begin response = client.head(endpoint.path, headers) content_length = nil if response.success? unless response.headers['accept-ranges'].include?('bytes') raise "Does not advertise support for accept-ranges: bytes!" end unless content_length = response.body&.length raise "Could not determine length of response!" end end ensure response&.close end Console.logger.info(self) {"Content length: #{content_length/(1024**2)}MiB"} parts = [] offset = 0 chunk_size = 1024*1024 start_time = Async::Clock.now amount = 0 while offset < content_length byte_range_start = offset byte_range_end = [offset + chunk_size, content_length].min parts << (byte_range_start...byte_range_end) offset += chunk_size end Console.logger.info(self) {"Breaking download into #{parts.size} parts..."} semaphore = Async::Semaphore.new(8) barrier = Async::Barrier.new(parent: semaphore) while !parts.empty? barrier.async do part = parts.shift Console.logger.info(self) {"Issuing range request range: bytes=#{part.min}-#{part.max}"} response = client.get(endpoint.path, [ ["range", "bytes=#{part.min}-#{part.max-1}"], *headers ]) if response.success? Console.logger.info(self) {"Got response: #{response}... writing data for #{part}."} written = file.pwrite(response.read, part.min) amount += written duration = Async::Clock.now - start_time Console.logger.info(self) {"Rate: #{((amount.to_f/(1024**2))/duration).round(2)}MiB/s"} end end end barrier.wait ensure client&.close end ruby-async-http-0.59.5/examples/fetch/ 0000775 0000000 0000000 00000000000 14365153164 0017602 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/examples/fetch/README.md 0000664 0000000 0000000 00000000125 14365153164 0021057 0 ustar 00root root 0000000 0000000 # Fetch This was an experiment to see how browsers handle bi-directional streaming. ruby-async-http-0.59.5/examples/fetch/config.ru 0000664 0000000 0000000 00000000666 14365153164 0021427 0 ustar 00root root 0000000 0000000 require 'rack' class Echo def initialize(app) @app = app end def call(env) request = Rack::Request.new(env) if request.path_info == "/echo" if output = request.body return [200, {}, output.body] else return [200, {}, ["Hello World?"]] end else return @app.call(env) end end end use Echo use Rack::Static, :urls => [''], :root => 'public', :index => 'index.html' run lambda{|env| [404, {}, []]} ruby-async-http-0.59.5/examples/fetch/gems.rb 0000664 0000000 0000000 00000000031 14365153164 0021054 0 ustar 00root root 0000000 0000000 gem 'rack' gem 'falcon' ruby-async-http-0.59.5/examples/fetch/public/ 0000775 0000000 0000000 00000000000 14365153164 0021060 5 ustar 00root root 0000000 0000000 ruby-async-http-0.59.5/examples/fetch/public/index.html 0000664 0000000 0000000 00000000455 14365153164 0023061 0 ustar 00root root 0000000 0000000