From 7bb83707925bd0cd1cde9efa18e1e9e4759e752a Mon Sep 17 00:00:00 2001 From: Jeff Cantrill Date: Wed, 21 Oct 2020 09:51:00 -0400 Subject: [PATCH] Bug 1886856: Add typhoeus for keep-alives in elasticsearch plugin --- fluentd/Gemfile | 2 + fluentd/Gemfile.lock | 6 + fluentd/rh-manifest.txt | 2 + fluentd/vendored_gem_src/ethon/.rspec | 3 + fluentd/vendored_gem_src/ethon/.travis.yml | 30 + fluentd/vendored_gem_src/ethon/CHANGELOG.md | 365 +++++++++++ fluentd/vendored_gem_src/ethon/Gemfile | 38 ++ fluentd/vendored_gem_src/ethon/Guardfile | 9 + fluentd/vendored_gem_src/ethon/LICENSE | 20 + fluentd/vendored_gem_src/ethon/README.md | 95 +++ fluentd/vendored_gem_src/ethon/Rakefile | 39 ++ fluentd/vendored_gem_src/ethon/ethon.gemspec | 25 + fluentd/vendored_gem_src/ethon/lib/ethon.rb | 35 ++ .../vendored_gem_src/ethon/lib/ethon/curl.rb | 89 +++ .../ethon/lib/ethon/curls/classes.rb | 54 ++ .../ethon/lib/ethon/curls/codes.rb | 122 ++++ .../ethon/lib/ethon/curls/constants.rb | 62 ++ .../ethon/lib/ethon/curls/form_options.rb | 36 ++ .../ethon/lib/ethon/curls/functions.rb | 66 ++ .../ethon/lib/ethon/curls/infos.rb | 150 +++++ .../ethon/lib/ethon/curls/messages.rb | 18 + .../ethon/lib/ethon/curls/options.rb | 468 ++++++++++++++ .../ethon/lib/ethon/curls/settings.rb | 9 + .../vendored_gem_src/ethon/lib/ethon/easy.rb | 315 ++++++++++ .../ethon/lib/ethon/easy/callbacks.rb | 147 +++++ .../ethon/lib/ethon/easy/debug_info.rb | 46 ++ .../ethon/lib/ethon/easy/features.rb | 30 + .../ethon/lib/ethon/easy/form.rb | 106 ++++ .../ethon/lib/ethon/easy/header.rb | 60 ++ .../ethon/lib/ethon/easy/http.rb | 67 ++ .../ethon/lib/ethon/easy/http/actionable.rb | 156 +++++ .../ethon/lib/ethon/easy/http/custom.rb | 28 + .../ethon/lib/ethon/easy/http/delete.rb | 24 + .../ethon/lib/ethon/easy/http/get.rb | 23 + .../ethon/lib/ethon/easy/http/head.rb | 23 + .../ethon/lib/ethon/easy/http/options.rb | 23 + .../ethon/lib/ethon/easy/http/patch.rb | 23 + .../ethon/lib/ethon/easy/http/post.rb | 25 + .../ethon/lib/ethon/easy/http/postable.rb | 31 + .../ethon/lib/ethon/easy/http/put.rb | 26 + .../ethon/lib/ethon/easy/http/putable.rb | 24 + .../ethon/lib/ethon/easy/informations.rb | 94 +++ .../ethon/lib/ethon/easy/mirror.rb | 35 ++ .../ethon/lib/ethon/easy/operations.rb | 63 ++ .../ethon/lib/ethon/easy/options.rb | 49 ++ .../ethon/lib/ethon/easy/params.rb | 28 + .../ethon/lib/ethon/easy/queryable.rb | 153 +++++ .../lib/ethon/easy/response_callbacks.rb | 130 ++++ .../ethon/lib/ethon/easy/util.rb | 27 + .../ethon/lib/ethon/errors.rb | 16 + .../ethon/lib/ethon/errors/ethon_error.rb | 8 + .../ethon/lib/ethon/errors/global_init.rb | 12 + .../ethon/lib/ethon/errors/invalid_option.rb | 12 + .../ethon/lib/ethon/errors/invalid_value.rb | 12 + .../ethon/lib/ethon/errors/multi_add.rb | 11 + .../ethon/lib/ethon/errors/multi_fdset.rb | 11 + .../ethon/lib/ethon/errors/multi_remove.rb | 11 + .../ethon/lib/ethon/errors/multi_timeout.rb | 12 + .../ethon/lib/ethon/errors/select.rb | 12 + .../vendored_gem_src/ethon/lib/ethon/libc.rb | 20 + .../ethon/lib/ethon/loggable.rb | 58 ++ .../vendored_gem_src/ethon/lib/ethon/multi.rb | 103 +++ .../ethon/lib/ethon/multi/operations.rb | 190 ++++++ .../ethon/lib/ethon/multi/options.rb | 116 ++++ .../ethon/lib/ethon/multi/stack.rb | 48 ++ .../ethon/lib/ethon/version.rb | 5 + .../ethon/profile/benchmarks.rb | 103 +++ .../ethon/profile/memory_leaks.rb | 113 ++++ .../ethon/profile/perf_spec_helper.rb | 36 ++ .../profile/support/memory_test_helpers.rb | 75 +++ .../profile/support/os_memory_leak_tracker.rb | 47 ++ .../support/ruby_object_leak_tracker.rb | 48 ++ .../ethon/spec/ethon/curl_spec.rb | 37 ++ .../ethon/spec/ethon/easy/callbacks_spec.rb | 58 ++ .../ethon/spec/ethon/easy/debug_info_spec.rb | 53 ++ .../ethon/spec/ethon/easy/features_spec.rb | 23 + .../ethon/spec/ethon/easy/form_spec.rb | 103 +++ .../ethon/spec/ethon/easy/header_spec.rb | 78 +++ .../ethon/spec/ethon/easy/http/custom_spec.rb | 176 ++++++ .../ethon/spec/ethon/easy/http/delete_spec.rb | 20 + .../ethon/spec/ethon/easy/http/get_spec.rb | 125 ++++ .../ethon/spec/ethon/easy/http/head_spec.rb | 79 +++ .../spec/ethon/easy/http/options_spec.rb | 50 ++ .../ethon/spec/ethon/easy/http/patch_spec.rb | 50 ++ .../ethon/spec/ethon/easy/http/post_spec.rb | 316 ++++++++++ .../ethon/spec/ethon/easy/http/put_spec.rb | 167 +++++ .../ethon/spec/ethon/easy/http_spec.rb | 63 ++ .../spec/ethon/easy/informations_spec.rb | 97 +++ .../ethon/spec/ethon/easy/mirror_spec.rb | 45 ++ .../ethon/spec/ethon/easy/operations_spec.rb | 267 ++++++++ .../ethon/spec/ethon/easy/options_spec.rb | 192 ++++++ .../ethon/spec/ethon/easy/queryable_spec.rb | 234 +++++++ .../ethon/easy/response_callbacks_spec.rb | 151 +++++ .../ethon/spec/ethon/easy/util_spec.rb | 27 + .../ethon/spec/ethon/easy_spec.rb | 202 ++++++ .../ethon/spec/ethon/libc_spec.rb | 13 + .../ethon/spec/ethon/loggable_spec.rb | 21 + .../ethon/spec/ethon/multi/operations_spec.rb | 297 +++++++++ .../ethon/spec/ethon/multi/options_spec.rb | 68 ++ .../ethon/spec/ethon/multi/stack_spec.rb | 79 +++ .../ethon/spec/ethon/multi_spec.rb | 21 + .../ethon/spec/spec_helper.rb | 27 + .../ethon/spec/support/localhost_server.rb | 94 +++ .../ethon/spec/support/server.rb | 114 ++++ .../vendored_gem_src/syslog_protocol/Gemfile | 2 + .../syslog_protocol/README.md | 84 +++ .../vendored_gem_src/syslog_protocol/Rakefile | 150 +++++ .../syslog_protocol/lib/syslog_protocol.rb | 8 + .../lib/syslog_protocol/common.rb | 79 +++ .../lib/syslog_protocol/logger.rb | 21 + .../lib/syslog_protocol/packet.rb | 135 ++++ .../lib/syslog_protocol/parser.rb | 57 ++ .../syslog_protocol/syslog_protocol.gemspec | 81 +++ .../syslog_protocol/test/helper.rb | 13 + .../syslog_protocol/test/test_logger.rb | 28 + .../syslog_protocol/test/test_packet.rb | 96 +++ .../syslog_protocol/test/test_parser.rb | 51 ++ fluentd/vendored_gem_src/typhoeus/.rspec | 4 + fluentd/vendored_gem_src/typhoeus/.travis.yml | 26 + .../vendored_gem_src/typhoeus/CHANGELOG.md | 406 ++++++++++++ .../vendored_gem_src/typhoeus/CONTRIBUTING.md | 20 + fluentd/vendored_gem_src/typhoeus/Gemfile | 32 + fluentd/vendored_gem_src/typhoeus/Guardfile | 9 + fluentd/vendored_gem_src/typhoeus/LICENSE | 22 + fluentd/vendored_gem_src/typhoeus/README.md | 584 ++++++++++++++++++ fluentd/vendored_gem_src/typhoeus/Rakefile | 38 ++ fluentd/vendored_gem_src/typhoeus/UPGRADE.md | 55 ++ .../typhoeus/lib/rack/typhoeus.rb | 1 + .../typhoeus/middleware/params_decoder.rb | 57 ++ .../middleware/params_decoder/helper.rb | 76 +++ .../vendored_gem_src/typhoeus/lib/typhoeus.rb | 143 +++++ .../typhoeus/lib/typhoeus/adapters/faraday.rb | 180 ++++++ .../typhoeus/lib/typhoeus/cache/dalli.rb | 28 + .../typhoeus/lib/typhoeus/cache/rails.rb | 28 + .../typhoeus/lib/typhoeus/cache/redis.rb | 35 ++ .../typhoeus/lib/typhoeus/config.rb | 69 +++ .../typhoeus/lib/typhoeus/easy_factory.rb | 180 ++++++ .../typhoeus/lib/typhoeus/errors.rb | 9 + .../typhoeus/lib/typhoeus/errors/no_stub.rb | 12 + .../lib/typhoeus/errors/typhoeus_error.rb | 8 + .../typhoeus/lib/typhoeus/expectation.rb | 217 +++++++ .../typhoeus/lib/typhoeus/hydra.rb | 95 +++ .../typhoeus/lib/typhoeus/hydra/addable.rb | 23 + .../typhoeus/lib/typhoeus/hydra/before.rb | 31 + .../lib/typhoeus/hydra/block_connection.rb | 35 ++ .../typhoeus/lib/typhoeus/hydra/cacheable.rb | 15 + .../typhoeus/lib/typhoeus/hydra/memoizable.rb | 56 ++ .../typhoeus/lib/typhoeus/hydra/queueable.rb | 83 +++ .../typhoeus/lib/typhoeus/hydra/runnable.rb | 19 + .../typhoeus/lib/typhoeus/hydra/stubbable.rb | 28 + .../typhoeus/lib/typhoeus/pool.rb | 70 +++ .../typhoeus/lib/typhoeus/railtie.rb | 12 + .../typhoeus/lib/typhoeus/request.rb | 221 +++++++ .../typhoeus/lib/typhoeus/request/actions.rb | 125 ++++ .../typhoeus/lib/typhoeus/request/before.rb | 30 + .../lib/typhoeus/request/block_connection.rb | 52 ++ .../lib/typhoeus/request/cacheable.rb | 38 ++ .../lib/typhoeus/request/callbacks.rb | 151 +++++ .../typhoeus/lib/typhoeus/request/marshal.rb | 22 + .../lib/typhoeus/request/memoizable.rb | 38 ++ .../lib/typhoeus/request/operations.rb | 40 ++ .../lib/typhoeus/request/responseable.rb | 29 + .../lib/typhoeus/request/streamable.rb | 34 + .../lib/typhoeus/request/stubbable.rb | 30 + .../typhoeus/lib/typhoeus/response.rb | 68 ++ .../lib/typhoeus/response/cacheable.rb | 14 + .../typhoeus/lib/typhoeus/response/header.rb | 105 ++++ .../lib/typhoeus/response/informations.rb | 248 ++++++++ .../typhoeus/lib/typhoeus/response/status.rb | 106 ++++ .../typhoeus/lib/typhoeus/version.rb | 5 + .../vendored_gem_src/typhoeus/perf/profile.rb | 14 + .../typhoeus/perf/vs_nethttp.rb | 64 ++ .../middleware/params_decoder/helper_spec.rb | 156 +++++ .../middleware/params_decoder_spec.rb | 31 + .../typhoeus/spec/spec_helper.rb | 29 + .../typhoeus/spec/support/localhost_server.rb | 94 +++ .../typhoeus/spec/support/memory_cache.rb | 15 + .../typhoeus/spec/support/server.rb | 116 ++++ .../spec/typhoeus/adapters/faraday_spec.rb | 339 ++++++++++ .../spec/typhoeus/cache/dalli_spec.rb | 41 ++ .../spec/typhoeus/cache/redis_spec.rb | 41 ++ .../typhoeus/spec/typhoeus/config_spec.rb | 15 + .../spec/typhoeus/easy_factory_spec.rb | 143 +++++ .../spec/typhoeus/errors/no_stub_spec.rb | 13 + .../spec/typhoeus/expectation_spec.rb | 280 +++++++++ .../spec/typhoeus/hydra/addable_spec.rb | 22 + .../spec/typhoeus/hydra/before_spec.rb | 98 +++ .../typhoeus/hydra/block_connection_spec.rb | 18 + .../spec/typhoeus/hydra/cacheable_spec.rb | 88 +++ .../spec/typhoeus/hydra/memoizable_spec.rb | 53 ++ .../spec/typhoeus/hydra/queueable_spec.rb | 98 +++ .../spec/typhoeus/hydra/runnable_spec.rb | 137 ++++ .../spec/typhoeus/hydra/stubbable_spec.rb | 48 ++ .../typhoeus/spec/typhoeus/hydra_spec.rb | 22 + .../typhoeus/spec/typhoeus/pool_spec.rb | 137 ++++ .../spec/typhoeus/request/actions_spec.rb | 19 + .../spec/typhoeus/request/before_spec.rb | 93 +++ .../typhoeus/request/block_connection_spec.rb | 75 +++ .../spec/typhoeus/request/cacheable_spec.rb | 94 +++ .../spec/typhoeus/request/callbacks_spec.rb | 91 +++ .../spec/typhoeus/request/marshal_spec.rb | 60 ++ .../spec/typhoeus/request/memoizable_spec.rb | 34 + .../spec/typhoeus/request/operations_spec.rb | 101 +++ .../typhoeus/request/responseable_spec.rb | 13 + .../spec/typhoeus/request/stubbable_spec.rb | 45 ++ .../typhoeus/spec/typhoeus/request_spec.rb | 232 +++++++ .../spec/typhoeus/response/header_spec.rb | 147 +++++ .../typhoeus/response/informations_spec.rb | 283 +++++++++ .../spec/typhoeus/response/status_spec.rb | 256 ++++++++ .../typhoeus/spec/typhoeus/response_spec.rb | 100 +++ .../typhoeus/spec/typhoeus_spec.rb | 105 ++++ .../typhoeus/typhoeus.gemspec | 25 + hack/update-fluentd-vendor-gems.sh | 4 +- 213 files changed, 16679 insertions(+), 2 deletions(-) create mode 100644 fluentd/vendored_gem_src/ethon/.rspec create mode 100644 fluentd/vendored_gem_src/ethon/.travis.yml create mode 100644 fluentd/vendored_gem_src/ethon/CHANGELOG.md create mode 100644 fluentd/vendored_gem_src/ethon/Gemfile create mode 100644 fluentd/vendored_gem_src/ethon/Guardfile create mode 100644 fluentd/vendored_gem_src/ethon/LICENSE create mode 100644 fluentd/vendored_gem_src/ethon/README.md create mode 100644 fluentd/vendored_gem_src/ethon/Rakefile create mode 100644 fluentd/vendored_gem_src/ethon/ethon.gemspec create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curl.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/classes.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/codes.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/constants.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/form_options.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/functions.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/infos.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/messages.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/options.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/curls/settings.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/callbacks.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/debug_info.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/features.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/form.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/header.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/actionable.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/custom.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/delete.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/get.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/head.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/options.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/patch.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/post.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/postable.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/put.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/putable.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/informations.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/mirror.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/operations.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/options.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/params.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/queryable.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/response_callbacks.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/easy/util.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/ethon_error.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/global_init.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_option.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_value.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_add.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_fdset.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_remove.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_timeout.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/errors/select.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/libc.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/loggable.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/multi.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/multi/operations.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/multi/options.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/multi/stack.rb create mode 100644 fluentd/vendored_gem_src/ethon/lib/ethon/version.rb create mode 100644 fluentd/vendored_gem_src/ethon/profile/benchmarks.rb create mode 100644 fluentd/vendored_gem_src/ethon/profile/memory_leaks.rb create mode 100644 fluentd/vendored_gem_src/ethon/profile/perf_spec_helper.rb create mode 100644 fluentd/vendored_gem_src/ethon/profile/support/memory_test_helpers.rb create mode 100644 fluentd/vendored_gem_src/ethon/profile/support/os_memory_leak_tracker.rb create mode 100644 fluentd/vendored_gem_src/ethon/profile/support/ruby_object_leak_tracker.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/curl_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/callbacks_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/debug_info_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/features_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/form_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/header_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/custom_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/delete_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/get_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/head_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/options_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/patch_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/post_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/put_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/http_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/informations_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/mirror_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/operations_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/options_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/queryable_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/response_callbacks_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy/util_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/easy_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/libc_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/loggable_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/multi/operations_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/multi/options_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/multi/stack_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/ethon/multi_spec.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/spec_helper.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/support/localhost_server.rb create mode 100644 fluentd/vendored_gem_src/ethon/spec/support/server.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/Gemfile create mode 100644 fluentd/vendored_gem_src/syslog_protocol/README.md create mode 100644 fluentd/vendored_gem_src/syslog_protocol/Rakefile create mode 100644 fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/common.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/logger.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/packet.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/parser.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/syslog_protocol.gemspec create mode 100644 fluentd/vendored_gem_src/syslog_protocol/test/helper.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/test/test_logger.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/test/test_packet.rb create mode 100644 fluentd/vendored_gem_src/syslog_protocol/test/test_parser.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/.rspec create mode 100644 fluentd/vendored_gem_src/typhoeus/.travis.yml create mode 100644 fluentd/vendored_gem_src/typhoeus/CHANGELOG.md create mode 100644 fluentd/vendored_gem_src/typhoeus/CONTRIBUTING.md create mode 100644 fluentd/vendored_gem_src/typhoeus/Gemfile create mode 100644 fluentd/vendored_gem_src/typhoeus/Guardfile create mode 100644 fluentd/vendored_gem_src/typhoeus/LICENSE create mode 100644 fluentd/vendored_gem_src/typhoeus/README.md create mode 100644 fluentd/vendored_gem_src/typhoeus/Rakefile create mode 100644 fluentd/vendored_gem_src/typhoeus/UPGRADE.md create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder/helper.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/adapters/faraday.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/dalli.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/rails.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/redis.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/config.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/easy_factory.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/no_stub.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/typhoeus_error.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/expectation.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/addable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/before.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/block_connection.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/cacheable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/memoizable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/queueable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/runnable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/stubbable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/pool.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/railtie.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/actions.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/before.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/block_connection.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/cacheable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/callbacks.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/marshal.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/memoizable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/operations.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/responseable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/streamable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/stubbable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/cacheable.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/header.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/informations.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/status.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/lib/typhoeus/version.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/perf/profile.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/perf/vs_nethttp.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/spec_helper.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/support/localhost_server.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/support/memory_cache.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/support/server.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/adapters/faraday_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/dalli_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/redis_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/config_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/easy_factory_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/errors/no_stub_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/expectation_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/addable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/before_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/block_connection_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/cacheable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/memoizable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/queueable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/runnable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/stubbable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/pool_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/actions_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/before_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/block_connection_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/cacheable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/callbacks_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/marshal_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/memoizable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/operations_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/responseable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/stubbable_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/header_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/informations_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/status_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/spec/typhoeus_spec.rb create mode 100644 fluentd/vendored_gem_src/typhoeus/typhoeus.gemspec diff --git a/fluentd/Gemfile b/fluentd/Gemfile index f0fe6c4a8..4e4ec1082 100644 --- a/fluentd/Gemfile +++ b/fluentd/Gemfile @@ -14,9 +14,11 @@ gem 'fluent-plugin-systemd' gem 'fluent-plugin-remote-syslog' gem 'fluent-plugin-prometheus' gem 'fluent-plugin-splunk-hec' +gem 'typhoeus' #Below gem(and two of its dependencies) are moved to O_A_L/fluentd/lib, but its dependencies still exist in O_A_L/fluentd/vendored_gem_src/ #gem 'fluent-plugin-remote_syslog', '1.0.0' gem 'ffi', '1.11.3' gem 'uuidtools', '2.1.5' +gem 'rake' diff --git a/fluentd/Gemfile.lock b/fluentd/Gemfile.lock index 0247d817d..e764c58cc 100644 --- a/fluentd/Gemfile.lock +++ b/fluentd/Gemfile.lock @@ -19,6 +19,8 @@ GEM elasticsearch-transport (7.8.0) faraday (~> 1) multi_json + ethon (0.12.0) + ffi (>= 1.3.0) excon (0.75.0) faraday (1.0.1) multipart-post (>= 1.2, < 3) @@ -129,6 +131,8 @@ GEM systemd-journal (1.3.3) ffi (~> 1.9) to_regexp (0.2.1) + typhoeus (1.4.0) + ethon (>= 0.9.0) tzinfo (2.0.2) concurrent-ruby (~> 1.0) tzinfo-data (1.2020.1) @@ -159,6 +163,8 @@ DEPENDENCIES fluent-plugin-splunk-hec fluent-plugin-systemd fluentd (= 1.7.4)! + rake + typhoeus uuidtools (= 2.1.5) BUNDLED WITH diff --git a/fluentd/rh-manifest.txt b/fluentd/rh-manifest.txt index 0bf3ce675..e4ca7dc92 100644 --- a/fluentd/rh-manifest.txt +++ b/fluentd/rh-manifest.txt @@ -20,6 +20,7 @@ rubygem-domain_name 0.5.20190701 https://github.com/knu/ruby-domain_name rubygem-elasticsearch 7.8.0 https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.x/index.html rubygem-elasticsearch-api 7.8.0 https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.x/index.html rubygem-elasticsearch-transport 7.8.0 https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.x/index.html +rubygem-ethon 0.12.0 https://github.com/typhoeus/ethon rubygem-excon 0.75.0 https://github.com/excon/excon rubygem-faraday 1.0.1 https://lostisland.github.io/faraday rubygem-ffi 1.11.3 https://github.com/ffi/ffi/wiki @@ -53,6 +54,7 @@ rubygem-rest-client 2.1.0 https://github.com/rest-client/rest-client rubygem-sigdump 0.2.4 https://github.com/frsyuki/sigdump rubygem-syslog_protocol 0.9.2 https://github.com/eric/syslog_protocol rubygem-systemd-journal 1.3.3 https://github.com/ledbettj/systemd-journal +rubygem-typhoeus 1.4.0 https://github.com/typhoeus/typhoeus rubygem-tzinfo 2.0.2 https://tzinfo.github.io rubygem-tzinfo-data 1.2020.1 https://tzinfo.github.io rubygem-unf 0.1.4 https://github.com/knu/ruby-unf diff --git a/fluentd/vendored_gem_src/ethon/.rspec b/fluentd/vendored_gem_src/ethon/.rspec new file mode 100644 index 000000000..7d8b8b7fb --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/.rspec @@ -0,0 +1,3 @@ +--tty +--color +--format documentation diff --git a/fluentd/vendored_gem_src/ethon/.travis.yml b/fluentd/vendored_gem_src/ethon/.travis.yml new file mode 100644 index 000000000..576083b1d --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/.travis.yml @@ -0,0 +1,30 @@ +language: ruby +cache: bundler +sudo: false + +bundler_args: --without perf +script: bundle exec rake +before_install: + - gem install bundler + +rvm: + - 1.8.7 + - 1.9.2 + - 1.9.3 + - 2.0.0-p648 + - 2.1.10 + - 2.2.10 + - 2.3.7 + - 2.4.4 + - 2.5.1 + - ruby-head + - ree + - jruby-18mode + - jruby-19mode + - jruby-head + +matrix: + allow_failures: + - rvm: ree + - rvm: ruby-head + - rvm: jruby-head diff --git a/fluentd/vendored_gem_src/ethon/CHANGELOG.md b/fluentd/vendored_gem_src/ethon/CHANGELOG.md new file mode 100644 index 000000000..4edcf28b1 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/CHANGELOG.md @@ -0,0 +1,365 @@ +# Changelog + +## Master + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.12.0...master) + +## 0.12.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.11.0...v0.12.0) + +## 0.11.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.10.1...v0.11.0) + +## 0.10.1 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.10.0...v0.10.1) + +## 0.10.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.9.1...v0.10.0) + +## 0.9.1 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.9.0...v0.9.1) + +## 0.9.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.8.1...v0.9.0) + +## 0.8.1 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.8.0...v0.8.1) + +* Support optional escaping of params. + ([Tasos Laskos](https://github.com/zapotek) +* `Easy::Mirror`: Reduced object allocations and method calls during info handling. + ([Tasos Laskos](https://github.com/zapotek) + +## 0.8.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.3...v0.7.4) + +* `Easy::Mirror`: Reduced object allocations and method calls during info handling. + ([Tasos Laskos](https://github.com/zapotek) + +## 0.7.4 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.3...v0.7.4) + +* Support different array encodings for params. + ([Marcello Barnaba](https://github.com/ifad), [\#104](https://github.com/typhoeus/ethon/pull/104)) +* Programtic access to version infos. + ([Jonas Wagner](https://github.com/jwagner), [\#90](https://github.com/typhoeus/ethon/pull/90)) + + +## 0.7.3 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.2...v0.7.3) + +* `Ethon::Curl::FDSet` + * Set `:fd_array` size to the current MS Windows `FD_SETSIZE` (2048). + ([Tasos Laskos](https://github.com/zapotek) + +* Added `redirect_time` value to available informations and `Easy::Mirror`. + ([Adrien Jarthon](https://github.com/jarthod) + +## 0.7.2 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.1...v0.7.2) + +* FFI data-types updated to be more correct. + +## 0.7.1 + +* MS Windows determination delegated to `Gem.windows?` for better accuracy. +* FFI data-types updated to work on MS Windows. + +## 0.7.0 + +Not backwards compatible changes: + +* `mime-types` are no longer a dependency. The gem will be still used if available to determine the mime type of a file which is uploaded. That means you have to have take care of the gem installation yourself. + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.6.3...v0.7.0) + +## 0.6.3 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.6.2...v0.6.3) + +## 0.6.2 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.6.1...v0.6.2) + +## 0.6.1 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.6.0...v0.6.1) + +The changelog entries are coming soon! + +## 0.6.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.12...v0.6.0) + +The changelog entries are coming soon! + +Bugfixes: + + * URL-encode nullbytes in parameters instead of escaping them to `\\0`. + ([Tasos Laskos](https://github.com/zapotek) + +## 0.5.12 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.11...v0.5.12) + +Enhancements: + +* Performance optimizations. + ([Kyle Oppenheim](https://github.com/koppenheim) and [Richie Vos](https://github.com/richievos), [\#48](https://github.com/typhoeus/ethon/pull/48)) +* Reuse memory pointer. + ([Richie Vos](https://github.com/richievos), [\#49](https://github.com/typhoeus/ethon/pull/49)) + +Bugfixes: + +* Fix windows install. + ([Derik Olsson](https://github.com/derikolsson), [\#47](https://github.com/typhoeus/ethon/pull/47)) +* Handle urls that already contain query params. + ([Turner King](https://github.com/turnerking ), [\#45](https://github.com/typhoeus/ethon/pull/45)) + +## 0.5.11 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.10...v0.5.11) + +Enhancements: + +* Add support for postredirs, unrestricted_auth. +* Add support for cookie, cookiejar, cookiefile. + ([erwanlr](https://github.com/erwanlr), [\#46](https://github.com/typhoeus/ethon/pull/46)) +* Relax ffi requirements. + ([voxik](https://github.com/voxik), [\#40](https://github.com/typhoeus/ethon/pull/40)) +* Various documentation improvements. + ([Craig Little](https://github.com/craiglittle)) + +Bugfixes: + +* Fix the memory leaks. + ([Richie Vos](https://github.com/richievos), [\#45](https://github.com/typhoeus/ethon/pull/45)) + +## 0.5.10 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.9...v0.5.10) + +Enhancements: + +* Allow custom requests. + ([Nathan Sutton](https://github.com/nate), [\#36](https://github.com/typhoeus/ethon/pull/36)) +* Use updated version of FFI. + +Bugfixes: + +* Fix windows install issue. + ([brainsucker](https://github.com/brainsucker), [\#38](https://github.com/typhoeus/ethon/pull/38)) + +## 0.5.9 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.8...v0.5.9) + +Enhancements: + +* Allow to set multiple protocols. + +## 0.5.8 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.7...v0.5.8) + +Enhancements: + +* Add support for protocols and redir_protocols( + [libcurl SASL buffer overflow vulnerability](http://curl.haxx.se/docs/adv_20130206.html)). +* Add max_send_speed_large and max_recv_speed_large([Paul Schuegraf](https://github.com/pschuegr), [\#33](https://github.com/typhoeus/ethon/pull/33)) + +## 0.5.7 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.6...v0.5.7) + +Enhancements: + +* Use new version of ffi. + +## 0.5.6 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.4...v0.5.6) + +Bugfixes: + +* Easy#reset resets on_complete callbacks. + +## 0.5.4 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.3...v0.5.4) + +Enhancements: + +* Use Libc#getdtablesize to get the FDSet size. +* New libcurl option accept_encoding. +* Documentation updates. + +## 0.5.3 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.2...v0.5.3) + +Enhancements: + +* Deprecate Easy#prepare. It is no longer necessary. +* Unroll metaprogramming for easy and multi options. +* More specs. + +Bugfixes: + +* Correct size for FDSets +* Add proxytypes to enums. + +## 0.5.2 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.1...v0.5.2) + +Enhancements: + +* New libcurl option keypasswd. + +Bugfixes: + +* Correct request logging when using multi interface. +* Remove invalid libcurl option sslcertpasswd. + +## 0.5.1 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.5.0...v0.5.1) + +Bugfixes: + +* Mark Curl.select and Curl.easy_perform as blocking so that the GIL is + released by ffi. + +## 0.5.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.4.4...v0.5.0) + +Enhancements: + +* New libcurl option proxyuserpwd +* Rename response_header to response_headers + +Bugfixes: + +* Mark Curl.select and Curl.easy_perform as blocking so that the GIL is + released by ffi. + +## 0.4.4 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.4.3...v0.4.4) + +Enhancements: + +* Prepare multi explicit like easy + +## 0.4.3 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.4.2...v0.4.3) + +Enhancements: + +* Remove deprecated libcurl option put +* More documentation +* New libcurl option connecttimeout_ms and timeout_ms +* Support multi options + +Bugfixes: + +* Handle nil values in query params + +## 0.4.2 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.4.1...v0.4.2) + +Enhancements: + +* New libcurl option forbid_reuse +* Use libcurls escape instead of CGI::escape + +## 0.4.1 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.4.0...v0.4.1) + +Bugfixes: + +* Handle nested hash in an array in params correct + ( [\#201](https://github.com/typhoeus/typhoeus/issues/201) ) + +## 0.4.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.3.0...v0.4.0) + +Enhancements: + +* ruby 1.8.7 compatible +* Ethon.logger +* Deal with string param/body +* More documentation + +Bugfixes: + +* Add multi_cleanup to curl + +## 0.3.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.2.0...v0.3.0) + +Enhancements: + +* New libcurl option proxyport +* Raise invalid value error when providing a wrong key for sslversion or httpauth + +Bugfixes: + +* Libcurl option sslversion is handled correct + +## 0.2.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.1.0...v0.2.0) + +Enhancements: + +* GET requests are using custom requests only when there is a request body +* Easy#on_complete takes multiple callbacks +* raise Errors::GlobalInit when libcurls global_init failed instead of + runtime error +* raise Errors::InvalidOption if option is invalid + +## 0.1.0 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.0.2...v0.1.0) + +Enhancements: + +* Documentation + ( [Alex P](https://github.com/ifesdjeen), [\#13](https://github.com/typhoeus/ethon/issues/13) ) +* New libcurl option dns_cache_timeout + ( [Chris Heald](https://github.com/cheald), [\#192](https://github.com/typhoeus/typhoeus/pull/192) ) + +Bugfixes: + +* Libcurl option ssl_verifyhost takes an integer. +* Add space between header key and value. + +## 0.0.2 + +[Full Changelog](https://github.com/typhoeus/ethon/compare/v0.0.1...v0.0.2) + +Bugfixes: + +* Add libcurl.so.4 to ffi_lib in order to load correct lib on Debian. +* Escape zero bytes. + +## 0.0.1 Initial version diff --git a/fluentd/vendored_gem_src/ethon/Gemfile b/fluentd/vendored_gem_src/ethon/Gemfile new file mode 100644 index 000000000..d73f3ca43 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/Gemfile @@ -0,0 +1,38 @@ +source "https://rubygems.org" +gemspec + +if Gem.ruby_version < Gem::Version.new("1.9.3") + gem "rake", "< 11" +else + gem "rake" +end + +group :development, :test do + gem "rspec", "~> 3.4" + + gem "sinatra" + + if Gem.ruby_version < Gem::Version.new("2.0.0") + gem "json", "< 2" + else + gem "json" + end + + if Gem.ruby_version >= Gem::Version.new("2.0.0") + gem "mime-types", "~> 1.18" + end + + if Gem.ruby_version >= Gem::Version.new("2.2.0") + gem "mustermann" + elsif Gem.ruby_version >= Gem::Version.new("2.1.0") + gem "mustermann", "0.4.0" + elsif Gem.ruby_version >= Gem::Version.new("2.0.0") + gem "mustermann", "0.3.1" + end +end + +group :perf do + gem "benchmark-ips" + gem "patron" + gem "curb" +end diff --git a/fluentd/vendored_gem_src/ethon/Guardfile b/fluentd/vendored_gem_src/ethon/Guardfile new file mode 100644 index 000000000..7466aa3d9 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/Guardfile @@ -0,0 +1,9 @@ +# vim:set filetype=ruby: +guard( + "rspec", + :all_after_pass => false, + :cli => "--fail-fast --tty --format documentation --colour") do + + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |match| "spec/#{match[1]}_spec.rb" } +end diff --git a/fluentd/vendored_gem_src/ethon/LICENSE b/fluentd/vendored_gem_src/ethon/LICENSE new file mode 100644 index 000000000..f064c17b1 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2012-2016 Hans Hasselberg + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/fluentd/vendored_gem_src/ethon/README.md b/fluentd/vendored_gem_src/ethon/README.md new file mode 100644 index 000000000..31383eae5 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/README.md @@ -0,0 +1,95 @@ +[![Gem Version](https://badge.fury.io/rb/ethon.svg)](https://badge.fury.io/rb/ethon) +[![Build Status](https://travis-ci.org/typhoeus/ethon.svg?branch=master)](https://travis-ci.org/typhoeus/ethon) + +# Ethon + +In Greek mythology, Ethon, the son of Typhoeus and Echidna, is a gigantic eagle. So much for the history. +In the modern world, Ethon is a very basic libcurl wrapper using ffi. + +* [Documentation](http://rubydoc.info/github/typhoeus/ethon/frames/Ethon) +* [Website](http://typhoeus.github.com/) +* [Mailing list](http://groups.google.com/group/typhoeus) + +## Installation + +With bundler: + + gem "ethon" + +With rubygems: + + gem install ethon + +## Usage + +Making the first request is simple: + +```ruby +easy = Ethon::Easy.new(url: "www.example.com") +easy.perform +#=> :ok +``` + +You have access to various options, such as following redirects: + +```ruby +easy = Ethon::Easy.new(url: "www.example.com", followlocation: true) +easy.perform +#=> :ok +``` + +Once you're done you can inspect the response code and body: + +```ruby +easy = Ethon::Easy.new(url: "www.example.com", followlocation: true) +easy.perform +easy.response_code +#=> 200 +easy.response_body +#=> " :ok +``` + +```ruby +easy = Ethon::Easy.new +easy.http_request("www.example.com", :post, { params: { a: 1 }, body: { b: 2 } }) +easy.perform +#=> :ok +``` + +This is really handy when making requests since you don't have to care about setting +everything up correctly. + +## LICENSE + +(The MIT License) + +Copyright © 2012-2016 [Hans Hasselberg](http://www.hans.io) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/fluentd/vendored_gem_src/ethon/Rakefile b/fluentd/vendored_gem_src/ethon/Rakefile new file mode 100644 index 000000000..1203f5e9b --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/Rakefile @@ -0,0 +1,39 @@ +require "bundler" +Bundler.setup + +require "rake" +require "rspec/core/rake_task" +$LOAD_PATH.unshift File.expand_path("../lib", __FILE__) +require "ethon/version" + +task :gem => :build +task :build do + system "gem build ethon.gemspec" +end + +task :install => :build do + system "gem install ethon-#{Ethon::VERSION}.gem" +end + +task :release => :build do + system "git tag -a v#{Ethon::VERSION} -m 'Tagging #{Ethon::VERSION}'" + system "git push --tags" + system "gem push ethon-#{Ethon::VERSION}.gem" +end + +RSpec::Core::RakeTask.new(:spec) do |t| + t.verbose = false + t.ruby_opts = "-W -I./spec -rspec_helper" +end + +desc "Start up the test servers" +task :start do + require_relative 'spec/support/boot' + begin + Boot.start_servers(:rake) + rescue Exception + end +end + +task :default => :spec + diff --git a/fluentd/vendored_gem_src/ethon/ethon.gemspec b/fluentd/vendored_gem_src/ethon/ethon.gemspec new file mode 100644 index 000000000..b0a56a46d --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/ethon.gemspec @@ -0,0 +1,25 @@ +# encoding: utf-8 +lib = File.expand_path('../lib/', __FILE__) +$:.unshift lib unless $:.include?(lib) + +require 'ethon/version' + +Gem::Specification.new do |s| + s.name = "ethon" + s.version = Ethon::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["Hans Hasselberg"] + s.email = ["me@hans.io"] + s.homepage = "https://github.com/typhoeus/ethon" + s.summary = "Libcurl wrapper." + s.description = "Very lightweight libcurl wrapper." + + s.required_rubygems_version = ">= 1.3.6" + s.license = 'MIT' + + s.add_dependency('ffi', ['>= 1.3.0']) + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- spec/*`.split("\n") + s.require_path = 'lib' +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon.rb b/fluentd/vendored_gem_src/ethon/lib/ethon.rb new file mode 100644 index 000000000..893bb63bd --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon.rb @@ -0,0 +1,35 @@ +require 'logger' +require 'ffi' +require 'thread' +begin + require 'mime/types/columnar' +rescue LoadError + begin + require 'mime/types' + rescue LoadError + end +end +require 'tempfile' + +require 'ethon/libc' +require 'ethon/curl' +require 'ethon/easy' +require 'ethon/errors' +require 'ethon/loggable' +require 'ethon/multi' +require 'ethon/version' + +# Ethon is a very simple libcurl. +# It provides direct access to libcurl functionality +# as well as some helpers for doing http requests. +# +# Ethon was extracted from Typhoeus. If you want to +# see how others use Ethon look at the Typhoeus code. +# +# @see https://www.github.com/typhoeus/typhoeus Typhoeus +# +# @note Please update to the latest libcurl version in order +# to benefit from all features and bugfixes. +# http://curl.haxx.se/download.html +module Ethon +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curl.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curl.rb new file mode 100644 index 000000000..72656957f --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curl.rb @@ -0,0 +1,89 @@ +require 'ethon/curls/codes' +require 'ethon/curls/options' +require 'ethon/curls/infos' +require 'ethon/curls/form_options' +require 'ethon/curls/messages' +require 'ethon/curls/functions' + +module Ethon + + # FFI Wrapper module for Curl. Holds constants and required initializers. + # + # @api private + module Curl + extend ::FFI::Library + extend Ethon::Curls::Codes + extend Ethon::Curls::Options + extend Ethon::Curls::Infos + extend Ethon::Curls::FormOptions + extend Ethon::Curls::Messages + + # :nodoc: + def self.windows? + Libc.windows? + end + + require 'ethon/curls/constants' + require 'ethon/curls/settings' + require 'ethon/curls/classes' + extend Ethon::Curls::Functions + + @blocking = true + + @@initialized = false + @@curl_mutex = Mutex.new + + class << self + # This function sets up the program environment that libcurl needs. + # Think of it as an extension of the library loader. + # + # This function must be called at least once within a program (a program is all the + # code that shares a memory space) before the program calls any other function in libcurl. + # The environment it sets up is constant for the life of the program and is the same for + # every program, so multiple calls have the same effect as one call. + # + # The flags option is a bit pattern that tells libcurl exactly what features to init, + # as described below. Set the desired bits by ORing the values together. In normal + # operation, you must specify CURL_GLOBAL_ALL. Don't use any other value unless + # you are familiar with it and mean to control internal operations of libcurl. + # + # This function is not thread safe. You must not call it when any other thread in + # the program (i.e. a thread sharing the same memory) is running. This doesn't just + # mean no other thread that is using libcurl. Because curl_global_init() calls + # functions of other libraries that are similarly thread unsafe, it could conflict with + # any other thread that uses these other libraries. + # + # @raise [ Ethon::Errors::GlobalInit ] If Curl.global_init fails. + def init + @@curl_mutex.synchronize { + if not @@initialized + raise Errors::GlobalInit.new if Curl.global_init(GLOBAL_ALL) != 0 + @@initialized = true + Ethon.logger.debug("ETHON: Libcurl initialized") if Ethon.logger + end + } + end + + # This function releases resources acquired by curl_global_init. + # You should call curl_global_cleanup once for each call you make to + # curl_global_init, after you are done using libcurl. + # This function is not thread safe. You must not call it when any other thread in the + # program (i.e. a thread sharing the same memory) is running. This doesn't just + # mean no other thread that is using libcurl. Because curl_global_cleanup calls functions of other + # libraries that are similarly thread unsafe, it could conflict with + # any other thread that uses these other libraries. + # See the description in libcurl of global environment requirements + # for details of how to use this function. + def cleanup + @@curl_mutex.synchronize { + if @@initialized + Curl.global_cleanup() + @@initialized = false + Ethon.logger.debug("ETHON: Libcurl cleanup") if Ethon.logger + end + } + end + + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/classes.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/classes.rb new file mode 100644 index 000000000..da629d608 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/classes.rb @@ -0,0 +1,54 @@ +module Ethon + module Curl + # :nodoc: + class MsgData < ::FFI::Union + layout :whatever, :pointer, :code, :easy_code + end + + # :nodoc: + class Msg < ::FFI::Struct + layout :code, :msg_code, :easy_handle, :pointer, :data, MsgData + end + + class VersionInfoData < ::FFI::Struct + layout :curl_version, :uint8, + :version, :string, + :version_num, :int, + :host, :string, + :features, :int, + :ssl_version, :string, + :ssl_version_num, :long, + :libz_version, :string, + :protocols, :pointer + end + + # :nodoc: + class FDSet < ::FFI::Struct + if Curl.windows? + layout :fd_count, :uint, + # TODO: Make it future proof by dynamically grabbing FD_SETSIZE. + :fd_array, [:uint, 2048] + + def clear; self[:fd_count] = 0; end + else + # FD Set size. + FD_SETSIZE = ::Ethon::Libc.getdtablesize + layout :fds_bits, [:long, FD_SETSIZE / ::FFI::Type::LONG.size] + + # :nodoc: + def clear; super; end + end + end + + # :nodoc: + class Timeval < ::FFI::Struct + if Curl.windows? + layout :sec, :long, + :usec, :long + else + layout :sec, :time_t, + :usec, :suseconds_t + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/codes.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/codes.rb new file mode 100644 index 000000000..a21f536ee --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/codes.rb @@ -0,0 +1,122 @@ +module Ethon + module Curls # :nodoc: + + # This module contains all easy and + # multi return codes. + module Codes + + # Libcurl error codes, refer + # https://github.com/bagder/curl/blob/master/include/curl/curl.h for details + def easy_codes + [ + :ok, + :unsupported_protocol, + :failed_init, + :url_malformat, + :not_built_in, + :couldnt_resolve_proxy, + :couldnt_resolve_host, + :couldnt_connect, + :ftp_weird_server_reply, + :remote_access_denied, + :ftp_accept_failed, + :ftp_weird_pass_reply, + :ftp_accept_timeout, + :ftp_weird_pasv_reply, + :ftp_weird_227_format, + :ftp_cant_get_host, + :obsolete16, + :ftp_couldnt_set_type, + :partial_file, + :ftp_couldnt_retr_file, + :obsolete20, + :quote_error, + :http_returned_error, + :write_error, + :obsolete24, + :upload_failed, + :read_error, + :out_of_memory, + :operation_timedout, + :obsolete29, + :ftp_port_failed, + :ftp_couldnt_use_rest, + :obsolete32, + :range_error, + :http_post_error, + :ssl_connect_error, + :bad_download_resume, + :file_couldnt_read_file, + :ldap_cannot_bind, + :ldap_search_failed, + :obsolete40, + :function_not_found, + :aborted_by_callback, + :bad_function_argument, + :obsolete44, + :interface_failed, + :obsolete46, + :too_many_redirects , + :unknown_option, + :telnet_option_syntax , + :obsolete50, + :peer_failed_verification, + :got_nothing, + :ssl_engine_notfound, + :ssl_engine_setfailed, + :send_error, + :recv_error, + :obsolete57, + :ssl_certproblem, + :ssl_cipher, + :ssl_cacert, + :bad_content_encoding, + :ldap_invalid_url, + :filesize_exceeded, + :use_ssl_failed, + :send_fail_rewind, + :ssl_engine_initfailed, + :login_denied, + :tftp_notfound, + :tftp_perm, + :remote_disk_full, + :tftp_illegal, + :tftp_unknownid, + :remote_file_exists, + :tftp_nosuchuser, + :conv_failed, + :conv_reqd, + :ssl_cacert_badfile, + :remote_file_not_found, + :ssh, + :ssl_shutdown_failed, + :again, + :ssl_crl_badfile, + :ssl_issuer_error, + :ftp_pret_failed, + :rtsp_cseq_error, + :rtsp_session_error, + :ftp_bad_file_list, + :chunk_failed, + :last + ] + end + + # Curl-Multi socket error codes, refer + # https://github.com/bagder/curl/blob/master/include/curl/multi.h for details + def multi_codes + [ + :call_multi_perform, -1, + :ok, + :bad_handle, + :bad_easy_handle, + :out_of_memory, + :internal_error, + :bad_socket, + :unknown_option, + :last + ] + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/constants.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/constants.rb new file mode 100644 index 000000000..02fcb28d0 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/constants.rb @@ -0,0 +1,62 @@ +module Ethon + module Curl + # :nodoc: + VERSION_NOW = 3 + + # Flag. Initialize SSL. + GLOBAL_SSL = 0x01 + # Flag. Initialize win32 socket libraries. + GLOBAL_WIN32 = 0x02 + # Flag. Initialize everything possible. + GLOBAL_ALL = (GLOBAL_SSL | GLOBAL_WIN32) + # Flag. Initialize everything by default. + GLOBAL_DEFAULT = GLOBAL_ALL + + # :nodoc: + EasyCode = enum(:easy_code, easy_codes) + # :nodoc: + MultiCode = enum(:multi_code, multi_codes) + + # :nodoc: + EasyOption = enum(:easy_option, easy_options(:enum).to_a.flatten) + # :nodoc: + MultiOption = enum(:multi_option, multi_options(:enum).to_a.flatten) + + # Used by curl_debug_callback when setting CURLOPT_DEBUGFUNCTION + # https://github.com/bagder/curl/blob/master/include/curl/curl.h#L378 for details + DebugInfoType = enum(:debug_info_type, debug_info_types) + + # :nodoc: + InfoType = enum(info_types.to_a.flatten) + + # Info details, refer + # https://github.com/bagder/curl/blob/master/src/tool_writeout.c#L66 for details + Info = enum(:info, infos.to_a.flatten) + + # Form options, used by FormAdd for temporary storage, refer + # https://github.com/bagder/curl/blob/master/lib/formdata.h#L51 for details + FormOption = enum(:form_option, form_options) + + # :nodoc: + MsgCode = enum(:msg_code, msg_codes) + + VERSION_IPV6 = (1<<0) # IPv6-enabled + VERSION_KERBEROS4 = (1<<1) # kerberos auth is supported + VERSION_SSL = (1<<2) # SSL options are present + VERSION_LIBZ = (1<<3) # libz features are present + VERSION_NTLM = (1<<4) # NTLM auth is supported + VERSION_GSSNEGOTIATE = (1<<5) # Negotiate auth supp + VERSION_DEBUG = (1<<6) # built with debug capabilities + VERSION_ASYNCHDNS = (1<<7) # asynchronous dns resolves + VERSION_SPNEGO = (1<<8) # SPNEGO auth is supported + VERSION_LARGEFILE = (1<<9) # supports files bigger than 2GB + VERSION_IDN = (1<<10) # International Domain Names support + VERSION_SSPI = (1<<11) # SSPI is supported + VERSION_CONV = (1<<12) # character conversions supported + VERSION_CURLDEBUG = (1<<13) # debug memory tracking supported + VERSION_TLSAUTH_SRP = (1<<14) # TLS-SRP auth is supported + VERSION_NTLM_WB = (1<<15) # NTLM delegating to winbind helper + VERSION_HTTP2 = (1<<16) # HTTP2 support built + VERSION_GSSAPI = (1<<17) # GSS-API is supported + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/form_options.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/form_options.rb new file mode 100644 index 000000000..3694dc674 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/form_options.rb @@ -0,0 +1,36 @@ +module Ethon + module Curls + + # This module contains the available options for forms. + module FormOptions + + # Form options, used by FormAdd for temporary storage, refer + # https://github.com/bagder/curl/blob/master/lib/formdata.h#L51 for details + def form_options + [ + :none, + :copyname, + :ptrname, + :namelength, + :copycontents, + :ptrcontents, + :contentslength, + :filecontent, + :array, + :obsolete, + :file, + :buffer, + :bufferptr, + :bufferlength, + :contenttype, + :contentheader, + :filename, + :end, + :obsolete2, + :stream, + :last + ] + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/functions.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/functions.rb new file mode 100644 index 000000000..aca3627ff --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/functions.rb @@ -0,0 +1,66 @@ +module Ethon + module Curls + + # This module contains the functions to be attached in order to work with + # libcurl. + module Functions + + # :nodoc: + def self.extended(base) + base.attach_function :global_init, :curl_global_init, [:long], :int + base.attach_function :global_cleanup, :curl_global_cleanup, [], :void + base.attach_function :free, :curl_free, [:pointer], :void + + base.attach_function :easy_init, :curl_easy_init, [], :pointer + base.attach_function :easy_cleanup, :curl_easy_cleanup, [:pointer], :void + base.attach_function :easy_getinfo, :curl_easy_getinfo, [:pointer, :info, :pointer], :easy_code + base.attach_function :easy_setopt_ffipointer, :curl_easy_setopt, [:pointer, :easy_option, :pointer], :easy_code + base.attach_function :easy_setopt_string, :curl_easy_setopt, [:pointer, :easy_option, :string], :easy_code + base.attach_function :easy_setopt_long, :curl_easy_setopt, [:pointer, :easy_option, :long], :easy_code + base.attach_function :easy_setopt_callback, :curl_easy_setopt, [:pointer, :easy_option, :callback], :easy_code + base.attach_function :easy_setopt_debug_callback, :curl_easy_setopt, [:pointer, :easy_option, :debug_callback], :easy_code + base.attach_function :easy_setopt_progress_callback, :curl_easy_setopt, [:pointer, :easy_option, :progress_callback], :easy_code + base.attach_function :easy_setopt_off_t, :curl_easy_setopt, [:pointer, :easy_option, :int64], :easy_code + base.instance_variable_set(:@blocking, true) + base.attach_function :easy_perform, :curl_easy_perform, [:pointer], :easy_code + base.attach_function :easy_strerror, :curl_easy_strerror, [:easy_code], :string + base.attach_function :easy_escape, :curl_easy_escape, [:pointer, :pointer, :int], :pointer + base.attach_function :easy_reset, :curl_easy_reset, [:pointer], :void + base.attach_function :easy_duphandle, :curl_easy_duphandle, [:pointer], :pointer + + base.attach_function :formadd, :curl_formadd, [:pointer, :pointer, :varargs], :int + base.attach_function :formfree, :curl_formfree, [:pointer], :void + + base.attach_function :multi_init, :curl_multi_init, [], :pointer + base.attach_function :multi_cleanup, :curl_multi_cleanup, [:pointer], :void + base.attach_function :multi_add_handle, :curl_multi_add_handle, [:pointer, :pointer], :multi_code + base.attach_function :multi_remove_handle, :curl_multi_remove_handle, [:pointer, :pointer], :multi_code + base.attach_function :multi_info_read, :curl_multi_info_read, [:pointer, :pointer], Curl::Msg.ptr + base.attach_function :multi_perform, :curl_multi_perform, [:pointer, :pointer], :multi_code + base.attach_function :multi_timeout, :curl_multi_timeout, [:pointer, :pointer], :multi_code + base.attach_function :multi_fdset, :curl_multi_fdset, [:pointer, Curl::FDSet.ptr, Curl::FDSet.ptr, Curl::FDSet.ptr, :pointer], :multi_code + base.attach_function :multi_strerror, :curl_multi_strerror, [:int], :string + base.attach_function :multi_setopt_ffipointer, :curl_multi_setopt, [:pointer, :multi_option, :pointer], :multi_code + base.attach_function :multi_setopt_string, :curl_multi_setopt, [:pointer, :multi_option, :string], :multi_code + base.attach_function :multi_setopt_long, :curl_multi_setopt, [:pointer, :multi_option, :long], :multi_code + base.attach_function :multi_setopt_callback, :curl_multi_setopt, [:pointer, :multi_option, :callback], :multi_code + base.attach_function :multi_setopt_off_t, :curl_multi_setopt, [:pointer, :multi_option, :int64], :multi_code + + base.attach_function :version, :curl_version, [], :string + base.attach_function :version_info, :curl_version_info, [], Curl::VersionInfoData.ptr + + base.attach_function :slist_append, :curl_slist_append, [:pointer, :string], :pointer + base.attach_function :slist_free_all, :curl_slist_free_all, [:pointer], :void + base.instance_variable_set(:@blocking, true) + + if Curl.windows? + base.ffi_lib 'ws2_32' + else + base.ffi_lib ::FFI::Library::LIBC + end + + base.attach_function :select, [:int, Curl::FDSet.ptr, Curl::FDSet.ptr, Curl::FDSet.ptr, Curl::Timeval.ptr], :int + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/infos.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/infos.rb new file mode 100644 index 000000000..993cd7fab --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/infos.rb @@ -0,0 +1,150 @@ +module Ethon + module Curls + + # This module contains logic for the available informations + # on an easy, eg.: connect_time. + module Infos + + # Return info types. + # + # @example Return info types. + # Ethon::Curl.info_types + # + # @return [ Hash ] The info types. + def info_types + { + :string =>0x100000, + :long => 0x200000, + :double =>0x300000, + :slist => 0x400000 + } + end + + # http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTDEBUGFUNCTION + # https://github.com/bagder/curl/blob/master/include/curl/curl.h#L378 + # + # @example Return debug info types. + # Ethon::Curl.debug_info_types + # + # @return [ Hash ] The info types available to curl_debug_callback. + def debug_info_types + [ + :text, 0, + :header_in, + :header_out, + :data_in, + :data_out, + :ssl_data_in, + :ssl_data_out + ] + end + + # Return Info details, refer + # https://github.com/bagder/curl/blob/master/src/tool_writeout.c#L66 for details + # + # @example Return infos. + # Ethon::Curl.infos + # + # @return [ Hash ] The infos. + def infos + { + :effective_url => info_types[:string] + 1, + :response_code => info_types[:long] + 2, + :total_time => info_types[:double] + 3, + :namelookup_time => info_types[:double] + 4, + :connect_time => info_types[:double] + 5, + :pretransfer_time => info_types[:double] + 6, + :size_upload => info_types[:double] + 7, + :size_download => info_types[:double] + 8, + :speed_download => info_types[:double] + 9, + :speed_upload => info_types[:double] + 10, + :header_size => info_types[:long] + 11, + :request_size => info_types[:long] + 12, + :ssl_verifyresult => info_types[:long] + 13, + :filetime => info_types[:long] + 14, + :content_length_download =>info_types[:double] + 15, + :content_length_upload => info_types[:double] + 16, + :starttransfer_time => info_types[:double] + 17, + :content_type => info_types[:string] + 18, + :redirect_time => info_types[:double] + 19, + :redirect_count => info_types[:long] + 20, + :private => info_types[:string] + 21, + :http_connectcode => info_types[:long] + 22, + :httpauth_avail => info_types[:long] + 23, + :proxyauth_avail => info_types[:long] + 24, + :os_errno => info_types[:long] + 25, + :num_connects => info_types[:long] + 26, + :ssl_engines => info_types[:slist] + 27, + :cookielist => info_types[:slist] + 28, + :lastsocket => info_types[:long] + 29, + :ftp_entry_path => info_types[:string] + 30, + :redirect_url => info_types[:string] + 31, + :primary_ip => info_types[:string] + 32, + :appconnect_time => info_types[:double] + 33, + :certinfo => info_types[:slist] + 34, + :condition_unmet => info_types[:long] + 35, + :rtsp_session_id => info_types[:string] + 36, + :rtsp_client_cseq => info_types[:long] + 37, + :rtsp_server_cseq => info_types[:long] + 38, + :rtsp_cseq_recv => info_types[:long] + 39, + :primary_port => info_types[:long] + 40, + :local_ip => info_types[:string] + 41, + :local_port => info_types[:long] + 42, + :last =>42 + } + end + + # Return info as string. + # + # @example Return info. + # Curl.get_info_string(:primary_ip, easy) + # + # @param [ Symbol ] option The option name. + # @param [ ::FFI::Pointer ] handle The easy handle. + # + # @return [ String ] The info. + def get_info_string(option, handle) + string_ptr = ::FFI::MemoryPointer.new(:pointer) + + if easy_getinfo(handle, option, string_ptr) == :ok + ptr=string_ptr.read_pointer + ptr.null? ? nil : ptr.read_string + end + end + + # Return info as integer. + # + # @example Return info. + # Curl.get_info_long(:response_code, easy) + # + # @param [ Symbol ] option The option name. + # @param [ ::FFI::Pointer ] handle The easy handle. + # + # @return [ Integer ] The info. + def get_info_long(option, handle) + long_ptr = ::FFI::MemoryPointer.new(:long) + + if easy_getinfo(handle, option, long_ptr) == :ok + long_ptr.read_long + end + end + + # Return info as float + # + # @example Return info. + # Curl.get_info_double(:response_code, easy) + # + # @param [ Symbol ] option The option name. + # @param [ ::FFI::Pointer ] handle The easy handle. + # + # @return [ Float ] The info. + def get_info_double(option, handle) + double_ptr = ::FFI::MemoryPointer.new(:double) + + if easy_getinfo(handle, option, double_ptr) == :ok + double_ptr.read_double + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/messages.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/messages.rb new file mode 100644 index 000000000..89893a60b --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/messages.rb @@ -0,0 +1,18 @@ +module Ethon + module Curls + + # This module contains available message codes. + module Messages + + # Return message codes. + # + # @example Return message codes. + # Ethon::Curl.msg_codes + # + # @return [ Array ] The messages codes. + def msg_codes + [:none, :done, :last] + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/options.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/options.rb new file mode 100644 index 000000000..0c3a7d6c6 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/options.rb @@ -0,0 +1,468 @@ +module Ethon + module Curls + + # This module contains logic for setting options on + # easy or multi interface. + module Options + + OPTION_STRINGS = { :easy => 'easy_options', :multi => 'multi_options' }.freeze + FOPTION_STRINGS = { :easy => 'EASY_OPTIONS', :multi => 'MULTI_OPTIONS' }.freeze + FTYPES = [:long, :string, :ffipointer, :callback, :debug_callback, :progress_callback, :off_t] + FUNCS = Hash[*[:easy, :multi].zip([:easy, :multi].map { |t| Hash[*FTYPES.zip(FTYPES.map { |ft| "#{t}_setopt_#{ft}" }).flatten] }).flatten] + # Sets appropriate option for easy, depending on value type. + def set_option(option, value, handle, type = :easy) + type = type.to_sym unless type.is_a?(Symbol) + raise NameError, "Ethon::Curls::Options unknown type #{type}." unless respond_to?(OPTION_STRINGS[type]) + opthash=send(OPTION_STRINGS[type], nil) + raise Errors::InvalidOption.new(option) unless opthash.include?(option) + + case opthash[option][:type] + when :none + return if value.nil? + value=1 + func=:long + when :int + return if value.nil? + func=:long + value=value.to_i + when :bool + return if value.nil? + func=:long + value=(value&&value!=0) ? 1 : 0 + when :time + return if value.nil? + func=:long + value=value.to_i + when :enum + return if value.nil? + func=:long + value = case value + when Symbol + opthash[option][:opts][value] + when String + opthash[option][:opts][value.to_sym] + else + value + end.to_i + when :bitmask + return if value.nil? + func=:long + value = case value + when Symbol + opthash[option][:opts][value] + when Array + value.inject(0) { |res,v| res|opthash[option][:opts][v] } + else + value + end.to_i + when :string + func=:string + value=value.to_s unless value.nil? + when :string_as_pointer + func = :ffipointer + s = '' + s = value.to_s unless value.nil? + value = FFI::MemoryPointer.new(:char, s.bytesize) + value.put_bytes(0, s) + when :string_escape_null + func=:string + value=Util.escape_zero_byte(value) unless value.nil? + when :ffipointer + func=:ffipointer + raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? FFI::Pointer + when :curl_slist + func=:ffipointer + raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? FFI::Pointer + when :buffer + raise NotImplementedError, "Ethon::Curls::Options option #{option} buffer type not implemented." + when :dontuse_object + raise NotImplementedError, "Ethon::Curls::Options option #{option} type not implemented." + when :cbdata + raise NotImplementedError, "Ethon::Curls::Options option #{option} callback data type not implemented. Use Ruby closures." + when :callback + func=:callback + raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc + when :debug_callback + func=:debug_callback + raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc + when :progress_callback + func=:progress_callback + raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc + when :off_t + return if value.nil? + func=:off_t + value=value.to_i + end + + if func==:long or func==:off_t then + bits=FFI.type_size(:long)*8 if func==:long + bits=FFI.type_size(:int64)*8 if func==:off_t + tv=((value<0) ? value.abs-1 : value) + raise Errors::InvalidValue.new(option,value) unless tv<(1< 0, + :objectpoint => 10000, + :functionpoint => 20000, + :off_t => 30000 + } + OPTION_TYPE_MAP = { + :none => :long, + :int => :long, + :bool => :long, + :time => :long, + :enum => :long, # Two ways to specify values (as opts parameter): + # * Array of symbols, these will number sequentially + # starting at 0. Skip elements with nil. (see :netrc) + # * Hash of :symbol => enum_value (See :proxytype) + :bitmask => :long, # Three ways to specify values (as opts parameter): + # * Hash of :symbol => bitmask_value or Array. + # An Array can be an array of already defined + # Symbols, which represents a bitwise or of those + # symbols. (See :httpauth) + # * Array of symbols, these will number the bits + # sequentially (i.e. 0, 1, 2, 4, etc.). Skip + # elements with nil. The last element can be a + # Hash, which will be interpreted as above. + # (See :protocols) + # :all defaults to all bits set + :string => :objectpoint, + :string_escape_null => :objectpoint, + :string_as_pointer => :objectpoint, + :ffipointer => :objectpoint, # FFI::Pointer + :curl_slist => :objectpoint, + :buffer => :objectpoint, # A memory buffer of size defined in the options + :dontuse_object => :objectpoint, # An object we don't support (e.g. FILE*) + :cbdata => :objectpoint, + :callback => :functionpoint, + :debug_callback => :functionpoint, + :progress_callback => :functionpoint, + :off_t => :off_t, + } + + def self.option(ftype,name,type,num,opts=nil) + case type + when :enum + if opts.is_a? Array then + opts=Hash[opts.each_with_index.to_a] + elsif not opts.is_a? Hash then + raise TypeError, "Ethon::Curls::Options #{ftype} #{name} Expected opts to be an Array or a Hash." + end + + when :bitmask + if opts.is_a? Array then + if opts.last.is_a? Hash then + hopts=opts.pop + else + hopts={} + end + opts.each_with_index do |v,i| + next if v.nil? + if i==0 then + hopts[v]=0 + else + hopts[v]=1<<(i-1) + end + end + opts=hopts + elsif not opts.is_a? Hash then + raise TypeError, "Ethon::Curls::Options #{ftype} #{name} Expected opts to be an Array or a Hash." + end + opts[:all]=-1 unless opts.include? :all + opts.each do |k,v| + if v.is_a? Array then + opts[k]=v.map { |b| opts[b] }.inject :| + end + end + + when :buffer + raise TypeError, "Ethon::Curls::Options #{ftype} #{name} Expected opts to be an Array or a Hash." unless opts.is_a? Integer + + else + raise ArgumentError, "Ethon::Curls::Options #{ftype} #{name} Expected no opts." unless opts.nil? + end + opthash=const_get(FOPTION_STRINGS[ftype]) + opthash[name] = { :type => type, + :opt => OPTION_TYPE_BASE[OPTION_TYPE_MAP[type]] + num, + :opts => opts } + end + + def self.option_alias(ftype,name,*aliases) + opthash=const_get(FOPTION_STRINGS[ftype]) + aliases.each { |a| opthash[a]=opthash[name] } + end + + def self.option_type(type) + cname = FOPTION_STRINGS[type] + const_set(cname, {}) + define_method(OPTION_STRINGS[type]) do |rt| + return Ethon::Curls::Options.const_get(cname).map { |k, v| [k, v[:opt]] } if rt == :enum + Ethon::Curls::Options.const_get(cname) + end + end + + # Curl multi options, refer + # Defined @ https://github.com/bagder/curl/blob/master/include/curl/multi.h + # Documentation @ http://curl.haxx.se/libcurl/c/curl_multi_setopt.html + option_type :multi + + option :multi, :socketfunction, :callback, 1 + option :multi, :socketdata, :cbdata, 2 + option :multi, :pipelining, :int, 3 + option :multi, :timerfunction, :callback, 4 + option :multi, :timerdata, :cbdata, 5 + option :multi, :maxconnects, :int, 6 + option :multi, :max_host_connections, :int, 7 + option :multi, :max_pipeline_length, :int, 8 + option :multi, :content_length_penalty_size, :off_t, 9 + option :multi, :chunk_length_penalty_size, :off_t, 10 + option :multi, :pipelining_site_bl, :dontuse_object, 11 + option :multi, :pipelining_server_bl, :dontuse_object, 12 + option :multi, :max_total_connections, :int, 3 + + # Curl easy options + # Defined @ https://github.com/bagder/curl/blob/master/include/curl/curl.h + # Documentation @ http://curl.haxx.se/libcurl/c/curl_easy_setopt.html + ## BEHAVIOR OPTIONS + option_type :easy + + option :easy, :verbose, :bool, 41 + option :easy, :header, :bool, 42 + option :easy, :noprogress, :bool, 43 + option :easy, :nosignal, :bool, 99 + option :easy, :wildcardmatch, :bool, 197 + ## CALLBACK OPTIONS + option :easy, :writefunction, :callback, 11 + option :easy, :file, :cbdata, 1 + option_alias :easy, :file, :writedata + option :easy, :readfunction, :callback, 12 + option :easy, :infile, :cbdata, 9 + option_alias :easy, :infile, :readdata + option :easy, :ioctlfunction, :callback, 130 + option :easy, :ioctldata, :cbdata, 131 + option :easy, :seekfunction, :callback, 167 + option :easy, :seekdata, :cbdata, 168 + option :easy, :sockoptfunction, :callback, 148 + option :easy, :sockoptdata, :cbdata, 149 + option :easy, :opensocketfunction, :callback, 163 + option :easy, :opensocketdata, :cbdata, 164 + option :easy, :closesocketfunction, :callback, 208 + option :easy, :closesocketdata, :cbdata, 209 + option :easy, :progressfunction, :progress_callback, 56 + option :easy, :progressdata, :cbdata, 57 + option :easy, :headerfunction, :callback, 79 + option :easy, :writeheader, :cbdata, 29 + option_alias :easy, :writeheader, :headerdata + option :easy, :debugfunction, :debug_callback, 94 + option :easy, :debugdata, :cbdata, 95 + option :easy, :ssl_ctx_function, :callback, 108 + option :easy, :ssl_ctx_data, :cbdata, 109 + option :easy, :conv_to_network_function, :callback, 143 + option :easy, :conv_from_network_function, :callback, 142 + option :easy, :conv_from_utf8_function, :callback, 144 + option :easy, :interleavefunction, :callback, 196 + option :easy, :interleavedata, :cbdata, 195 + option :easy, :chunk_bgn_function, :callback, 198 + option :easy, :chunk_end_function, :callback, 199 + option :easy, :chunk_data, :cbdata, 201 + option :easy, :fnmatch_function, :callback, 200 + option :easy, :fnmatch_data, :cbdata, 202 + option :easy, :xferinfofunction, :progress_callback, 219 + option :easy, :xferinfodata, :cbdata, 57 + ## ERROR OPTIONS + option :easy, :errorbuffer, :buffer, 10, 256 + option :easy, :stderr, :dontuse_object, 37 + option :easy, :failonerror, :bool, 45 + ## NETWORK OPTIONS + option :easy, :url, :string, 2 + option :easy, :protocols, :bitmask, 181, [nil, :http, :https, :ftp, :ftps, :scp, :sftp, :telnet, :ldap, :ldaps, :dict, :file, :tftp, :imap, :imaps, :pop3, :pop3s, :smtp, :smtps, :rtsp, :rtmp, :rtmpt, :rtmpe, :rtmpte, :rtmps, :rtmpts, :gopher] + option :easy, :redir_protocols, :bitmask, 182, [nil, :http, :https, :ftp, :ftps, :scp, :sftp, :telnet, :ldap, :ldaps, :dict, :file, :tftp, :imap, :imaps, :pop3, :pop3s, :smtp, :smtps, :rtsp, :rtmp, :rtmpt, :rtmpe, :rtmpte, :rtmps, :rtmpts, :gopher] + option :easy, :proxy, :string, 4 + option :easy, :proxyport, :int, 59 + option :easy, :proxytype, :enum, 101, [:http, :http_1_0, nil, nil, :socks4, :socks5, :socks4a, :socks5_hostname] + option :easy, :noproxy, :string, 177 + option :easy, :httpproxytunnel, :bool, 61 + option :easy, :socks5_gssapi_service, :string, 179 + option :easy, :socks5_gssapi_nec, :bool, 180 + option :easy, :interface, :string, 62 + option :easy, :localport, :int, 139 + option :easy, :localportrange, :int, 140 + option :easy, :dns_cache_timeout, :int, 92 + option :easy, :dns_use_global_cache, :bool, 91 # Obsolete + option :easy, :dns_interface, :string, 221 + option :easy, :dns_local_ip4, :string, 222 + option :easy, :buffersize, :int, 98 + option :easy, :port, :int, 3 + option :easy, :tcp_nodelay, :bool, 121 + option :easy, :address_scope, :int, 171 + option :easy, :tcp_keepalive, :bool, 213 + option :easy, :tcp_keepidle, :int, 214 + option :easy, :tcp_keepintvl, :int, 215 + ## NAMES and PASSWORDS OPTIONS (Authentication) + option :easy, :netrc, :enum, 51, [:ignored, :optional, :required] + option :easy, :netrc_file, :string, 118 + option :easy, :userpwd, :string, 5 + option :easy, :proxyuserpwd, :string, 6 + option :easy, :username, :string, 173 + option :easy, :password, :string, 174 + option :easy, :proxyusername, :string, 175 + option :easy, :proxypassword, :string, 176 + option :easy, :httpauth, :bitmask, 107, [:none, :basic, :digest, :gssnegotiate, :ntlm, :digest_ie, :ntlm_wb, {:only => 1<<31, :any => ~0x10, :anysafe => ~0x11, :auto => 0x1f}] + option :easy, :tlsauth_type, :enum, 206, [:none, :srp] + option :easy, :tlsauth_username, :string, 204 + option :easy, :tlsauth_password, :string, 205 + option :easy, :proxyauth, :bitmask, 111, [:none, :basic, :digest, :gssnegotiate, :ntlm, :digest_ie, :ntlm_wb, {:only => 1<<31, :any => ~0x10, :anysafe => ~0x11, :auto => 0x1f}] + option :easy, :sasl_ir, :bool, 218 + ## HTTP OPTIONS + option :easy, :autoreferer, :bool, 58 + option :easy, :accept_encoding, :string, 102 + option_alias :easy, :accept_encoding, :encoding + option :easy, :transfer_encoding, :bool, 207 + option :easy, :followlocation, :bool, 52 + option :easy, :unrestricted_auth, :bool, 105 + option :easy, :maxredirs, :int, 68 + option :easy, :postredir, :bitmask, 161, [:get_all, :post_301, :post_302, :post_303, {:post_all => [:post_301, :post_302, :post_303]}] + option_alias :easy, :postredir, :post301 + option :easy, :put, :bool, 54 + option :easy, :post, :bool, 47 + option :easy, :postfields, :string, 15 + option :easy, :postfieldsize, :int, 60 + option :easy, :postfieldsize_large, :off_t, 120 + option :easy, :copypostfields, :string_as_pointer, 165 + option :easy, :httppost, :ffipointer, 24 + option :easy, :referer, :string, 16 + option :easy, :useragent, :string, 18 + option :easy, :httpheader, :curl_slist, 23 + option :easy, :http200aliases, :curl_slist, 104 + option :easy, :cookie, :string, 22 + option :easy, :cookiefile, :string, 31 + option :easy, :cookiejar, :string, 82 + option :easy, :cookiesession, :bool, 96 + option :easy, :cookielist, :string, 135 + option :easy, :httpget, :bool, 80 + option :easy, :http_version, :enum, 84, [:none, :httpv1_0, :httpv1_1, :httpv2_0] + option :easy, :ignore_content_length, :bool, 136 + option :easy, :http_content_decoding, :bool, 158 + option :easy, :http_transfer_decoding, :bool, 157 + ## SMTP OPTIONS + option :easy, :mail_from, :string, 186 + option :easy, :mail_rcpt, :curl_slist, 187 + option :easy, :mail_auth, :string, 217 + ## TFTP OPTIONS + option :easy, :tftp_blksize, :int, 178 + ## FTP OPTIONS + option :easy, :ftpport, :string, 17 + option :easy, :quote, :curl_slist, 28 + option :easy, :postquote, :curl_slist, 39 + option :easy, :prequote, :curl_slist, 93 + option :easy, :dirlistonly, :bool, 48 + option_alias :easy, :dirlistonly, :ftplistonly + option :easy, :append, :bool, 50 + option_alias :easy, :append, :ftpappend + option :easy, :ftp_use_eprt, :bool, 106 + option :easy, :ftp_use_epsv, :bool, 85 + option :easy, :ftp_use_pret, :bool, 188 + option :easy, :ftp_create_missing_dirs, :bool, 110 + option :easy, :ftp_response_timeout, :int, 112 + option_alias :easy, :ftp_response_timeout, :server_response_timeout + option :easy, :ftp_alternative_to_user, :string, 147 + option :easy, :ftp_skip_pasv_ip, :bool, 137 + option :easy, :ftpsslauth, :enum, 129, [:default, :ssl, :tls] + option :easy, :ftp_ssl_ccc, :enum, 154, [:none, :passive, :active] + option :easy, :ftp_account, :string, 134 + option :easy, :ftp_filemethod, :enum, 138, [:default, :multicwd, :nocwd, :singlecwd] + ## RTSP OPTIONS + option :easy, :rtsp_request, :enum, 189, [:none, :options, :describe, :announce, :setup, :play, :pause, :teardown, :get_parameter, :set_parameter, :record, :receive] + option :easy, :rtsp_session_id, :string, 190 + option :easy, :rtsp_stream_uri, :string, 191 + option :easy, :rtsp_transport, :string, 192 + option_alias :easy, :httpheader, :rtspheader + option :easy, :rtsp_client_cseq, :int, 193 + option :easy, :rtsp_server_cseq, :int, 194 + ## PROTOCOL OPTIONS + option :easy, :transfertext, :bool, 53 + option :easy, :proxy_transfer_mode, :bool, 166 + option :easy, :crlf, :bool, 27 + option :easy, :range, :string, 7 + option :easy, :resume_from, :int, 21 + option :easy, :resume_from_large, :off_t, 116 + option :easy, :customrequest, :string, 36 + option :easy, :filetime, :bool, 69 + option :easy, :nobody, :bool, 44 + option :easy, :infilesize, :int, 14 + option :easy, :infilesize_large, :off_t, 115 + option :easy, :upload, :bool, 46 + option :easy, :maxfilesize, :int, 114 + option :easy, :maxfilesize_large, :off_t, 117 + option :easy, :timecondition, :enum, 33, [:none, :ifmodsince, :ifunmodsince, :lastmod] + option :easy, :timevalue, :time, 34 + ## CONNECTION OPTIONS + option :easy, :timeout, :int, 13 + option :easy, :timeout_ms, :int, 155 + option :easy, :low_speed_limit, :int, 19 + option :easy, :low_speed_time, :int, 20 + option :easy, :max_send_speed_large, :off_t, 145 + option :easy, :max_recv_speed_large, :off_t, 146 + option :easy, :maxconnects, :int, 71 + option :easy, :fresh_connect, :bool, 74 + option :easy, :forbid_reuse, :bool, 75 + option :easy, :connecttimeout, :int, 78 + option :easy, :connecttimeout_ms, :int, 156 + option :easy, :ipresolve, :enum, 113, [:whatever, :v4, :v6] + option :easy, :connect_only, :bool, 141 + option :easy, :use_ssl, :enum, 119, [:none, :try, :control, :all] + option_alias :easy, :use_ssl, :ftp_ssl + option :easy, :resolve, :curl_slist, 203 + option :easy, :dns_servers, :string, 211 + option :easy, :accepttimeout_ms, :int, 212 + option :easy, :unix_socket_path, :string, 231 + option :easy, :pipewait, :bool, 237 + option_alias :easy, :unix_socket_path, :unix_socket + ## SSL and SECURITY OPTIONS + option :easy, :sslcert, :string, 25 + option :easy, :sslcerttype, :string, 86 + option :easy, :sslkey, :string, 87 + option :easy, :sslkeytype, :string, 88 + option :easy, :keypasswd, :string, 26 + option_alias :easy, :keypasswd, :sslcertpasswd + option_alias :easy, :keypasswd, :sslkeypasswd + option :easy, :sslengine, :string, 89 + option :easy, :sslengine_default, :none, 90 + option :easy, :sslversion, :enum, 32, [:default, :tlsv1, :sslv2, :sslv3, :tlsv1_0, :tlsv1_1, :tlsv1_2] + option :easy, :ssl_verifypeer, :bool, 64 + option :easy, :cainfo, :string, 65 + option :easy, :issuercert, :string, 170 + option :easy, :capath, :string, 97 + option :easy, :crlfile, :string, 169 + option :easy, :ssl_verifyhost, :int, 81 + option :easy, :certinfo, :bool, 172 + option :easy, :random_file, :string, 76 + option :easy, :egdsocket, :string, 77 + option :easy, :ssl_cipher_list, :string, 83 + option :easy, :ssl_sessionid_cache, :bool, 150 + option :easy, :ssl_options, :bitmask, 216, [nil, :allow_beast] + option :easy, :krblevel, :string, 63 + option_alias :easy, :krblevel, :krb4level + option :easy, :gssapi_delegation, :bitmask, 210, [:none, :policy_flag, :flag] + ## SSH OPTIONS + option :easy, :ssh_auth_types, :bitmask, 151, [:none, :publickey, :password, :host, :keyboard, :agent, {:any => [:all], :default => [:any]}] + option :easy, :ssh_host_public_key_md5, :string, 162 + option :easy, :ssh_public_keyfile, :string, 152 + option :easy, :ssh_private_keyfile, :string, 153 + option :easy, :ssh_knownhosts, :string, 183 + option :easy, :ssh_keyfunction, :callback, 184 + option :easy, :khstat, :enum, -1, [:fine_add_to_file, :fine, :reject, :defer] # Kludge to make this enum available... Access via CurL::EASY_OPTIONS[:khstat][:opt] + option :easy, :ssh_keydata, :cbdata, 185 + ## OTHER OPTIONS + option :easy, :private, :cbdata, 103 + option :easy, :share, :dontuse_object, 100 + option :easy, :new_file_perms, :int, 159 + option :easy, :new_directory_perms, :int, 160 + ## TELNET OPTIONS + option :easy, :telnetoptions, :curl_slist, 70 + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/curls/settings.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/settings.rb new file mode 100644 index 000000000..345e6dfb0 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/curls/settings.rb @@ -0,0 +1,9 @@ +module Ethon + module Curl + callback :callback, [:pointer, :size_t, :size_t, :pointer], :size_t + callback :debug_callback, [:pointer, :debug_info_type, :pointer, :size_t, :pointer], :int + callback :progress_callback, [:pointer, :long_long, :long_long, :long_long, :long_long], :int + ffi_lib_flags :now, :global + ffi_lib ['libcurl', 'libcurl.so.4'] + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy.rb new file mode 100644 index 000000000..34e291cf6 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy.rb @@ -0,0 +1,315 @@ +require 'ethon/easy/informations' +require 'ethon/easy/features' +require 'ethon/easy/callbacks' +require 'ethon/easy/options' +require 'ethon/easy/header' +require 'ethon/easy/util' +require 'ethon/easy/params' +require 'ethon/easy/form' +require 'ethon/easy/http' +require 'ethon/easy/operations' +require 'ethon/easy/response_callbacks' +require 'ethon/easy/debug_info' +require 'ethon/easy/mirror' + +module Ethon + + # This is the class representing the libcurl easy interface + # See http://curl.haxx.se/libcurl/c/libcurl-easy.html for more informations. + # + # @example You can access the libcurl easy interface through this class, every request is based on it. The simplest setup looks like that: + # + # e = Ethon::Easy.new(url: "www.example.com") + # e.perform + # #=> :ok + # + # @example You can the reuse this Easy for the next request: + # + # e.reset # reset easy handle + # e.url = "www.google.com" + # e.followlocation = true + # e.perform + # #=> :ok + # + # @see initialize + class Easy + include Ethon::Easy::Informations + include Ethon::Easy::Callbacks + include Ethon::Easy::Options + include Ethon::Easy::Header + include Ethon::Easy::Http + include Ethon::Easy::Operations + include Ethon::Easy::ResponseCallbacks + extend Ethon::Easy::Features + + # Returns the curl return code. + # + # @return [ Symbol ] The return code. + # * :ok: All fine. Proceed as usual. + # * :unsupported_protocol: The URL you passed to libcurl used a + # protocol that this libcurl does not support. The support + # might be a compile-time option that you didn't use, it can + # be a misspelled protocol string or just a protocol + # libcurl has no code for. + # * :failed_init: Very early initialization code failed. This + # is likely to be an internal error or problem, or a + # resource problem where something fundamental couldn't + # get done at init time. + # * :url_malformat: The URL was not properly formatted. + # * :not_built_in: A requested feature, protocol or option + # was not found built-in in this libcurl due to a build-time + # decision. This means that a feature or option was not enabled + # or explicitly disabled when libcurl was built and in + # order to get it to function you have to get a rebuilt libcurl. + # * :couldnt_resolve_proxy: Couldn't resolve proxy. The given + # proxy host could not be resolved. + # * :couldnt_resolve_host: Couldn't resolve host. The given remote + # host was not resolved. + # * :couldnt_connect: Failed to connect() to host or proxy. + # * :ftp_weird_server_reply: After connecting to a FTP server, + # libcurl expects to get a certain reply back. This error + # code implies that it got a strange or bad reply. The given + # remote server is probably not an OK FTP server. + # * :remote_access_denied: We were denied access to the resource + # given in the URL. For FTP, this occurs while trying to + # change to the remote directory. + # * :ftp_accept_failed: While waiting for the server to connect + # back when an active FTP session is used, an error code was + # sent over the control connection or similar. + # * :ftp_weird_pass_reply: After having sent the FTP password to + # the server, libcurl expects a proper reply. This error code + # indicates that an unexpected code was returned. + # * :ftp_accept_timeout: During an active FTP session while + # waiting for the server to connect, the CURLOPT_ACCEPTTIMOUT_MS + # (or the internal default) timeout expired. + # * :ftp_weird_pasv_reply: libcurl failed to get a sensible result + # back from the server as a response to either a PASV or a + # EPSV command. The server is flawed. + # * :ftp_weird_227_format: FTP servers return a 227-line as a response + # to a PASV command. If libcurl fails to parse that line, + # this return code is passed back. + # * :ftp_cant_get_host: An internal failure to lookup the host used + # for the new connection. + # * :ftp_couldnt_set_type: Received an error when trying to set + # the transfer mode to binary or ASCII. + # * :partial_file: A file transfer was shorter or larger than + # expected. This happens when the server first reports an expected + # transfer size, and then delivers data that doesn't match the + # previously given size. + # * :ftp_couldnt_retr_file: This was either a weird reply to a + # 'RETR' command or a zero byte transfer complete. + # * :quote_error: When sending custom "QUOTE" commands to the + # remote server, one of the commands returned an error code that + # was 400 or higher (for FTP) or otherwise indicated unsuccessful + # completion of the command. + # * :http_returned_error: This is returned if CURLOPT_FAILONERROR is + # set TRUE and the HTTP server returns an error code that is >= 400. + # * :write_error: An error occurred when writing received data to a + # local file, or an error was returned to libcurl from a write callback. + # * :upload_failed: Failed starting the upload. For FTP, the server + # typically denied the STOR command. The error buffer usually + # contains the server's explanation for this. + # * :read_error: There was a problem reading a local file or an error + # returned by the read callback. + # * :out_of_memory: A memory allocation request failed. This is serious + # badness and things are severely screwed up if this ever occurs. + # * :operation_timedout: Operation timeout. The specified time-out + # period was reached according to the conditions. + # * :ftp_port_failed: The FTP PORT command returned error. This mostly + # happens when you haven't specified a good enough address for + # libcurl to use. See CURLOPT_FTPPORT. + # * :ftp_couldnt_use_rest: The FTP REST command returned error. This + # should never happen if the server is sane. + # * :range_error: The server does not support or accept range requests. + # * :http_post_error: This is an odd error that mainly occurs due to + # internal confusion. + # * :ssl_connect_error: A problem occurred somewhere in the SSL/TLS + # handshake. You really want the error buffer and read the message + # there as it pinpoints the problem slightly more. Could be + # certificates (file formats, paths, permissions), passwords, and others. + # * :bad_download_resume: The download could not be resumed because + # the specified offset was out of the file boundary. + # * :file_couldnt_read_file: A file given with FILE:// couldn't be + # opened. Most likely because the file path doesn't identify an + # existing file. Did you check file permissions? + # * :ldap_cannot_bind: LDAP cannot bind. LDAP bind operation failed. + # * :ldap_search_failed: LDAP search failed. + # * :function_not_found: Function not found. A required zlib function was not found. + # * :aborted_by_callback: Aborted by callback. A callback returned + # "abort" to libcurl. + # * :bad_function_argument: Internal error. A function was called with + # a bad parameter. + # * :interface_failed: Interface error. A specified outgoing interface + # could not be used. Set which interface to use for outgoing + # connections' source IP address with CURLOPT_INTERFACE. + # * :too_many_redirects: Too many redirects. When following redirects, + # libcurl hit the maximum amount. Set your limit with CURLOPT_MAXREDIRS. + # * :unknown_option: An option passed to libcurl is not recognized/known. + # Refer to the appropriate documentation. This is most likely a + # problem in the program that uses libcurl. The error buffer might + # contain more specific information about which exact option it concerns. + # * :telnet_option_syntax: A telnet option string was Illegally formatted. + # * :peer_failed_verification: The remote server's SSL certificate or + # SSH md5 fingerprint was deemed not OK. + # * :got_nothing: Nothing was returned from the server, and under the + # circumstances, getting nothing is considered an error. + # * :ssl_engine_notfound: The specified crypto engine wasn't found. + # * :ssl_engine_setfailed: Failed setting the selected SSL crypto engine as default! + # * :send_error: Failed sending network data. + # * :recv_error: Failure with receiving network data. + # * :ssl_certproblem: problem with the local client certificate. + # * :ssl_cipher: Couldn't use specified cipher. + # * :ssl_cacert: Peer certificate cannot be authenticated with known CA certificates. + # * :bad_content_encoding: Unrecognized transfer encoding. + # * :ldap_invalid_url: Invalid LDAP URL. + # * :filesize_exceeded: Maximum file size exceeded. + # * :use_ssl_failed: Requested FTP SSL level failed. + # * :send_fail_rewind: When doing a send operation curl had to rewind the data to + # retransmit, but the rewinding operation failed. + # * :ssl_engine_initfailed: Initiating the SSL Engine failed. + # * :login_denied: The remote server denied curl to login + # * :tftp_notfound: File not found on TFTP server. + # * :tftp_perm: Permission problem on TFTP server. + # * :remote_disk_full: Out of disk space on the server. + # * :tftp_illegal: Illegal TFTP operation. + # * :tftp_unknownid: Unknown TFTP transfer ID. + # * :remote_file_exists: File already exists and will not be overwritten. + # * :tftp_nosuchuser: This error should never be returned by a properly + # functioning TFTP server. + # * :conv_failed: Character conversion failed. + # * :conv_reqd: Caller must register conversion callbacks. + # * :ssl_cacert_badfile: Problem with reading the SSL CA cert (path? access rights?): + # * :remote_file_not_found: The resource referenced in the URL does not exist. + # * :ssh: An unspecified error occurred during the SSH session. + # * :ssl_shutdown_failed: Failed to shut down the SSL connection. + # * :again: Socket is not ready for send/recv wait till it's ready and try again. + # This return code is only returned from curl_easy_recv(3) and curl_easy_send(3) + # * :ssl_crl_badfile: Failed to load CRL file + # * :ssl_issuer_error: Issuer check failed + # * :ftp_pret_failed: The FTP server does not understand the PRET command at + # all or does not support the given argument. Be careful when + # using CURLOPT_CUSTOMREQUEST, a custom LIST command will be sent with PRET CMD + # before PASV as well. + # * :rtsp_cseq_error: Mismatch of RTSP CSeq numbers. + # * :rtsp_session_error: Mismatch of RTSP Session Identifiers. + # * :ftp_bad_file_list: Unable to parse FTP file list (during FTP wildcard downloading). + # * :chunk_failed: Chunk callback reported error. + # * :obsolete: These error codes will never be returned. They were used in an old + # libcurl version and are currently unused. + # + # @see http://curl.haxx.se/libcurl/c/libcurl-errors.html + attr_accessor :return_code + + # Initialize a new Easy. + # It initializes curl, if not already done and applies the provided options. + # Look into {Ethon::Easy::Options Options} to see what you can provide in the + # options hash. + # + # @example Create a new Easy. + # Easy.new(url: "www.google.de") + # + # @param [ Hash ] options The options to set. + # @option options :headers [ Hash ] Request headers. + # + # @return [ Easy ] A new Easy. + # + # @see Ethon::Easy::Options + # @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html + def initialize(options = {}) + Curl.init + set_attributes(options) + set_callbacks + end + + # Set given options. + # + # @example Set options. + # easy.set_attributes(options) + # + # @param [ Hash ] options The options. + # + # @raise InvalidOption + # + # @see initialize + def set_attributes(options) + options.each_pair do |key, value| + method = "#{key}=" + unless respond_to?(method) + raise Errors::InvalidOption.new(key) + end + send(method, value) + end + end + + # Reset easy. This means resetting all options and instance variables. + # Also the easy handle is resetted. + # + # @example Reset. + # easy.reset + def reset + @url = nil + @escape = nil + @hash = nil + @on_complete = nil + @on_headers = nil + @on_body = nil + @on_progress = nil + @procs = nil + @mirror = nil + Curl.easy_reset(handle) + set_callbacks + end + + # Clones libcurl session handle. This means that all options that is set in + # the current handle will be set on duplicated handle. + def dup + e = super + e.handle = Curl.easy_duphandle(handle) + e.instance_variable_set(:@body_write_callback, nil) + e.instance_variable_set(:@header_write_callback, nil) + e.instance_variable_set(:@debug_callback, nil) + e.instance_variable_set(:@progress_callback, nil) + e.set_callbacks + e + end + # Url escapes the value. + # + # @example Url escape. + # easy.escape(value) + # + # @param [ String ] value The value to escape. + # + # @return [ String ] The escaped value. + # + # @api private + def escape(value) + string_pointer = Curl.easy_escape(handle, value, value.bytesize) + returned_string = string_pointer.read_string + Curl.free(string_pointer) + returned_string + end + + # Returns the informations available through libcurl as + # a hash. + # + # @return [ Hash ] The informations hash. + def to_hash + Kernel.warn("Ethon: Easy#to_hash is deprecated and will be removed, please use #mirror.") + mirror.to_hash + end + + def mirror + @mirror ||= Mirror.from_easy(self) + end + + # Return pretty log out. + # + # @example Return log out. + # easy.log_inspect + # + # @return [ String ] The log out. + def log_inspect + "EASY #{mirror.log_informations.map{|k, v| "#{k}=#{v}"}.flatten.join(' ')}" + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/callbacks.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/callbacks.rb new file mode 100644 index 000000000..719c821b6 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/callbacks.rb @@ -0,0 +1,147 @@ +module Ethon + class Easy + + # This module contains all the logic around the callbacks, + # which are needed to interact with libcurl. + # + # @api private + module Callbacks + + # :nodoc: + def self.included(base) + base.send(:attr_accessor, *[:response_body, :response_headers, :debug_info]) + end + + # Set writefunction and headerfunction callback. + # They are called by libcurl in order to provide the header and + # the body from the request. + # + # @example Set callbacks. + # easy.set_callbacks + def set_callbacks + Curl.set_option(:writefunction, body_write_callback, handle) + Curl.set_option(:headerfunction, header_write_callback, handle) + Curl.set_option(:debugfunction, debug_callback, handle) + @response_body = "" + @response_headers = "" + @headers_called = false + @debug_info = Ethon::Easy::DebugInfo.new + end + + # Returns the body write callback. + # + # @example Return the callback. + # easy.body_write_callback + # + # @return [ Proc ] The callback. + def body_write_callback + @body_write_callback ||= proc do |stream, size, num, object| + headers + result = body(chunk = stream.read_string(size * num)) + @response_body << chunk if result == :unyielded + result != :abort ? size * num : -1 + end + end + + # Returns the header write callback. + # + # @example Return the callback. + # easy.header_write_callback + # + # @return [ Proc ] The callback. + def header_write_callback + @header_write_callback ||= proc {|stream, size, num, object| + @response_headers << stream.read_string(size * num) + size * num + } + end + + # Returns the debug callback. This callback is currently used + # write the raw http request headers. + # + # @example Return the callback. + # easy.body_write_callback + # + # @return [ Proc ] The callback. + def debug_callback + @debug_callback ||= proc {|handle, type, data, size, udata| + message = data.read_string(size) + @debug_info.add type, message + print message unless [:data_in, :data_out].include?(type) + 0 + } + end + + def set_progress_callback + if Curl.version_info[:version] >= "7.32.0" + Curl.set_option(:xferinfofunction, progress_callback, handle) + else + Curl.set_option(:progressfunction, progress_callback, handle) + end + end + + # Returns the progress callback. + # + # @example Return the callback. + # easy.progress_callback + # + # @return [ Proc ] The callback. + def progress_callback + @progress_callback ||= proc { |_, dltotal, dlnow, ultotal, ulnow| + progress(dltotal, dlnow, ultotal, ulnow) + 0 + } + end + + # Set the read callback. This callback is used by libcurl to + # read data when performing a PUT request. + # + # @example Set the callback. + # easy.set_read_callback("a=1") + # + # @param [ String ] body The body. + def set_read_callback(body) + @request_body_read = 0 + readfunction do |stream, size, num, object| + size = size * num + body_size = if body.respond_to?(:bytesize) + body.bytesize + elsif body.respond_to?(:size) + body.size + elsif body.is_a?(File) + File.size(body.path) + end + + left = body_size - @request_body_read + size = left if size > left + + if size > 0 + chunk = if body.respond_to?(:byteslice) + body.byteslice(@request_body_read, size) + elsif body.respond_to?(:read) + body.read(size) + else + body[@request_body_read, size] + end + + stream.write_string( + chunk, size + ) + @request_body_read += size + end + size + end + end + + # Returns the body read callback. + # + # @example Return the callback. + # easy.read_callback + # + # @return [ Proc ] The callback. + def read_callback + @read_callback + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/debug_info.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/debug_info.rb new file mode 100644 index 000000000..91a6a15a5 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/debug_info.rb @@ -0,0 +1,46 @@ +module Ethon + class Easy + + # This class is used to store and retreive debug information, + # which is only saved when verbose is set to true. + # + # @api private + class DebugInfo + + MESSAGE_TYPES = Ethon::Curl::DebugInfoType.to_h.keys + + class Message + attr_reader :type, :message + + def initialize(type, message) + @type = type + @message = message + end + end + + def initialize + @messages = [] + end + + def add(type, message) + @messages << Message.new(type, message) + end + + def messages_for(type) + @messages.select {|m| m.type == type }.map(&:message) + end + + MESSAGE_TYPES.each do |type| + eval %Q|def #{type}; messages_for(:#{type}); end| + end + + def to_a + @messages.map(&:message) + end + + def to_h + Hash[MESSAGE_TYPES.map {|k| [k, send(k)] }] + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/features.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/features.rb new file mode 100644 index 000000000..51bd90182 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/features.rb @@ -0,0 +1,30 @@ +module Ethon + class Easy + + # This module contains class methods for feature checks + module Features + # Returns true if this curl version supports zlib. + # + # @example Return wether zlib is supported. + # Ethon::Easy.supports_zlib? + # + # @return [ Boolean ] True if supported, else false. + def supports_zlib? + !!(Curl.version_info[:features] & Curl::VERSION_LIBZ) + end + + # Returns true if this curl version supports AsynchDNS. + # + # @example + # Ethon::Easy.supports_asynch_dns? + # + # @return [ Boolean ] True if supported, else false. + def supports_asynch_dns? + !!(Curl.version_info[:features] & Curl::VERSION_ASYNCHDNS) + end + + alias :supports_timeout_ms? :supports_asynch_dns? + + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/form.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/form.rb new file mode 100644 index 000000000..f2543a9ff --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/form.rb @@ -0,0 +1,106 @@ +require 'ethon/easy/util' +require 'ethon/easy/queryable' + +module Ethon + class Easy + + # This class represents a form and is used to send a payload in the + # request body via POST/PUT. + # It handles multipart forms, too. + # + # @api private + class Form + include Ethon::Easy::Util + include Ethon::Easy::Queryable + + # Return a new Form. + # + # @example Return a new Form. + # Form.new({}) + # + # @param [ Hash ] params The parameter with which to initialize the form. + # + # @return [ Form ] A new Form. + def initialize(easy, params, multipart = nil) + @easy = easy + @params = params || {} + @multipart = multipart + end + + # Return a pointer to the first form element in libcurl. + # + # @example Return the first form element. + # form.first + # + # @return [ FFI::Pointer ] The first element. + def first + @first ||= FFI::MemoryPointer.new(:pointer) + end + + # Return a pointer to the last form element in libcurl. + # + # @example Return the last form element. + # form.last + # + # @return [ FFI::Pointer ] The last element. + def last + @last ||= FFI::MemoryPointer.new(:pointer) + end + + # Return if form is multipart. The form is multipart + # when it contains a file or multipart option is set on the form during creation. + # + # @example Return if form is multipart. + # form.multipart? + # + # @return [ Boolean ] True if form is multipart, else false. + def multipart? + return true if @multipart + query_pairs.any?{|pair| pair.respond_to?(:last) && pair.last.is_a?(Array)} + end + + # Add form elements to libcurl. + # + # @example Add form to libcurl. + # form.materialize + def materialize + query_pairs.each { |pair| form_add(pair.first.to_s, pair.last) } + end + + private + + def form_add(name, content) + case content + when Array + Curl.formadd(first, last, + :form_option, :copyname, :pointer, name, + :form_option, :namelength, :long, name.bytesize, + :form_option, :file, :string, content[2], + :form_option, :filename, :string, content[0], + :form_option, :contenttype, :string, content[1], + :form_option, :end + ) + else + Curl.formadd(first, last, + :form_option, :copyname, :pointer, name, + :form_option, :namelength, :long, name.bytesize, + :form_option, :copycontents, :pointer, content.to_s, + :form_option, :contentslength, :long, content ? content.to_s.bytesize : 0, + :form_option, :end + ) + end + + setup_garbage_collection + end + + def setup_garbage_collection + # first is a pointer to a pointer. Since it's a MemoryPointer it will + # auto clean itself up, but we need to clean up the object it points + # to. So this results in (pseudo-c): + # form_data_cleanup_handler = *first + # curl_form_free(form_data_cleanup_handler) + @form_data_cleanup_handler ||= FFI::AutoPointer.new(@first.get_pointer(0), Curl.method(:formfree)) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/header.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/header.rb new file mode 100644 index 000000000..893d21c00 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/header.rb @@ -0,0 +1,60 @@ +module Ethon + class Easy + # This module contains the logic around adding headers to libcurl. + # + # @api private + module Header + # Return headers, return empty hash if none. + # + # @example Return the headers. + # easy.headers + # + # @return [ Hash ] The headers. + def headers + @headers ||= {} + end + + # Set the headers. + # + # @example Set the headers. + # easy.headers = {'User-Agent' => 'ethon'} + # + # @param [ Hash ] headers The headers. + def headers=(headers) + headers ||= {} + header_list = nil + headers.each do |k, v| + header_list = Curl.slist_append(header_list, compose_header(k,v)) + end + Curl.set_option(:httpheader, header_list, handle) + + @header_list = header_list && FFI::AutoPointer.new(header_list, Curl.method(:slist_free_all)) + end + + # Return header_list. + # + # @example Return header_list. + # easy.header_list + # + # @return [ FFI::Pointer ] The header list. + def header_list + @header_list + end + + # Compose libcurl header string from key and value. + # Also replaces null bytes, because libcurl will complain + # otherwise. + # + # @example Compose header. + # easy.compose_header('User-Agent', 'Ethon') + # + # @param [ String ] key The header name. + # @param [ String ] value The header value. + # + # @return [ String ] The composed header. + def compose_header(key, value) + Util.escape_zero_byte("#{key}: #{value}") + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http.rb new file mode 100644 index 000000000..e405ce155 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http.rb @@ -0,0 +1,67 @@ +require 'ethon/easy/http/actionable' +require 'ethon/easy/http/post' +require 'ethon/easy/http/get' +require 'ethon/easy/http/head' +require 'ethon/easy/http/put' +require 'ethon/easy/http/delete' +require 'ethon/easy/http/patch' +require 'ethon/easy/http/options' +require 'ethon/easy/http/custom' + +module Ethon + class Easy + + # This module contains logic about making valid HTTP requests. + module Http + + # Set specified options in order to make a HTTP request. + # Look at {Ethon::Easy::Options Options} to see what you can + # provide in the options hash. + # + # @example Set options for HTTP request. + # easy.http_request("www.google.com", :get, {}) + # + # @param [ String ] url The url. + # @param [ String ] action_name The HTTP action name. + # @param [ Hash ] options The options hash. + # + # @option options :params [ Hash ] Params hash which + # is attached to the url. + # @option options :body [ Hash ] Body hash which + # becomes the request body. It is a PUT body for + # PUT requests and a POST for everything else. + # @option options :headers [ Hash ] Request headers. + # + # @return [ void ] + # + # @see Ethon::Easy::Options + def http_request(url, action_name, options = {}) + fabricate(url, action_name, options).setup(self) + end + + private + + # Return the corresponding action class. + # + # @example Return the action. + # Action.fabricate(:get) + # Action.fabricate(:smash) + # + # @param [ String ] url The url. + # @param [ String ] action_name The HTTP action name. + # @param [ Hash ] options The option hash. + # + # @return [ Easy::Ethon::Actionable ] The request instance. + def fabricate(url, action_name, options) + constant_name = action_name.to_s.capitalize + + if Ethon::Easy::Http.const_defined?(constant_name) + Ethon::Easy::Http.const_get(constant_name).new(url, options) + else + Ethon::Easy::Http::Custom.new(constant_name.upcase, url, options) + end + end + + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/actionable.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/actionable.rb new file mode 100644 index 000000000..329ab5433 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/actionable.rb @@ -0,0 +1,156 @@ +require 'ethon/easy/http/putable' +require 'ethon/easy/http/postable' + +module Ethon + class Easy + module Http + # This module represents a Http Action and is a factory + # for more real actions like GET, HEAD, POST and PUT. + module Actionable + + QUERY_OPTIONS = [ :params, :body, :params_encoding ] + + # Create a new action. + # + # @example Create a new action. + # Action.new("www.example.com", {}) + # + # @param [ String ] url The url. + # @param [ Hash ] options The options. + # + # @return [ Action ] A new action. + def initialize(url, options) + @url = url + @options, @query_options = parse_options(options) + end + + # Return the url. + # + # @example Return url. + # action.url + # + # @return [ String ] The url. + def url + @url + end + + # Return the options hash. + # + # @example Return options. + # action.options + # + # @return [ Hash ] The options. + def options + @options + end + + # Returns the query options hash. + # + # @example Return query options. + # action.query_options + # + # @return [ Hash ] The query options. + def query_options + @query_options + end + + # Return the params. + # + # @example Return params. + # action.params + # + # @return [ Params ] The params. + def params + @params ||= Params.new(@easy, query_options.fetch(:params, nil)) + end + + # Return the form. + # + # @example Return form. + # action.form + # + # @return [ Form ] The form. + def form + @form ||= Form.new(@easy, query_options.fetch(:body, nil), options.fetch(:multipart, nil)) + end + + # Get the requested array encoding. By default it's + # :typhoeus, but it can also be set to :rack. + # + # @example Get encoding from options + # action.params_encoding + # + def params_encoding + @params_encoding ||= query_options.fetch(:params_encoding, :typhoeus) + end + + # Setup everything necessary for a proper request. + # + # @example setup. + # action.setup(easy) + # + # @param [ easy ] easy the easy to setup. + def setup(easy) + @easy = easy + + # Order is important, @easy will be used to provide access to options + # relevant to the following operations (like whether or not to escape + # values). + easy.set_attributes(options) + + set_form(easy) unless form.empty? + + if params.empty? + easy.url = url + else + set_params(easy) + end + end + + # Setup request with params. + # + # @example Setup nothing. + # action.set_params(easy) + # + # @param [ Easy ] easy The easy to setup. + def set_params(easy) + params.escape = easy.escape? + params.params_encoding = params_encoding + + base_url, base_params = url.split('?') + base_url << '?' + base_url << base_params.to_s + base_url << '&' if base_params + base_url << params.to_s + + easy.url = base_url + end + + # Setup request with form. + # + # @example Setup nothing. + # action.set_form(easy) + # + # @param [ Easy ] easy The easy to setup. + def set_form(easy) + end + + private + + def parse_options(options) + query_options = {} + options = options.dup + + QUERY_OPTIONS.each do |query_option| + if options.key?(query_option) + query_options[query_option] = options.delete(query_option) + end + end + + return options, query_options + end + end + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/custom.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/custom.rb new file mode 100644 index 000000000..1bee2f653 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/custom.rb @@ -0,0 +1,28 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making requests for custom HTTP verbs. + class Custom + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + def initialize(verb, url, options) + @verb = verb + super(url, options) + end + + # Setup easy to make a request. + # + # @example Setup. + # custom.set_params(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + easy.customrequest = @verb + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/delete.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/delete.rb new file mode 100644 index 000000000..ecdf33aaf --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/delete.rb @@ -0,0 +1,24 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making DELETE requests. + class Delete + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + # Setup easy to make a DELETE request. + # + # @example Setup customrequest. + # delete.setup(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + easy.customrequest = "DELETE" + end + end + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/get.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/get.rb new file mode 100644 index 000000000..345146bda --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/get.rb @@ -0,0 +1,23 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making GET requests. + class Get + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + # Setup easy to make a GET request. + # + # @example Setup. + # get.set_params(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + easy.customrequest = "GET" unless form.empty? + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/head.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/head.rb new file mode 100644 index 000000000..b15460cce --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/head.rb @@ -0,0 +1,23 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making HEAD requests. + class Head + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + # Setup easy to make a HEAD request. + # + # @example Setup. + # get.set_params(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + easy.nobody = true + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/options.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/options.rb new file mode 100644 index 000000000..b49f75ee2 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/options.rb @@ -0,0 +1,23 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making OPTIONS requests. + class Options + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + # Setup easy to make a OPTIONS request. + # + # @example Setup. + # options.setup(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + easy.customrequest = "OPTIONS" + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/patch.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/patch.rb new file mode 100644 index 000000000..36a69a664 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/patch.rb @@ -0,0 +1,23 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making PATCH requests. + class Patch + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + # Setup easy to make a PATCH request. + # + # @example Setup. + # patch.setup(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + easy.customrequest = "PATCH" + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/post.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/post.rb new file mode 100644 index 000000000..c454cbe93 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/post.rb @@ -0,0 +1,25 @@ +module Ethon + class Easy + module Http + # This class knows everything about making POST requests. + class Post + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Postable + + # Setup easy to make a POST request. + # + # @example Setup. + # post.setup(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + if form.empty? + easy.postfieldsize = 0 + easy.copypostfields = "" + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/postable.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/postable.rb new file mode 100644 index 000000000..a93ce1754 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/postable.rb @@ -0,0 +1,31 @@ +module Ethon + class Easy + module Http + + # This module contains logic for setting up a [multipart] POST body. + module Postable + + # Set things up when form is provided. + # Deals with multipart forms. + # + # @example Setup. + # post.set_form(easy) + # + # @param [ Easy ] easy The easy to setup. + def set_form(easy) + easy.url ||= url + form.params_encoding = params_encoding + if form.multipart? + form.escape = false + form.materialize + easy.httppost = form.first.read_pointer + else + form.escape = easy.escape? + easy.postfieldsize = form.to_s.bytesize + easy.copypostfields = form.to_s + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/put.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/put.rb new file mode 100644 index 000000000..4bfa41550 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/put.rb @@ -0,0 +1,26 @@ +module Ethon + class Easy + module Http + + # This class knows everything about making PUT requests. + class Put + include Ethon::Easy::Http::Actionable + include Ethon::Easy::Http::Putable + + # Setup easy to make a PUT request. + # + # @example Setup. + # put.setup(easy) + # + # @param [ Easy ] easy The easy to setup. + def setup(easy) + super + if form.empty? + easy.upload = true + easy.infilesize = 0 + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/putable.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/putable.rb new file mode 100644 index 000000000..5bca8750a --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/http/putable.rb @@ -0,0 +1,24 @@ +module Ethon + class Easy + module Http + + # This module contains logic about setting up a PUT body. + module Putable + # Set things up when form is provided. + # Deals with multipart forms. + # + # @example Setup. + # put.set_form(easy) + # + # @param [ Easy ] easy The easy to setup. + def set_form(easy) + easy.upload = true + form.escape = true + form.params_encoding = params_encoding + easy.infilesize = form.to_s.bytesize + easy.set_read_callback(form.to_s) + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/informations.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/informations.rb new file mode 100644 index 000000000..111993989 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/informations.rb @@ -0,0 +1,94 @@ +module Ethon + class Easy + + # This module contains the methods to return informations + # from the easy handle. See http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html + # for more information. + module Informations + + # Holds available informations and their type, which is needed to + # request the informations from libcurl. + AVAILABLE_INFORMATIONS = { + # Return the available HTTP auth methods. + :httpauth_avail => :long, + + # Return the total time in seconds for the previous + # transfer, including name resolution, TCP connection, etc. + :total_time => :double, + + # Return the time, in seconds, it took from the start + # until the first byte was received by libcurl. This + # includes pre-transfer time and also the time the + # server needs to calculate the result. + :starttransfer_time => :double, + + # Return the time, in seconds, it took from the start + # until the SSL/SSH connect/handshake to the remote + # host was completed. This time is most often very near + # to the pre-transfer time, except for cases such as HTTP + # pipelining where the pre-transfer time can be delayed + # due to waits in line for the pipeline and more. + :appconnect_time => :double, + + # Return the time, in seconds, it took from the start + # until the file transfer was just about to begin. This + # includes all pre-transfer commands and negotiations + # that are specific to the particular protocol(s) involved. + # It does not involve the sending of the protocol- + # specific request that triggers a transfer. + :pretransfer_time => :double, + + # Return the time, in seconds, it took from the start + # until the connect to the remote host (or proxy) was completed. + :connect_time => :double, + + # Return the time, in seconds, it took from the + # start until the name resolution was completed. + :namelookup_time => :double, + + # Return the time, in seconds, it took for all redirection steps + # include name lookup, connect, pretransfer and transfer before the + # final transaction was started. time_redirect shows the complete + # execution time for multiple redirections. (Added in 7.12.3) + :redirect_time => :double, + + # Return the last used effective url. + :effective_url => :string, + + # Return the string holding the IP address of the most recent + # connection done with this curl handle. This string + # may be IPv6 if that's enabled. + :primary_ip => :string, + + # Return the last received HTTP, FTP or SMTP response code. + # The value will be zero if no server response code has + # been received. Note that a proxy's CONNECT response should + # be read with http_connect_code and not this. + :response_code => :long, + + :request_size => :long, + + # Return the total number of redirections that were + # actually followed. + :redirect_count => :long + } + + AVAILABLE_INFORMATIONS.each do |name, type| + eval %Q|def #{name}; Curl.send(:get_info_#{type}, :#{name}, handle); end| + end + + # Returns true if this curl version supports zlib. + # + # @example Return wether zlib is supported. + # easy.supports_zlib? + # + # @return [ Boolean ] True if supported, else false. + # @deprecated Please use the static version instead + def supports_zlib? + Kernel.warn("Ethon: Easy#supports_zlib? is deprecated and will be removed, please use Easy#.") + Easy.supports_zlib? + end + + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/mirror.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/mirror.rb new file mode 100644 index 000000000..f6920e66e --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/mirror.rb @@ -0,0 +1,35 @@ +module Ethon + class Easy + class Mirror + attr_reader :options + alias_method :to_hash, :options + + INFORMATIONS_TO_MIRROR = Informations::AVAILABLE_INFORMATIONS.keys + + [:return_code, :response_headers, :response_body, :debug_info] + + INFORMATIONS_TO_LOG = [:effective_url, :response_code, :return_code, :total_time] + + def self.from_easy(easy) + options = {} + INFORMATIONS_TO_MIRROR.each do |info| + options[info] = easy.send(info) + end + new(options) + end + + def initialize(options = {}) + @options = options + end + + def log_informations + Hash[*INFORMATIONS_TO_LOG.map do |info| + [info, options[info]] + end.flatten] + end + + INFORMATIONS_TO_MIRROR.each do |info| + eval %Q|def #{info}; options[#{info}]; end| + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/operations.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/operations.rb new file mode 100644 index 000000000..43702f406 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/operations.rb @@ -0,0 +1,63 @@ +module Ethon + class Easy + # This module contains the logic to prepare and perform + # an easy. + module Operations + # Returns a pointer to the curl easy handle. + # + # @example Return the handle. + # easy.handle + # + # @return [ FFI::Pointer ] A pointer to the curl easy handle. + def handle + @handle ||= FFI::AutoPointer.new(Curl.easy_init, Curl.method(:easy_cleanup)) + end + + # Sets a pointer to the curl easy handle. + # @param [ ::FFI::Pointer ] Easy handle that will be assigned. + def handle=(h) + @handle = h + end + + # Perform the easy request. + # + # @example Perform the request. + # easy.perform + # + # @return [ Integer ] The return code. + def perform + @return_code = Curl.easy_perform(handle) + if Ethon.logger.debug? + Ethon.logger.debug { "ETHON: performed #{log_inspect}" } + end + complete + @return_code + end + + # Clean up the easy. + # + # @example Perform clean up. + # easy.cleanup + # + # @return the result of the free which is nil + def cleanup + handle.free + end + + # Prepare the easy. Options, headers and callbacks + # were set. + # + # @example Prepare easy. + # easy.prepare + # + # @deprecated It is no longer necessary to call prepare. + def prepare + Ethon.logger.warn( + "ETHON: It is no longer necessary to call "+ + "Easy#prepare. It's going to be removed "+ + "in future versions." + ) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/options.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/options.rb new file mode 100644 index 000000000..d93952392 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/options.rb @@ -0,0 +1,49 @@ +module Ethon + class Easy + + # This module contains the logic and knowledge about the + # available options on easy. + module Options + attr_reader :url + + def url=(value) + @url = value + Curl.set_option(:url, value, handle) + end + + def escape=( b ) + @escape = b + end + + def escape? + return true if !defined?(@escape) || @escape.nil? + @escape + end + + def multipart=(b) + @multipart = b + end + + def multipart? + !!@multipart + end + + Curl.easy_options(nil).each do |opt, props| + method_name = "#{opt}=".freeze + unless method_defined? method_name + define_method(method_name) do |value| + Curl.set_option(opt, value, handle) + value + end + end + next if props[:type] != :callback || method_defined?(opt) + define_method(opt) do |&block| + @procs ||= {} + @procs[opt.to_sym] = block + Curl.set_option(opt, block, handle) + nil + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/params.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/params.rb new file mode 100644 index 000000000..634a03fde --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/params.rb @@ -0,0 +1,28 @@ +require 'ethon/easy/util' +require 'ethon/easy/queryable' + +module Ethon + class Easy + + # This class represents HTTP request parameters. + # + # @api private + class Params + include Ethon::Easy::Util + include Ethon::Easy::Queryable + + # Create a new Params. + # + # @example Create a new Params. + # Params.new({}) + # + # @param [ Hash ] params The params to use. + # + # @return [ Params ] A new Params. + def initialize(easy, params) + @easy = easy + @params = params || {} + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/queryable.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/queryable.rb new file mode 100644 index 000000000..ae35ef652 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/queryable.rb @@ -0,0 +1,153 @@ +module Ethon + class Easy + + # This module contains logic about building + # query parameters for url or form. + module Queryable + + # :nodoc: + def self.included(base) + base.send(:attr_accessor, :escape) + base.send(:attr_accessor, :params_encoding) + end + + # Return wether there are elements in params or not. + # + # @example Return if params is empty. + # form.empty? + # + # @return [ Boolean ] True if params is empty, else false. + def empty? + @params.empty? + end + + # Return the string representation of params. + # + # @example Return string representation. + # params.to_s + # + # @return [ String ] The string representation. + def to_s + @to_s ||= query_pairs.map{ |pair| + return pair if pair.is_a?(String) + + if escape && @easy + pair.map{ |e| @easy.escape(e.to_s) }.join("=") + else + pair.join("=") + end + }.join('&') + end + + # Return the query pairs. + # + # @example Return the query pairs. + # params.query_pairs + # + # @return [ Array ] The query pairs. + def query_pairs + @query_pairs ||= build_query_pairs(@params) + end + + # Return query pairs build from a hash. + # + # @example Build query pairs. + # action.build_query_pairs({a: 1, b: 2}) + # #=> [[:a, 1], [:b, 2]] + # + # @param [ Hash ] hash The hash to go through. + # + # @return [ Array ] The array of query pairs. + def build_query_pairs(hash) + return [hash] if hash.is_a?(String) + + pairs = [] + recursively_generate_pairs(hash, nil, pairs) + pairs + end + + # Return file info for a file. + # + # @example Return file info. + # action.file_info(File.open('fubar', 'r')) + # + # @param [ File ] file The file to handle. + # + # @return [ Array ] Array of informations. + def file_info(file) + filename = File.basename(file.path) + [ + filename, + mime_type(filename), + File.expand_path(file.path) + ] + end + + private + + def mime_type(filename) + if defined?(MIME) && t = MIME::Types.type_for(filename).first + t.to_s + else + 'application/octet-stream' + end + end + + def recursively_generate_pairs(h, prefix, pairs) + case h + when Hash + encode_hash_pairs(h, prefix, pairs) + when Array + if params_encoding == :rack + encode_rack_array_pairs(h, prefix, pairs) + elsif params_encoding == :multi + encode_multi_array_pairs(h, prefix, pairs) + elsif params_encoding == :none + pairs << [prefix, h] + else + encode_indexed_array_pairs(h, prefix, pairs) + end + end + end + + def encode_hash_pairs(h, prefix, pairs) + h.each_pair do |k,v| + key = prefix.nil? ? k : "#{prefix}[#{k}]" + pairs_for(v, key, pairs) + end + end + + def encode_indexed_array_pairs(h, prefix, pairs) + h.each_with_index do |v, i| + key = "#{prefix}[#{i}]" + pairs_for(v, key, pairs) + end + end + + def encode_rack_array_pairs(h, prefix, pairs) + h.each do |v| + key = "#{prefix}[]" + pairs_for(v, key, pairs) + end + end + + def encode_multi_array_pairs(h, prefix, pairs) + h.each_with_index do |v, i| + key = prefix + pairs_for(v, key, pairs) + end + end + + def pairs_for(v, key, pairs) + case v + when Hash, Array + recursively_generate_pairs(v, key, pairs) + when File, Tempfile + pairs << [key, file_info(v)] + else + pairs << [key, v] + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/response_callbacks.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/response_callbacks.rb new file mode 100644 index 000000000..835d495da --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/response_callbacks.rb @@ -0,0 +1,130 @@ +module Ethon + class Easy + + # This module contains the logic for the response callbacks. + # The on_complete callback is the only one at the moment. + # + # You can set multiple callbacks, which are then executed + # in the same order. + # + # easy.on_complete { p 1 } + # easy.on_complete { p 2 } + # easy.complete + # #=> 1 + # #=> 2 + # + # You can clear the callbacks: + # + # easy.on_complete { p 1 } + # easy.on_complete { p 2 } + # easy.on_complete.clear + # easy.on_complete + # #=> [] + module ResponseCallbacks + + # Set on_headers callback. + # + # @example Set on_headers. + # request.on_headers { p "yay" } + # + # @param [ Block ] block The block to execute. + def on_headers(&block) + @on_headers ||= [] + @on_headers << block if block_given? + @on_headers + end + + # Execute on_headers callbacks. + # + # @example Execute on_headers. + # request.headers + def headers + return if @headers_called + @headers_called = true + if defined?(@on_headers) and not @on_headers.nil? + @on_headers.each{ |callback| callback.call(self) } + end + end + + # Set on_complete callback. + # + # @example Set on_complete. + # request.on_complete { p "yay" } + # + # @param [ Block ] block The block to execute. + def on_complete(&block) + @on_complete ||= [] + @on_complete << block if block_given? + @on_complete + end + + # Execute on_complete callbacks. + # + # @example Execute on_completes. + # request.complete + def complete + headers unless @response_headers.empty? + if defined?(@on_complete) and not @on_complete.nil? + @on_complete.each{ |callback| callback.call(self) } + end + end + + # Set on_progress callback. + # + # @example Set on_progress. + # request.on_progress {|dltotal, dlnow, ultotal, ulnow| p "#{dltotal} #{dlnow} #{ultotal} #{ulnow}" } + # + # @param [ Block ] block The block to execute. + def on_progress(&block) + @on_progress ||= [] + if block_given? + @on_progress << block + set_progress_callback + self.noprogress = 0 + end + @on_progress + end + + # Execute on_progress callbacks. + # + # @example Execute on_progress. + # request.body(1, 1, 1, 1) + def progress(dltotal, dlnow, ultotal, ulnow) + if defined?(@on_progress) and not @on_progress.nil? + @on_progress.each{ |callback| callback.call(dltotal, dlnow, ultotal, ulnow) } + end + end + + # Set on_body callback. + # + # @example Set on_body. + # request.on_body { |chunk| p "yay" } + # + # @param [ Block ] block The block to execute. + def on_body(&block) + @on_body ||= [] + @on_body << block if block_given? + @on_body + end + + # Execute on_body callbacks. + # + # @example Execute on_body. + # request.body("This data came from HTTP.") + # + # @return [ Object ] If there are no on_body callbacks, returns the symbol :unyielded. + def body(chunk) + if defined?(@on_body) and not @on_body.nil? + result = nil + @on_body.each do |callback| + result = callback.call(chunk, self) + break if result == :abort + end + result + else + :unyielded + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/easy/util.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/util.rb new file mode 100644 index 000000000..6b222cce2 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/easy/util.rb @@ -0,0 +1,27 @@ +module Ethon + class Easy # :nodoc: + + # This module contains small helpers. + # + # @api private + module Util + + # Escapes zero bytes in strings. + # + # @example Escape zero bytes. + # Util.escape_zero_byte("1\0") + # #=> "1\\0" + # + # @param [ Object ] value The value to escape. + # + # @return [ String, Object ] Escaped String if + # zero byte found, original object if not. + def escape_zero_byte(value) + return value unless value.to_s.include?(0.chr) + value.to_s.gsub(0.chr, '\\\0') + end + + extend self + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors.rb new file mode 100644 index 000000000..185d749e0 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors.rb @@ -0,0 +1,16 @@ +require 'ethon/errors/ethon_error' +require 'ethon/errors/global_init' +require 'ethon/errors/multi_timeout' +require 'ethon/errors/multi_fdset' +require 'ethon/errors/multi_add' +require 'ethon/errors/multi_remove' +require 'ethon/errors/select' +require 'ethon/errors/invalid_option' +require 'ethon/errors/invalid_value' + +module Ethon + + # This namespace contains all errors raised by ethon. + module Errors + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/ethon_error.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/ethon_error.rb new file mode 100644 index 000000000..ad12e88a5 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/ethon_error.rb @@ -0,0 +1,8 @@ +module Ethon + module Errors + + # Default Ethon error class for all custom errors. + class EthonError < StandardError + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/global_init.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/global_init.rb new file mode 100644 index 000000000..7056dcc02 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/global_init.rb @@ -0,0 +1,12 @@ +module Ethon + module Errors + + # Raises when global_init failed. + class GlobalInit < EthonError + def initialize + super("An error occured initializing curl.") + end + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_option.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_option.rb new file mode 100644 index 000000000..2ef4e534d --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_option.rb @@ -0,0 +1,12 @@ +module Ethon + module Errors + + # Raises when option is invalid. + class InvalidOption < EthonError + def initialize(option) + super("The option: #{option} is invalid.") + end + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_value.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_value.rb new file mode 100644 index 000000000..c45b8f244 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/invalid_value.rb @@ -0,0 +1,12 @@ +module Ethon + module Errors + + # Raises when option is invalid. + class InvalidValue < EthonError + def initialize(option, value) + super("The value: #{value} is invalid for option: #{option}.") + end + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_add.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_add.rb new file mode 100644 index 000000000..194ef9663 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_add.rb @@ -0,0 +1,11 @@ +module Ethon + module Errors + + # Raises when multi_add_handle failed. + class MultiAdd < EthonError + def initialize(code, easy) + super("An error occured adding the easy handle: #{easy} to the multi: #{code}") + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_fdset.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_fdset.rb new file mode 100644 index 000000000..2364015d4 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_fdset.rb @@ -0,0 +1,11 @@ +module Ethon + module Errors + + # Raises when multi_fdset failed. + class MultiFdset < EthonError + def initialize(code) + super("An error occured getting the fdset: #{code}") + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_remove.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_remove.rb new file mode 100644 index 000000000..fb43998b8 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_remove.rb @@ -0,0 +1,11 @@ +module Ethon + module Errors + + # Raises when multi_remove_handle failed. + class MultiRemove < EthonError + def initialize(code, easy) + super("An error occured removing the easy handle: #{easy} from the multi: #{code}") + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_timeout.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_timeout.rb new file mode 100644 index 000000000..647de75d4 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/multi_timeout.rb @@ -0,0 +1,12 @@ +module Ethon + module Errors + + # Raised when multi_timeout failed. + class MultiTimeout < EthonError + def initialize(code) + super("An error occured getting the timeout: #{code}") + # "An error occured getting the timeout: #{code}: #{Curl.multi_strerror(code)}" + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/errors/select.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/select.rb new file mode 100644 index 000000000..9bd22df79 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/errors/select.rb @@ -0,0 +1,12 @@ +module Ethon + module Errors + + # Raised when select failed. + class Select < EthonError + def initialize(errno) + super("An error occured on select: #{errno}") + end + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/libc.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/libc.rb new file mode 100644 index 000000000..845986678 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/libc.rb @@ -0,0 +1,20 @@ +module Ethon + + # FFI Wrapper module for Libc. + # + # @api private + module Libc + extend FFI::Library + ffi_lib 'c' + + # :nodoc: + def self.windows? + Gem.win_platform? + end + + unless windows? + attach_function :getdtablesize, [], :int + attach_function :free, [:pointer], :void + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/loggable.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/loggable.rb new file mode 100644 index 000000000..a442399fe --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/loggable.rb @@ -0,0 +1,58 @@ +# encoding: utf-8 +module Ethon + + # Contains logging behaviour. + module Loggable + + # Get the logger. + # + # @note Will try to grab Rails' logger first before creating a new logger + # with stdout. + # + # @example Get the logger. + # Loggable.logger + # + # @return [ Logger ] The logger. + def logger + return @logger if defined?(@logger) + @logger = rails_logger || default_logger + end + + # Set the logger. + # + # @example Set the logger. + # Loggable.logger = Logger.new($stdout) + # + # @param [ Logger ] logger The logger to set. + # + # @return [ Logger ] The new logger. + def logger=(logger) + @logger = logger + end + + private + + # Gets the default Ethon logger - stdout. + # + # @example Get the default logger. + # Loggable.default_logger + # + # @return [ Logger ] The default logger. + def default_logger + logger = Logger.new($stdout) + logger.level = Logger::INFO + logger + end + + # Get the Rails logger if it's defined. + # + # @example Get Rails' logger. + # Loggable.rails_logger + # + # @return [ Logger ] The Rails logger. + def rails_logger + defined?(::Rails) && ::Rails.respond_to?(:logger) && ::Rails.logger + end + end + extend Loggable +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/multi.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/multi.rb new file mode 100644 index 000000000..e51bb2976 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/multi.rb @@ -0,0 +1,103 @@ +require 'ethon/easy/util' +require 'ethon/multi/stack' +require 'ethon/multi/operations' +require 'ethon/multi/options' + +module Ethon + + # This class represents libcurl multi. + class Multi + include Ethon::Multi::Stack + include Ethon::Multi::Operations + include Ethon::Multi::Options + + # Create a new multi. Initialize curl in case + # it didn't happen before. + # + # @example Create a new Multi. + # Multi.new + # + # @param [ Hash ] options The options. + # + # @option options :socketdata [String] + # Pass a pointer to whatever you want passed to the + # curl_socket_callback's forth argument, the userp pointer. This is not + # used by libcurl but only passed-thru as-is. Set the callback pointer + # with CURLMOPT_SOCKETFUNCTION. + # @option options :pipelining [Boolean] + # Pass a long set to 1 to enable or 0 to disable. Enabling pipelining + # on a multi handle will make it attempt to perform HTTP Pipelining as + # far as possible for transfers using this handle. This means that if + # you add a second request that can use an already existing connection, + # the second request will be "piped" on the same connection rather than + # being executed in parallel. (Added in 7.16.0) + # @option options :timerfunction [Proc] + # Pass a pointer to a function matching the curl_multi_timer_callback + # prototype. This function will then be called when the timeout value + # changes. The timeout value is at what latest time the application + # should call one of the "performing" functions of the multi interface + # (curl_multi_socket_action(3) and curl_multi_perform(3)) - to allow + # libcurl to keep timeouts and retries etc to work. A timeout value of + # -1 means that there is no timeout at all, and 0 means that the + # timeout is already reached. Libcurl attempts to limit calling this + # only when the fixed future timeout time actually changes. See also + # CURLMOPT_TIMERDATA. This callback can be used instead of, or in + # addition to, curl_multi_timeout(3). (Added in 7.16.0) + # @option options :timerdata [String] + # Pass a pointer to whatever you want passed to the + # curl_multi_timer_callback's third argument, the userp pointer. This + # is not used by libcurl but only passed-thru as-is. Set the callback + # pointer with CURLMOPT_TIMERFUNCTION. (Added in 7.16.0) + # @option options :maxconnects [Integer] + # Pass a long. The set number will be used as the maximum amount of + # simultaneously open connections that libcurl may cache. Default is + # 10, and libcurl will enlarge the size for each added easy handle to + # make it fit 4 times the number of added easy handles. + # By setting this option, you can prevent the cache size from growing + # beyond the limit set by you. + # When the cache is full, curl closes the oldest one in the cache to + # prevent the number of open connections from increasing. + # This option is for the multi handle's use only, when using the easy + # interface you should instead use the CURLOPT_MAXCONNECTS option. + # (Added in 7.16.3) + # @option options :max_total_connections [Integer] + # Pass a long. The set number will be used as the maximum amount of + # simultaneously open connections in total. For each new session, + # libcurl will open a new connection up to the limit set by + # CURLMOPT_MAX_TOTAL_CONNECTIONS. When the limit is reached, the + # sessions will be pending until there are available connections. + # If CURLMOPT_PIPELINING is 1, libcurl will try to pipeline if the host + # is capable of it. + # The default value is 0, which means that there is no limit. However, + # for backwards compatibility, setting it to 0 when CURLMOPT_PIPELINING + # is 1 will not be treated as unlimited. Instead it will open only 1 + # connection and try to pipeline on it. + # (Added in 7.30.0) + # + # @return [ Multi ] The new multi. + def initialize(options = {}) + Curl.init + set_attributes(options) + init_vars + end + + # Set given options. + # + # @example Set options. + # multi.set_attributes(options) + # + # @raise InvalidOption + # + # @see initialize + # + # @api private + def set_attributes(options) + options.each_pair do |key, value| + unless respond_to?("#{key}=") + raise Errors::InvalidOption.new(key) + end + method("#{key}=").call(value) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/multi/operations.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/multi/operations.rb new file mode 100644 index 000000000..8e0c49d8a --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/multi/operations.rb @@ -0,0 +1,190 @@ +module Ethon + class Multi # :nodoc + # This module contains logic to run a multi. + module Operations + STARTED_MULTI = "ETHON: started MULTI" + PERFORMED_MULTI = "ETHON: performed MULTI" + + # Return the multi handle. Inititialize multi handle, + # in case it didn't happened already. + # + # @example Return multi handle. + # multi.handle + # + # @return [ FFI::Pointer ] The multi handle. + def handle + @handle ||= FFI::AutoPointer.new(Curl.multi_init, Curl.method(:multi_cleanup)) + end + + # Initialize variables. + # + # @example Initialize variables. + # multi.init_vars + # + # @return [ void ] + def init_vars + @timeout = ::FFI::MemoryPointer.new(:long) + @timeval = Curl::Timeval.new + @fd_read = Curl::FDSet.new + @fd_write = Curl::FDSet.new + @fd_excep = Curl::FDSet.new + @max_fd = ::FFI::MemoryPointer.new(:int) + end + + # Perform multi. + # + # @return [ nil ] + # + # @example Perform multi. + # multi.perform + def perform + Ethon.logger.debug(STARTED_MULTI) + while ongoing? + run + timeout = get_timeout + next if timeout == 0 + reset_fds + set_fds(timeout) + end + Ethon.logger.debug(PERFORMED_MULTI) + nil + end + + # Prepare multi. + # + # @return [ nil ] + # + # @example Prepare multi. + # multi.prepare + # + # @deprecated It is no longer necessary to call prepare. + def prepare + Ethon.logger.warn( + "ETHON: It is no longer necessay to call "+ + "Multi#prepare. Its going to be removed "+ + "in future versions." + ) + end + + private + + # Return wether the multi still requests or not. + # + # @example Return if ongoing. + # multi.ongoing? + # + # @return [ Boolean ] True if ongoing, else false. + def ongoing? + easy_handles.size > 0 || (!defined?(@running_count) || running_count > 0) + end + + # Get timeout. + # + # @example Get timeout. + # multi.get_timeout + # + # @return [ Integer ] The timeout. + # + # @raise [ Ethon::Errors::MultiTimeout ] If getting the timeout fails. + def get_timeout + code = Curl.multi_timeout(handle, @timeout) + raise Errors::MultiTimeout.new(code) unless code == :ok + timeout = @timeout.read_long + timeout = 1 if timeout < 0 + timeout + end + + # Reset file describtors. + # + # @example Reset fds. + # multi.reset_fds + # + # @return [ void ] + def reset_fds + @fd_read.clear + @fd_write.clear + @fd_excep.clear + end + + # Set fds. + # + # @example Set fds. + # multi.set_fds + # + # @return [ void ] + # + # @raise [ Ethon::Errors::MultiFdset ] If setting the file descriptors fails. + # @raise [ Ethon::Errors::Select ] If select fails. + def set_fds(timeout) + code = Curl.multi_fdset(handle, @fd_read, @fd_write, @fd_excep, @max_fd) + raise Errors::MultiFdset.new(code) unless code == :ok + max_fd = @max_fd.read_int + if max_fd == -1 + sleep(0.001) + else + @timeval[:sec] = timeout / 1000 + @timeval[:usec] = (timeout * 1000) % 1000000 + loop do + code = Curl.select(max_fd + 1, @fd_read, @fd_write, @fd_excep, @timeval) + break unless code < 0 && ::FFI.errno == Errno::EINTR::Errno + end + raise Errors::Select.new(::FFI.errno) if code < 0 + end + end + + # Check. + # + # @example Check. + # multi.check + # + # @return [ void ] + def check + msgs_left = ::FFI::MemoryPointer.new(:int) + while true + msg = Curl.multi_info_read(handle, msgs_left) + break if msg.null? + next if msg[:code] != :done + easy = easy_handles.find{ |e| e.handle == msg[:easy_handle] } + easy.return_code = msg[:data][:code] + Ethon.logger.debug { "ETHON: performed #{easy.log_inspect}" } + delete(easy) + easy.complete + end + end + + # Run. + # + # @example Run + # multi.run + # + # @return [ void ] + def run + running_count_pointer = FFI::MemoryPointer.new(:int) + begin code = trigger(running_count_pointer) end while code == :call_multi_perform + check + end + + # Trigger. + # + # @example Trigger. + # multi.trigger + # + # @return [ Symbol ] The Curl.multi_perform return code. + def trigger(running_count_pointer) + code = Curl.multi_perform(handle, running_count_pointer) + @running_count = running_count_pointer.read_int + code + end + + # Return number of running requests. + # + # @example Return count. + # multi.running_count + # + # @return [ Integer ] Number running requests. + def running_count + @running_count ||= nil + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/multi/options.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/multi/options.rb new file mode 100644 index 000000000..a564ac6d9 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/multi/options.rb @@ -0,0 +1,116 @@ +module Ethon + class Multi + + # This module contains the logic and knowledge about the + # available options on multi. + module Options + + # Sets max_total_connections option. + # + # @example Set max_total_connections option. + # easy.max_total_conections = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def max_total_connections=(value) + Curl.set_option(:max_total_connections, value_for(value, :int), handle, :multi) + end + + # Sets maxconnects option. + # + # @example Set maxconnects option. + # easy.maxconnects = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def maxconnects=(value) + Curl.set_option(:maxconnects, value_for(value, :int), handle, :multi) + end + + # Sets pipelining option. + # + # @example Set pipelining option. + # easy.pipelining = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def pipelining=(value) + Curl.set_option(:pipelining, value_for(value, :int), handle, :multi) + end + + # Sets socketdata option. + # + # @example Set socketdata option. + # easy.socketdata = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def socketdata=(value) + Curl.set_option(:socketdata, value_for(value, :string), handle, :multi) + end + + # Sets socketfunction option. + # + # @example Set socketfunction option. + # easy.socketfunction = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def socketfunction=(value) + Curl.set_option(:socketfunction, value_for(value, :string), handle, :multi) + end + + # Sets timerdata option. + # + # @example Set timerdata option. + # easy.timerdata = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def timerdata=(value) + Curl.set_option(:timerdata, value_for(value, :string), handle, :multi) + end + + # Sets timerfunction option. + # + # @example Set timerfunction option. + # easy.timerfunction = $value + # + # @param [ String ] value The value to set. + # + # @return [ void ] + def timerfunction=(value) + Curl.set_option(:timerfunction, value_for(value, :string), handle, :multi) + end + + private + + # Return the value to set to multi handle. It is converted with the help + # of bool_options, enum_options and int_options. + # + # @example Return casted the value. + # multi.value_for(:verbose) + # + # @return [ Object ] The casted value. + def value_for(value, type, option = nil) + return nil if value.nil? + + if type == :bool + value ? 1 : 0 + elsif type == :int + value.to_i + elsif value.is_a?(String) + Ethon::Easy::Util.escape_zero_byte(value) + else + value + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/multi/stack.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/multi/stack.rb new file mode 100644 index 000000000..fe1619f50 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/multi/stack.rb @@ -0,0 +1,48 @@ +module Ethon + class Multi + + # This module provides the multi stack behaviour. + module Stack + + # Return easy handles. + # + # @example Return easy handles. + # multi.easy_handles + # + # @return [ Array ] The easy handles. + def easy_handles + @easy_handles ||= [] + end + + # Add an easy to the stack. + # + # @example Add easy. + # multi.add(easy) + # + # @param [ Easy ] easy The easy to add. + # + # @raise [ Ethon::Errors::MultiAdd ] If adding an easy failed. + def add(easy) + return nil if easy_handles.include?(easy) + + code = Curl.multi_add_handle(handle, easy.handle) + raise Errors::MultiAdd.new(code, easy) unless code == :ok + easy_handles << easy + end + + # Delete an easy from stack. + # + # @example Delete easy from stack. + # + # @param [ Easy ] easy The easy to delete. + # + # @raise [ Ethon::Errors::MultiRemove ] If removing an easy failed. + def delete(easy) + if easy_handles.delete(easy) + code = Curl.multi_remove_handle(handle, easy.handle) + raise Errors::MultiRemove.new(code, handle) unless code == :ok + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/lib/ethon/version.rb b/fluentd/vendored_gem_src/ethon/lib/ethon/version.rb new file mode 100644 index 000000000..a2c62deca --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/lib/ethon/version.rb @@ -0,0 +1,5 @@ +module Ethon + + # Ethon version. + VERSION = '0.12.0' +end diff --git a/fluentd/vendored_gem_src/ethon/profile/benchmarks.rb b/fluentd/vendored_gem_src/ethon/profile/benchmarks.rb new file mode 100644 index 000000000..3a5e24d2d --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/profile/benchmarks.rb @@ -0,0 +1,103 @@ +# encoding: utf-8 +require 'ethon' +require 'open-uri' +require 'patron' +require 'curb' +require 'net/http' +require 'cgi' +require 'benchmark/ips' + +require_relative '../spec/support/server' +require_relative '../spec/support/localhost_server' + +LocalhostServer.new(TESTSERVER.new, 3000) +LocalhostServer.new(TESTSERVER.new, 3001) +LocalhostServer.new(TESTSERVER.new, 3002) + +url = 'http://localhost:3000/'.freeze +uri = URI.parse('http://localhost:3000/').freeze +ethon = Ethon::Easy.new(url: url) +patron = Patron::Session.new +patron_url = Patron::Session.new(base_url: url) +curb = Curl::Easy.new(url) + +puts '[Creation]' +Benchmark.ips do |x| + x.report('String.new') { '' } + x.report('Easy.new') { Ethon::Easy.new } +end + +puts '[Escape]' +Benchmark.ips do |x| + x.report('CGI.escape') { CGI.escape("まつもと") } + x.report('Easy.escape') { ethon.escape("まつもと") } +end + +puts '[Requests]' +Benchmark.ips do |x| + x.report('net/http') { Net::HTTP.get_response(uri) } + x.report('open-uri') { open url } + + x.report('patron') do + patron.base_url = url + patron.get('/') + end + + x.report('patron reuse') { patron_url.get('/') } + + x.report('curb') do + curb.url = url + curb.perform + end + + x.report('curb reuse') { curb.perform } + + x.report('Easy.perform') do + ethon.url = url + ethon.perform + end + + x.report('Easy.perform reuse') { ethon.perform } +end + +puts "[ 4 delayed Requests ]" +Benchmark.ips do |x| + x.report('net/http') do + 3.times do |i| + uri = URI.parse("http://localhost:300#{i}/?delay=1") + Net::HTTP.get_response(uri) + end + end + + x.report("open-uri") do + 3.times do |i| + open("http://localhost:300#{i}/?delay=1") + end + end + + x.report("patron") do + sess = Patron::Session.new + 3.times do |i| + sess.base_url = "http://localhost:300#{i}/?delay=1" + sess.get("/") + end + end + + x.report("Easy.perform") do + easy = Ethon::Easy.new + 3.times do |i| + easy.url = "http://localhost:300#{i}/?delay=1" + easy.perform + end + end + + x.report("Multi.perform") do + multi = Ethon::Multi.new + 3.times do |i| + easy = Ethon::Easy.new + easy.url = "http://localhost:300#{i}/?delay=1" + multi.add(easy) + end + multi.perform + end +end diff --git a/fluentd/vendored_gem_src/ethon/profile/memory_leaks.rb b/fluentd/vendored_gem_src/ethon/profile/memory_leaks.rb new file mode 100644 index 000000000..f8821081f --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/profile/memory_leaks.rb @@ -0,0 +1,113 @@ +require 'ethon' +require 'ethon/easy' + +require_relative 'perf_spec_helper' +require 'rspec/autorun' + +describe "low-level interactions with libcurl" do + describe Ethon::Multi do + memory_leak_test("init") do + Ethon::Multi.new + end + + memory_leak_test("handle") do + Ethon::Multi.new.handle + end + end + + describe Ethon::Easy do + memory_leak_test("init") do + Ethon::Easy.new + end + + memory_leak_test("handle") do + Ethon::Easy.new.handle + end + + memory_leak_test("headers") do + Ethon::Easy.new.headers = { "a" => 1, "b" => 2, "c" => 3, "d" => 4} + end + + memory_leak_test("escape") do + Ethon::Easy.new.escape("the_sky&is_blue") + end + end + + + describe Ethon::Easy::Form do + memory_leak_test("init") do + Ethon::Easy::Form.new(nil, {}) + end + + memory_leak_test("first") do + Ethon::Easy::Form.new(nil, {}).first + end + + memory_leak_test("last") do + Ethon::Easy::Form.new(nil, {}).last + end + + memory_leak_test("materialized with some params") do + form = Ethon::Easy::Form.new(nil, { "a" => "1" }) + form.materialize + end + + memory_leak_test("materialized with a file") do + File.open(__FILE__, "r") do |file| + form = Ethon::Easy::Form.new(nil, { "a" => file }) + form.materialize + end + end + end +end + +describe "higher level operations" do + memory_leak_test("a simple request") do + Ethon::Easy.new(:url => "http://localhost:3001/", + :forbid_reuse => true).perform + end + + memory_leak_test("a request with headers") do + Ethon::Easy.new(:url => "http://localhost:3001/", + :headers => { "Content-Type" => "application/json", + "Something" => "1", + "Else" => "qwerty", + "Long-String" => "aassddffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"}, + :forbid_reuse => true).perform + end + + memory_leak_test("a request with headers and params") do + easy = Ethon::Easy.new(:url => "http://localhost:3001/", + :headers => { "Content-Type" => "application/json", + "Something" => "1", + "Else" => "qwerty", + "Long-String" => "aassddffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"}, + :forbid_reuse => true) + easy.http_request("http://localhost:3001/", + :get, + :params => { "param1" => "value1", + "param2" => "value2", + "param3" => "value3", + "param4" => "value4"}) + end + + memory_leak_test("a request with headers, params, and body") do + easy = Ethon::Easy.new(:url => "http://localhost:3001/", + :headers => { "Content-Type" => "application/json", + "Something" => "1", + "Else" => "qwerty", + "Long-String" => "aassddffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"}, + :forbid_reuse => true) + easy.http_request("http://localhost:3001/", + :get, + :params => { "param1" => "value1", + "param2" => "value2", + "param3" => "value3", + "param4" => "value4"}, + :body => { + "body1" => "value1", + "body2" => "value2", + "body3" => "value3" + }) + end +end diff --git a/fluentd/vendored_gem_src/ethon/profile/perf_spec_helper.rb b/fluentd/vendored_gem_src/ethon/profile/perf_spec_helper.rb new file mode 100644 index 000000000..9b433fc89 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/profile/perf_spec_helper.rb @@ -0,0 +1,36 @@ +#### SETUP +require 'bundler' +Bundler.setup +require 'rspec' + +require 'support/localhost_server' +require 'support/server' +require_relative 'support/memory_test_helpers' + +require 'logger' + +if ENV['VERBOSE'] + Ethon.logger = Logger.new($stdout) + Ethon.logger.level = Logger::DEBUG +end + +RSpec.configure do |config| + config.before(:suite) do + LocalhostServer.new(TESTSERVER.new, 3001) + end + config.include(MemoryTestHelpers) + config.extend(MemoryTestHelpers::TestMethods) +end + +MemoryTestHelpers.setup +MemoryTestHelpers.logger = Logger.new($stdout) +MemoryTestHelpers.logger.level = Logger::INFO +MemoryTestHelpers.logger.formatter = proc do |severity, datetime, progname, msg| + "\t\t#{msg}\n" +end + +if ENV['VERBOSE'] + MemoryTestHelpers.logger.level = Logger::DEBUG +end + +MemoryTestHelpers.iterations = ENV.fetch("ITERATIONS", 10_000).to_i diff --git a/fluentd/vendored_gem_src/ethon/profile/support/memory_test_helpers.rb b/fluentd/vendored_gem_src/ethon/profile/support/memory_test_helpers.rb new file mode 100644 index 000000000..99f8bd5a8 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/profile/support/memory_test_helpers.rb @@ -0,0 +1,75 @@ +require_relative 'ruby_object_leak_tracker' +require_relative 'os_memory_leak_tracker' + +module MemoryTestHelpers + class << self + attr_accessor :gc_proc, :iterations, :logger + + def setup + if RUBY_PLATFORM == "java" + # for leak detection + JRuby.objectspace = true if defined?(JRuby) + # for gc + require 'java' + java_import 'java.lang.System' + self.gc_proc = proc { System.gc } + else + self.gc_proc = proc { GC.start } + end + end + end + + module TestMethods + def memory_leak_test(description, &block) + context(description) do + it "doesn't leak ruby objects" do + object_leak_tracker = RubyObjectLeakTracker.new + track_memory_usage(object_leak_tracker, &block) + object_leak_tracker.total_difference_between_runs.should be <= 10 + end + + it "doesn't leak OS memory (C interop check)" do + os_memory_leak_tracker = OSMemoryLeakTracker.new + track_memory_usage(os_memory_leak_tracker, &block) + os_memory_leak_tracker.total_difference_between_runs.should be <= 10 + end + end + end + end + + def track_memory_usage(tracker) + # Intentionally do all this setup before we do any testing + logger = MemoryTestHelpers.logger + iterations = MemoryTestHelpers.iterations + + checkpoint_frequency = (iterations / 10.0).to_i + gc_frequency = 20 + + warmup_iterations = [(iterations / 3.0).to_i, 500].min + logger.info "Performing #{warmup_iterations} warmup iterations" + warmup_iterations.times do + yield + MemoryTestHelpers.gc_proc.call + end + tracker.capture_initial_memory_usage + + logger.info "Performing #{iterations} iterations (checkpoint every #{checkpoint_frequency})" + + iterations.times do |i| + yield + + last_iteration = (i == iterations - 1) + checkpoint = last_iteration || (i % checkpoint_frequency == 0) + + if checkpoint || (i % gc_frequency == 0) + MemoryTestHelpers.gc_proc.call + end + + if checkpoint + logger.info "Iteration #{i} checkpoint" + tracker.capture_memory_usage + tracker.dump_status(logger) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/profile/support/os_memory_leak_tracker.rb b/fluentd/vendored_gem_src/ethon/profile/support/os_memory_leak_tracker.rb new file mode 100644 index 000000000..082c756f2 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/profile/support/os_memory_leak_tracker.rb @@ -0,0 +1,47 @@ +class OSMemoryLeakTracker + attr_reader :current_run + + def initialize + @previous_run = @current_run = 0 + end + + def difference_between_runs(basis=@previous_run) + @current_run - basis + end + + def total_difference_between_runs + difference_between_runs(@initial_count_run) + end + + def capture_initial_memory_usage + capture_memory_usage + @initial_count_run = @current_run + end + + def capture_memory_usage + @previous_run = @current_run + @current_run = rss_bytes + end + + def dump_status(logger) + delta = difference_between_runs + logger.add(log_level(delta), sprintf("\tTotal memory usage (kb): %d (%+d)", current_run, delta)) + end + + private + # amount of memory the current process "is using", in RAM + # (doesn't include any swap memory that it may be using, just that in actual RAM) + # Code loosely based on https://github.com/rdp/os/blob/master/lib/os.rb + # returns 0 on windows + def rss_bytes + if ENV['OS'] == 'Windows_NT' + 0 + else + `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes + end + end + + def log_level(delta) + delta > 0 ? Logger::WARN : Logger::DEBUG + end +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/ethon/profile/support/ruby_object_leak_tracker.rb b/fluentd/vendored_gem_src/ethon/profile/support/ruby_object_leak_tracker.rb new file mode 100644 index 000000000..f744cac99 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/profile/support/ruby_object_leak_tracker.rb @@ -0,0 +1,48 @@ +class RubyObjectLeakTracker + attr_reader :previous_count_hash, :current_count_hash + + def initialize + @previous_count_hash = @current_count_hash = {} + end + + def difference_between_runs(basis=@previous_count_hash) + @difference_between_runs ||= Hash[@current_count_hash.map do |object_class, count| + [object_class, count - (basis[object_class] || 0)] + end] + end + + def total_difference_between_runs + difference_between_runs(@initial_count_hash).values.inject(0) { |sum, count| sum + count } + end + + def capture_initial_memory_usage + capture_memory_usage + @initial_count_hash = @current_count_hash + end + + def capture_memory_usage + @difference_between_runs = nil + @previous_count_hash = @current_count_hash + + class_to_count = Hash.new { |hash, key| hash[key] = 0 } + ObjectSpace.each_object { |obj| class_to_count[obj.class] += 1 } + + sorted_class_to_count = class_to_count.sort_by { |k, v| -v } + @current_count_hash = Hash[sorted_class_to_count] + end + + def dump_status(logger) + diff = difference_between_runs + most_used_objects = current_count_hash.to_a.sort_by(&:last).reverse[0, 20] + + most_used_objects.each do |object_class, count| + delta = diff[object_class] + logger.add(log_level(delta), sprintf("\t%s: %d (%+d)", object_class, count, delta)) + end + end + + private + def log_level(delta) + delta > 0 ? Logger::WARN : Logger::DEBUG + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/curl_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/curl_spec.rb new file mode 100644 index 000000000..8f68537f1 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/curl_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe Ethon::Curl do + describe ".init" do + before { Ethon::Curl.send(:class_variable_set, :@@initialized, false) } + + context "when global_init fails" do + it "raises global init error" do + expect(Ethon::Curl).to receive(:global_init).and_return(1) + expect{ Ethon::Curl.init }.to raise_error(Ethon::Errors::GlobalInit) + end + end + + context "when global_init works" do + before { expect(Ethon::Curl).to receive(:global_init).and_return(0) } + + it "doesn't raises global init error" do + expect{ Ethon::Curl.init }.to_not raise_error + end + + it "logs" do + expect(Ethon.logger).to receive(:debug) + Ethon::Curl.init + end + end + + context "when global_cleanup is called" do + before { expect(Ethon::Curl).to receive(:global_cleanup) } + + it "logs" do + expect(Ethon.logger).to receive(:debug).twice + Ethon::Curl.init + Ethon::Curl.cleanup + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/callbacks_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/callbacks_spec.rb new file mode 100644 index 000000000..a9c8d1a9a --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/callbacks_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe Ethon::Easy::Callbacks do + let!(:easy) { Ethon::Easy.new } + + describe "#set_callbacks" do + before do + expect(Ethon::Curl).to receive(:set_option).exactly(3).times + end + + it "sets write-, debug-, and headerfunction" do + easy.set_callbacks + end + + it "resets @response_body" do + easy.set_callbacks + expect(easy.instance_variable_get(:@response_body)).to eq("") + end + + it "resets @response_headers" do + easy.set_callbacks + expect(easy.instance_variable_get(:@response_headers)).to eq("") + end + + it "resets @debug_info" do + easy.set_callbacks + expect(easy.instance_variable_get(:@debug_info).to_a).to eq([]) + end + end + + describe "#progress_callback" do + it "returns 0" do + expect(easy.progress_callback.call(0,1,1,1,1)).to be(0) + end + end + + describe "#body_write_callback" do + let(:body_write_callback) { easy.instance_variable_get(:@body_write_callback) } + let(:stream) { double(:read_string => "") } + context "when body returns not :abort" do + it "returns number bigger than 0" do + expect(body_write_callback.call(stream, 1, 1, nil) > 0).to be(true) + end + end + + context "when body returns :abort" do + before do + easy.on_body.clear + easy.on_body { :abort } + end + let(:body_write_callback) { easy.instance_variable_get(:@body_write_callback) } + + it "returns -1 to indicate abort to libcurl" do + expect(body_write_callback.call(stream, 1, 1, nil)).to eq(-1) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/debug_info_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/debug_info_spec.rb new file mode 100644 index 000000000..77d3d57ac --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/debug_info_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Ethon::Easy::DebugInfo do + let(:easy) { Ethon::Easy.new } + + before do + easy.url = "http://localhost:3001/" + easy.perform + end + + describe "#debug_info" do + context "when verbose is not set to true" do + it "does not save any debug info after a request" do + expect(easy.debug_info.to_a.length).to eq(0) + expect(easy.debug_info.to_h.values.flatten.length).to eq(0) + end + end + + context "when verbose is set to true" do + before do + easy.verbose = true + easy.perform + end + + after do + easy.verbose = false + easy.reset + end + + it "saves debug info after a request" do + expect(easy.debug_info.to_a.length).to be > 0 + end + + it "saves request headers" do + expect(easy.debug_info.header_out.join).to include('GET / HTTP/1.1') + end + + it "saves response headers" do + expect(easy.debug_info.header_in.length).to be > 0 + expect(easy.response_headers).to include(easy.debug_info.header_in.join) + end + + it "saves incoming data" do + expect(easy.debug_info.data_in.length).to be > 0 + expect(easy.response_body).to include(easy.debug_info.data_in.join) + end + + it "saves debug text" do + expect(easy.debug_info.text.length).to be > 0 + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/features_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/features_spec.rb new file mode 100644 index 000000000..1c84ebff3 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/features_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe Ethon::Easy::Informations do + + describe "#supports_asynch_dns?" do + it "returns boolean" do + expect([true, false].include? Ethon::Easy.supports_asynch_dns?).to be_truthy + end + end + + describe "#supports_zlib?" do + it "returns boolean" do + expect([true, false].include? Ethon::Easy.supports_zlib?).to be_truthy + end + end + + describe "#supports_timeout_ms?" do + it "returns boolean" do + expect([true, false].include? Ethon::Easy.supports_timeout_ms?).to be_truthy + end + end + +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/form_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/form_spec.rb new file mode 100644 index 000000000..99885c7f2 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/form_spec.rb @@ -0,0 +1,103 @@ +require 'spec_helper' + +describe Ethon::Easy::Form do + let(:hash) { {} } + let!(:easy) { Ethon::Easy.new } + let(:form) { Ethon::Easy::Form.new(easy, hash) } + + describe ".new" do + it "assigns attribute to @params" do + expect(form.instance_variable_get(:@params)).to eq(hash) + end + end + + describe "#first" do + it "returns a pointer" do + expect(form.first).to be_a(FFI::Pointer) + end + end + + describe "#last" do + it "returns a pointer" do + expect(form.first).to be_a(FFI::Pointer) + end + end + + describe "#multipart?" do + before { form.instance_variable_set(:@query_pairs, pairs) } + + context "when query_pairs contains string values" do + let(:pairs) { [['a', '1'], ['b', '2']] } + + it "returns false" do + expect(form.multipart?).to be_falsey + end + end + + context "when query_pairs contains file" do + let(:pairs) { [['a', '1'], ['b', ['path', 'encoding', 'abs_path']]] } + + it "returns true" do + expect(form.multipart?).to be_truthy + end + end + + context "when options contains multipart=true" do + before { form.instance_variable_set(:@multipart, true) } + let(:pairs) { [['a', '1'], ['b', '2']] } + + it "returns true" do + expect(form.multipart?).to be_truthy + end + end + end + + describe "#materialize" do + before { form.instance_variable_set(:@query_pairs, pairs) } + + context "when query_pairs contains string values" do + let(:pairs) { [['a', '1']] } + + it "adds params to form" do + expect(Ethon::Curl).to receive(:formadd) + form.materialize + end + end + + context "when query_pairs contains nil" do + let(:pairs) { [['a', nil]] } + + it "adds params to form" do + expect(Ethon::Curl).to receive(:formadd) + form.materialize + end + end + + context "when query_pairs contains file" do + let(:pairs) { [['a', ["file", "type", "path/file"]]] } + + it "adds file to form" do + expect(Ethon::Curl).to receive(:formadd) + form.materialize + end + end + + context "when query_pairs contains file and string values" do + let(:pairs) { [['a', ["file", "type", "path/file"]], ['b', '1']] } + + it "adds file to form" do + expect(Ethon::Curl).to receive(:formadd).twice + form.materialize + end + end + + context "when query_pairs contains file, string and int values" do + let(:pairs) { [['a', ["file", "type", "path/file"]], ['b', '1'], ['c', 1]] } + + it "adds file to form" do + expect(Ethon::Curl).to receive(:formadd).exactly(3).times + form.materialize + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/header_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/header_spec.rb new file mode 100644 index 000000000..9ab22e678 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/header_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe Ethon::Easy::Header do + let(:easy) { Ethon::Easy.new } + + describe "#headers=" do + let(:headers) { { 'User-Agent' => 'Ethon' } } + + it "sets header" do + expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks) + expect(Ethon::Curl).to receive(:set_option) + easy.headers = headers + end + + context "when requesting" do + before do + easy.headers = headers + easy.url = "http://localhost:3001" + easy.perform + end + + it "sends" do + expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"') + end + + context "when header value contains null byte" do + let(:headers) { { 'User-Agent' => "Ethon\0" } } + + it "escapes" do + expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon\\\\0"') + end + end + + context "when header value has leading whitespace" do + let(:headers) { { 'User-Agent' => " Ethon" } } + + it "removes" do + expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"') + end + end + + context "when header value has traiing whitespace" do + let(:headers) { { 'User-Agent' => "Ethon " } } + + it "removes" do + expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"') + end + end + end + end + + describe "#compose_header" do + it "has space in between" do + expect(easy.compose_header('a', 'b')).to eq('a: b') + end + + context "when value is a symbol" do + it "works" do + expect{ easy.compose_header('a', :b) }.to_not raise_error + end + end + end + + describe "#header_list" do + context "when no set_headers" do + it "returns nil" do + expect(easy.header_list).to eq(nil) + end + end + + context "when set_headers" do + it "returns pointer to header list" do + easy.headers = {'User-Agent' => 'Custom'} + expect(easy.header_list).to be_a(FFI::Pointer) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/custom_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/custom_spec.rb new file mode 100644 index 000000000..729df51f2 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/custom_spec.rb @@ -0,0 +1,176 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Custom do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:custom) { described_class.new("PURGE", url, {:params => params, :body => form}) } + + describe "#setup" do + context "when nothing" do + it "sets url" do + custom.setup(easy) + expect(easy.url).to eq(url) + end + + it "makes a custom request" do + custom.setup(easy) + easy.perform + expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"') + end + end + + context "when params" do + let(:params) { {:a => "1&"} } + + it "attaches escaped to url" do + custom.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26") + end + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + custom.setup(easy) + easy.perform + end + + it "is a custom verb" do + expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"') + end + + it "does not use application/x-www-form-urlencoded content type" do + expect(easy.response_body).to_not include('"CONTENT_TYPE":"application/x-www-form-urlencoded"') + end + + it "requests parameterized url" do + expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?a=1%26"') + end + end + end + + context "when body" do + context "when multipart" do + let(:form) { {:a => File.open(__FILE__, 'r')} } + + it "sets httppost" do + expect(easy).to receive(:httppost=) + custom.setup(easy) + end + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + custom.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a custom verb" do + expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"') + end + + it "uses multipart/form-data content type" do + expect(easy.response_body).to include('"CONTENT_TYPE":"multipart/form-data') + end + + it "submits a body" do + expect(easy.response_body).to match('"body":".+"') + end + + it "submits the data" do + expect(easy.response_body).to include('"filename":"custom_spec.rb"') + end + end + end + + context "when not multipart" do + let(:form) { {:a => "1&b=2"} } + let(:encoded) { "a=1%26b%3D2" } + + it "sets escaped copypostfields" do + expect(easy).to receive(:copypostfields=).with(encoded) + custom.setup(easy) + end + + it "sets postfieldsize" do + expect(easy).to receive(:postfieldsize=).with(encoded.bytesize) + custom.setup(easy) + end + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + custom.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a custom verb" do + expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"') + end + + it "uses multipart/form-data content type" do + expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded') + end + + it "submits a body" do + expect(easy.response_body).to match('"body":"a=1%26b%3D2"') + end + + it "submits the data" do + expect(easy.response_body).to include('"rack.request.form_hash":{"a":"1&b=2"}') + end + end + end + + context "when string" do + let(:form) { "{a: 1}" } + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + custom.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "sends string" do + expect(easy.response_body).to include('"body":"{a: 1}"') + end + end + end + end + + context "when params and body" do + let(:form) { {:a => "1"} } + let(:params) { {:b => "2"} } + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + custom.setup(easy) + easy.perform + end + + it "url contains params" do + expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?b=2"') + end + + it "body contains form" do + expect(easy.response_body).to include('"body":"a=1"') + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/delete_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/delete_spec.rb new file mode 100644 index 000000000..073c97dbf --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/delete_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Delete do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:delete) { described_class.new(url, {:params => params, :body => form}) } + + context "when requesting" do + before do + delete.setup(easy) + easy.perform + end + + it "makes a delete request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"DELETE"') + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/get_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/get_spec.rb new file mode 100644 index 000000000..ea384498b --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/get_spec.rb @@ -0,0 +1,125 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Get do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:options) { {} } + let(:get) { described_class.new(url, {:params => params, :body => form}.merge(options)) } + + describe "#setup" do + it "sets url" do + get.setup(easy) + expect(easy.url).to eq(url) + end + + context "when body" do + let(:form) { { :a => 1 } } + + it "sets customrequest" do + expect(easy).to receive(:customrequest=).with("GET") + get.setup(easy) + end + end + + context "when no body" do + it "doesn't set customrequest" do + expect(easy).to receive(:customrequest=).never + get.setup(easy) + end + end + + context "when requesting" do + before do + get.setup(easy) + easy.perform + end + + context "when url already contains params" do + let(:url) { "http://localhost:3001/?query=here" } + let(:params) { {:a => "1&b=2"} } + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a get request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"GET"') + end + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2") + end + end + + context "when params and no body" do + let(:params) { {:a => "1&b=2"} } + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a get request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"GET"') + end + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2") + end + end + + context "when params and body" do + let(:params) { {:a => "1&b=2"} } + let(:form) { {:b => "2"} } + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a get request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"GET"') + end + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2") + end + end + + context "with :escape" do + let(:params) { {:a => "1&b=2"} } + + context 'missing' do + it "escapes values" do + expect(easy.url).to eq("#{url}?a=1%26b%3D2") + end + end + + context 'nil' do + let(:options) { {:escape => nil} } + + it "escapes values" do + expect(easy.url).to eq("#{url}?a=1%26b%3D2") + end + end + + context 'true' do + let(:options) { {:escape => true} } + + it "escapes values" do + expect(easy.url).to eq("#{url}?a=1%26b%3D2") + end + end + + context 'false' do + let(:options) { {:escape => false} } + + it "sends raw values" do + expect(easy.url).to eq("#{url}?a=1&b=2") + end + end + end + + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/head_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/head_spec.rb new file mode 100644 index 000000000..9325b61e1 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/head_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Head do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:head) { described_class.new(url, {:params => params, :body => form}) } + + describe "#setup" do + context "when nothing" do + it "sets nobody" do + expect(easy).to receive(:nobody=).with(true) + head.setup(easy) + end + + it "sets url" do + head.setup(easy) + expect(easy.url).to eq(url) + end + end + + context "when params" do + let(:params) { {:a => "1&b=2"} } + + it "sets nobody" do + expect(easy).to receive(:nobody=).with(true) + head.setup(easy) + end + + it "attaches escaped to url" do + head.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26b%3D2") + end + + context "when requesting" do + before do + head.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "has no body" do + expect(easy.response_body).to be_empty + end + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2") + end + + context "when url already contains params" do + let(:url) { "http://localhost:3001/?query=here" } + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2") + end + end + end + end + + context "when body" do + let(:form) { {:a => 1} } + + context "when requesting" do + before do + head.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/options_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/options_spec.rb new file mode 100644 index 000000000..b85b5941c --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/options_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Options do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:options) { described_class.new(url, {:params => params, :body => form}) } + + describe "#setup" do + it "sets customrequest" do + expect(easy).to receive(:customrequest=).with("OPTIONS") + options.setup(easy) + end + + it "sets url" do + options.setup(easy) + expect(easy.url).to eq(url) + end + + context "when requesting" do + let(:params) { {:a => "1&b=2"} } + + before do + options.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a options request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"OPTIONS"') + end + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2") + end + + context "when url already contains params" do + let(:url) { "http://localhost:3001/?query=here" } + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2") + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/patch_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/patch_spec.rb new file mode 100644 index 000000000..7c1b957a0 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/patch_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Patch do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:patch) { described_class.new(url, {:params => params, :body => form}) } + + describe "#setup" do + it "sets customrequest" do + expect(easy).to receive(:customrequest=).with("PATCH") + patch.setup(easy) + end + + it "sets url" do + patch.setup(easy) + expect(easy.url).to eq(url) + end + + context "when requesting" do + let(:params) { {:a => "1&b=2"} } + + before do + patch.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a patch request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"PATCH"') + end + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2") + end + + context "when url already contains params" do + let(:url) { "http://localhost:3001/?query=here" } + + it "requests parameterized url" do + expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2") + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/post_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/post_spec.rb new file mode 100644 index 000000000..2389e3bbf --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/post_spec.rb @@ -0,0 +1,316 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Post do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:options) { Hash.new } + let(:post) { described_class.new(url, options.merge({:params => params, :body => form})) } + + describe "#setup" do + context "when nothing" do + it "sets url" do + post.setup(easy) + expect(easy.url).to eq(url) + end + + it "sets postfield_size" do + expect(easy).to receive(:postfieldsize=).with(0) + post.setup(easy) + end + + it "sets copy_postfields" do + expect(easy).to receive(:copypostfields=).with("") + post.setup(easy) + end + + it "makes a post request" do + post.setup(easy) + easy.perform + expect(easy.response_body).to include('"REQUEST_METHOD":"POST"') + end + end + + context "when params" do + let(:params) { {:a => "1&"} } + + it "attaches escaped to url" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26") + end + + context "with arrays" do + let(:params) { {:a => %w( foo bar )} } + + context "by default" do + it "encodes them with indexes" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a%5B0%5D=foo&a%5B1%5D=bar") + end + end + + context "when params_encoding is :rack" do + let(:options) { {:params_encoding => :rack} } + it "encodes them without indexes" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a%5B%5D=foo&a%5B%5D=bar") + end + end + end + + context "with :escape" do + context 'missing' do + it "escapes values" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26") + end + end + + context 'nil' do + let(:options) { {:escape => nil} } + + it "escapes values" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26") + end + end + + context 'true' do + let(:options) { {:escape => true} } + + it "escapes values" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26") + end + end + + context 'false' do + let(:options) { {:escape => false} } + + it "sends raw values" do + post.setup(easy) + expect(easy.url).to eq("#{url}?a=1&") + end + end + end + + it "sets postfieldsize" do + expect(easy).to receive(:postfieldsize=).with(0) + post.setup(easy) + end + + it "sets copypostfields" do + expect(easy).to receive(:copypostfields=).with("") + post.setup(easy) + end + + context "when requesting" do + let(:postredir) { nil } + + before do + easy.headers = { 'Expect' => '' } + post.setup(easy) + easy.postredir = postredir + easy.followlocation = true + easy.perform + end + + it "is a post" do + expect(easy.response_body).to include('"REQUEST_METHOD":"POST"') + end + + it "uses application/x-www-form-urlencoded content type" do + expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded"') + end + + it "requests parameterized url" do + expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?a=1%26"') + end + + context "when redirection" do + let(:url) { "localhost:3001/redirect" } + + context "when no postredirs" do + it "is a get" do + expect(easy.response_body).to include('"REQUEST_METHOD":"GET"') + end + end + + unless ENV['TRAVIS'] + context "when postredirs" do + let(:postredir) { :post_all } + + it "is a post" do + expect(easy.response_body).to include('"REQUEST_METHOD":"POST"') + end + end + end + end + end + end + + context "when body" do + context "when multipart" do + let(:form) { {:a => File.open(__FILE__, 'r')} } + + it "sets httppost" do + expect(easy).to receive(:httppost=) + post.setup(easy) + end + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + post.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a post" do + expect(easy.response_body).to include('"REQUEST_METHOD":"POST"') + end + + it "uses multipart/form-data content type" do + expect(easy.response_body).to include('"CONTENT_TYPE":"multipart/form-data') + end + + it "submits a body" do + expect(easy.response_body).to match('"body":".+"') + end + + it "submits the data" do + expect(easy.response_body).to include('"filename":"post_spec.rb"') + end + end + end + + context "when not multipart" do + let(:form) { {:a => "1&b=2"} } + let(:encoded) { "a=1%26b%3D2" } + + it "sets escaped copypostfields" do + expect(easy).to receive(:copypostfields=).with(encoded) + post.setup(easy) + end + + it "sets postfieldsize" do + expect(easy).to receive(:postfieldsize=).with(encoded.bytesize) + post.setup(easy) + end + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + post.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "is a post" do + expect(easy.response_body).to include('"REQUEST_METHOD":"POST"') + end + + it "uses multipart/form-data content type" do + expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded') + end + + it "submits a body" do + expect(easy.response_body).to match('"body":"a=1%26b%3D2"') + end + + it "submits the data" do + expect(easy.response_body).to include('"rack.request.form_hash":{"a":"1&b=2"}') + end + end + end + + context "when string" do + let(:form) { "{a: 1}" } + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + post.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "sends string" do + expect(easy.response_body).to include('"body":"{a: 1}"') + end + end + end + + context "when binary with null bytes" do + let(:form) { [1, 0, 1].pack('c*') } + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + post.setup(easy) + easy.perform + end + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "sends binary data" do + expect(easy.response_body).to include('"body":"\\u0001\\u0000\\u0001"') + end + end + end + + context "when arrays" do + let(:form) { {:a => %w( foo bar )} } + + context "by default" do + it "sets copypostfields with indexed, escaped representation" do + expect(easy).to receive(:copypostfields=).with('a%5B0%5D=foo&a%5B1%5D=bar') + post.setup(easy) + end + end + + context "when params_encoding is :rack" do + let(:options) { {:params_encoding => :rack} } + + it "sets copypostfields with non-indexed, escaped representation" do + expect(easy).to receive(:copypostfields=).with('a%5B%5D=foo&a%5B%5D=bar') + post.setup(easy) + end + end + end + end + + context "when params and body" do + let(:form) { {:a => "1"} } + let(:params) { {:b => "2"} } + + context "when requesting" do + before do + easy.headers = { 'Expect' => '' } + post.setup(easy) + easy.perform + end + + it "url contains params" do + expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?b=2"') + end + + it "body contains form" do + expect(easy.response_body).to include('"body":"a=1"') + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/put_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/put_spec.rb new file mode 100644 index 000000000..5067774b8 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http/put_spec.rb @@ -0,0 +1,167 @@ +require 'spec_helper' + +describe Ethon::Easy::Http::Put do + let(:easy) { Ethon::Easy.new } + let(:url) { "http://localhost:3001/" } + let(:params) { nil } + let(:form) { nil } + let(:options) { Hash.new } + let(:put) { described_class.new(url, options.merge({:params => params, :body => form})) } + + describe "#setup" do + context "when nothing" do + it "sets url" do + put.setup(easy) + expect(easy.url).to eq(url) + end + + it "sets upload" do + expect(easy).to receive(:upload=).with(true) + put.setup(easy) + end + + it "sets infilesize" do + expect(easy).to receive(:infilesize=).with(0) + put.setup(easy) + end + + context "when requesting" do + it "makes a put request" do + put.setup(easy) + easy.perform + expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"') + end + end + end + + context "when params" do + let(:params) { {:a => "1&"} } + + it "attaches escaped to url" do + put.setup(easy) + expect(easy.url).to eq("#{url}?a=1%26") + end + + context "with arrays" do + let(:params) { {:a => %w( foo bar )} } + + context "by default" do + it "encodes them with indexes" do + put.setup(easy) + expect(easy.url).to eq("#{url}?a%5B0%5D=foo&a%5B1%5D=bar") + end + end + + context "when params_encoding is :rack" do + let(:options) { {:params_encoding => :rack} } + it "encodes them without indexes" do + put.setup(easy) + expect(easy.url).to eq("#{url}?a%5B%5D=foo&a%5B%5D=bar") + end + end + end + + it "sets upload" do + expect(easy).to receive(:upload=).with(true) + put.setup(easy) + end + + it "sets infilesize" do + expect(easy).to receive(:infilesize=).with(0) + put.setup(easy) + end + + context "when requesting" do + before do + put.setup(easy) + easy.perform + end + + it "makes a put request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"') + end + end + end + + context "when body" do + let(:form) { {:a => "1&b=2"} } + + it "sets infilesize" do + expect(easy).to receive(:infilesize=).with(11) + put.setup(easy) + end + + it "sets readfunction" do + expect(easy).to receive(:readfunction) + put.setup(easy) + end + + it "sets upload" do + expect(easy).to receive(:upload=).with(true) + put.setup(easy) + end + + context "when requesting" do + context "sending string body" do + before do + easy.headers = { 'Expect' => '' } + put.setup(easy) + easy.perform + end + + it "makes a put request" do + expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"') + end + + it "submits a body" do + expect(easy.response_body).to include('"body":"a=1%26b%3D2"') + end + end + + context "when injecting a file as body" do + let(:file) { File.open(__FILE__) } + let(:easy) do + e = Ethon::Easy.new(:url => url, :upload => true) + e.set_read_callback(file) + e.infilesize = File.size(file.path) + e + end + + before do + easy.headers = { 'Expect' => '' } + easy.perform + end + + it "submits file" do + expect(easy.response_body).to include("injecting") + end + end + end + + context "when arrays" do + let(:form) { {:a => %w( foo bar )} } + + before do + put.setup(easy) + easy.perform + end + + context "by default" do + it "submits an indexed, escaped representation" do + expect(easy.response_body).to include('"body":"a%5B0%5D=foo&a%5B1%5D=bar"') + end + end + + context "when params_encoding is :rack" do + let(:options) { {:params_encoding => :rack} } + + it "submits an non-indexed, escaped representation" do + expect(easy.response_body).to include('"body":"a%5B%5D=foo&a%5B%5D=bar"') + end + end + end + end + + context "when params and body" + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http_spec.rb new file mode 100644 index 000000000..93f476ecc --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/http_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe Ethon::Easy::Http do + let(:easy) { Ethon::Easy.new } + + describe "#http_request" do + let(:url) { "http://localhost:3001/" } + let(:action_name) { :get } + let(:options) { {} } + + let(:get) { double(:setup) } + let(:get_class) { Ethon::Easy::Http::Get } + + it "instanciates action" do + expect(get).to receive(:setup) + expect(get_class).to receive(:new).and_return(get) + easy.http_request(url, action_name, options) + end + + context "when requesting" do + [ :get, :post, :put, :delete, :head, :patch, :options ].map do |action| + it "returns ok" do + easy.http_request(url, action, options) + easy.perform + expect(easy.return_code).to be(:ok) + end + + unless action == :head + it "makes a #{action.to_s.upcase} request" do + easy.http_request(url, action, options) + easy.perform + expect(easy.response_body).to include("\"REQUEST_METHOD\":\"#{action.to_s.upcase}\"") + end + + it "streams the response body from the #{action.to_s.upcase} request" do + bytes_read = 0 + easy.on_body { |chunk, response| bytes_read += chunk.bytesize } + easy.http_request(url, action, options) + easy.perform + content_length = ((easy.response_headers =~ /Content-Length: (\d+)/) && $1.to_i) + expect(bytes_read).to eq(content_length) + expect(easy.response_body).to eq("") + end + + it "notifies when headers are ready" do + headers = [] + easy.on_headers { |r| headers << r.response_headers } + easy.http_request(url, action, options) + easy.perform + expect(headers).to eq([easy.response_headers]) + expect(headers.first).to match(/Content-Length: (\d+)/) + end + end + end + + it "makes requests with custom HTTP verbs" do + easy.http_request(url, :purge, options) + easy.perform + expect(easy.response_body).to include(%{"REQUEST_METHOD":"PURGE"}) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/informations_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/informations_spec.rb new file mode 100644 index 000000000..1e6522c29 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/informations_spec.rb @@ -0,0 +1,97 @@ +require 'spec_helper' + +describe Ethon::Easy::Informations do + let(:easy) { Ethon::Easy.new } + + before do + easy.url = "http://localhost:3001" + easy.perform + end + + describe "#httpauth_avail" do + it "returns" do + expect(easy.httpauth_avail).to be + end + end + + describe "#total_time" do + it "returns float" do + expect(easy.total_time).to be_a(Float) + end + end + + describe "#starttransfer_time" do + it "returns float" do + expect(easy.starttransfer_time).to be_a(Float) + end + end + + describe "#appconnect_time" do + it "returns float" do + expect(easy.appconnect_time).to be_a(Float) + end + end + + describe "#pretransfer_time" do + it "returns float" do + expect(easy.pretransfer_time).to be_a(Float) + end + end + + describe "#connect_time" do + it "returns float" do + expect(easy.connect_time).to be_a(Float) + end + end + + describe "#namelookup_time" do + it "returns float" do + expect(easy.namelookup_time).to be_a(Float) + end + end + + describe "#redirect_time" do + it "returns float" do + expect(easy.redirect_time).to be_a(Float) + end + end + + describe "#effective_url" do + it "returns url" do + expect(easy.effective_url).to match(/^http:\/\/localhost:3001\/?/) + end + end + + describe "#primary_ip" do + it "returns localhost" do + expect(easy.primary_ip).to match(/::1|127\.0\.0\.1/) + end + end + + describe "#response_code" do + it "returns 200" do + expect(easy.response_code).to eq(200) + end + end + + describe "#redirect_count" do + it "returns 0" do + expect(easy.redirect_count).to eq(0) + end + end + + describe "#request_size" do + it "returns 53" do + expect(easy.request_size).to eq(53) + end + end + + describe "#supports_zlib?" do + it "returns true" do + expect(Kernel).to receive(:warn) + expect(easy.supports_zlib?).to be_truthy + end + end + + +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/mirror_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/mirror_spec.rb new file mode 100644 index 000000000..7a03c6baf --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/mirror_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe Ethon::Easy::Mirror do + let(:options) { nil } + let(:mirror) { described_class.new(options) } + + describe "::INFORMATIONS_TO_LOG" do + [ + :return_code, :response_code, :response_body, :response_headers, + :total_time, :starttransfer_time, :appconnect_time, + :pretransfer_time, :connect_time, :namelookup_time, :redirect_time, + :effective_url, :primary_ip, :redirect_count, :debug_info + ].each do |name| + it "contains #{name}" do + expect(described_class::INFORMATIONS_TO_MIRROR).to include(name) + end + end + end + + describe "#to_hash" do + let(:options) { {:return_code => 1} } + + it "returns mirror as hash" do + expect(mirror.to_hash).to eq(options) + end + end + + describe "#log_informations" do + let(:options) { {:return_code => 1} } + + it "returns hash" do + expect(mirror.log_informations).to be_a(Hash) + end + + it "only calls methods that exist" do + described_class::INFORMATIONS_TO_LOG.each do |method_name| + expect(mirror.respond_to? method_name).to eql(true) + end + end + + it "includes return code" do + expect(mirror.log_informations).to include(options) + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/operations_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/operations_spec.rb new file mode 100644 index 000000000..153a94ff3 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/operations_spec.rb @@ -0,0 +1,267 @@ +require 'spec_helper' + +describe Ethon::Easy::Operations do + let(:easy) { Ethon::Easy.new } + + describe "#handle" do + it "returns a pointer" do + expect(easy.handle).to be_a(FFI::Pointer) + end + end + + + describe "#perform" do + let(:url) { nil } + let(:timeout) { nil } + let(:connect_timeout) { nil } + let(:follow_location) { nil } + let(:max_redirs) { nil } + let(:user_pwd) { nil } + let(:http_auth) { nil } + let(:headers) { nil } + let(:protocols) { nil } + let(:redir_protocols) { nil } + let(:username) { nil } + let(:password) { nil } + + before do + Ethon.logger.level = Logger::DEBUG + easy.url = url + easy.timeout = timeout + easy.connecttimeout = connect_timeout + easy.followlocation = follow_location + easy.maxredirs = max_redirs + easy.httpauth = http_auth + easy.headers = headers + easy.protocols = protocols + easy.redir_protocols = redir_protocols + + if user_pwd + easy.userpwd = user_pwd + else + easy.username = username + easy.password = password + end + + easy.perform + end + + it "calls Curl.easy_perform" do + expect(Ethon::Curl).to receive(:easy_perform) + easy.perform + end + + it "calls Curl.easy_cleanup" do + expect_any_instance_of(FFI::AutoPointer).to receive(:free) + easy.cleanup + end + + it "logs" do + expect(Ethon.logger).to receive(:debug) + easy.perform + end + + it "doesn't log after completing because completing could reset" do + easy.on_complete{ expect(Ethon.logger).to receive(:debug).never } + easy.perform + end + + context "when url" do + let(:url) { "http://localhost:3001/" } + + it "returns ok" do + expect(easy.return_code).to eq(:ok) + end + + it "sets response body" do + expect(easy.response_body).to be + end + + it "sets response headers" do + expect(easy.response_headers).to be + end + + context "when request timed out" do + let(:url) { "http://localhost:3001/?delay=1" } + let(:timeout) { 1 } + + it "returns operation_timedout" do + expect(easy.return_code).to eq(:operation_timedout) + end + end + + context "when connection timed out" do + let(:url) { "http://localhost:3009" } + let(:connect_timeout) { 1 } + + it "returns couldnt_connect" do + expect(easy.return_code).to eq(:couldnt_connect) + end + end + + context "when no follow location" do + let(:url) { "http://localhost:3001/redirect" } + let(:follow_location) { false } + + it "doesn't follow" do + expect(easy.response_code).to eq(302) + end + end + + context "when follow location" do + let(:url) { "http://localhost:3001/redirect" } + let(:follow_location) { true } + + it "follows" do + expect(easy.response_code).to eq(200) + end + + context "when infinite redirect loop" do + let(:url) { "http://localhost:3001/bad_redirect" } + let(:max_redirs) { 5 } + + context "when max redirect set" do + it "follows only x times" do + expect(easy.response_code).to eq(302) + end + end + end + end + + context "when user agent" do + let(:headers) { { 'User-Agent' => 'Ethon' } } + + it "sets" do + expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"') + end + end + end + + context "when auth url" do + before { easy.url = url } + + context "when basic auth" do + let(:url) { "http://localhost:3001/auth_basic/username/password" } + + context "when no user_pwd" do + it "returns 401" do + expect(easy.response_code).to eq(401) + end + end + + context "when invalid user_pwd" do + let(:user_pwd) { "invalid:invalid" } + + it "returns 401" do + expect(easy.response_code).to eq(401) + end + end + + context "when valid user_pwd" do + let(:user_pwd) { "username:password" } + + it "returns 200" do + expect(easy.response_code).to eq(200) + end + end + + context "when user and password" do + let(:username) { "username" } + let(:password) { "password" } + + it "returns 200" do + expect(easy.response_code).to eq(200) + end + end + end + + context "when ntlm" do + let(:url) { "http://localhost:3001/auth_ntlm" } + let(:http_auth) { :ntlm } + + context "when no user_pwd" do + it "returns 401" do + expect(easy.response_code).to eq(401) + end + end + + context "when user_pwd" do + let(:user_pwd) { "username:password" } + + it "returns 200" do + expect(easy.response_code).to eq(200) + end + end + end + end + + context "when protocols" do + context "when asking for a allowed url" do + let(:url) { "http://localhost:3001" } + let(:protocols) { :http } + + it "returns ok" do + expect(easy.return_code).to be(:ok) + end + end + + context "when asking for a not allowed url" do + let(:url) { "http://localhost:3001" } + let(:protocols) { :https } + + it "returns unsupported_protocol" do + expect(easy.return_code).to be(:unsupported_protocol) + end + end + end + + context "when multiple protocols" do + context "when asking for a allowed url" do + let(:protocols) { [:http, :https] } + + context "when http" do + let(:url) { "http://localhost:3001" } + + it "returns ok for http" do + expect(easy.return_code).to be(:ok) + end + end + + context "when https" do + let(:url) { "https://localhost:3001" } + + it "returns ssl_connect_error for https" do + expect(easy.return_code).to be(:ssl_connect_error) + end + end + end + + context "when asking for a not allowed url" do + let(:url) { "ssh://localhost" } + let(:protocols) { [:https, :http] } + + it "returns unsupported_protocol" do + expect(easy.return_code).to be(:unsupported_protocol) + end + end + end + + context "when redir_protocols" do + context "when redirecting to a not allowed url" do + let(:url) { "http://localhost:3001/redirect" } + let(:follow_location) { true } + let(:redir_protocols) { :https } + + it "returns unsupported_protocol" do + expect(easy.return_code).to be(:unsupported_protocol) + end + end + end + + context "when no url" do + it "returns url_malformat" do + expect(easy.perform).to eq(:url_malformat) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/options_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/options_spec.rb new file mode 100644 index 000000000..80414806e --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/options_spec.rb @@ -0,0 +1,192 @@ +require 'spec_helper' + +describe Ethon::Easy::Options do + let(:easy) { Ethon::Easy.new } + + [ + :accept_encoding, :cainfo, :capath, :connecttimeout, :connecttimeout_ms, :cookie, + :cookiejar, :cookiefile, :copypostfields, :customrequest, :dns_cache_timeout, + :followlocation, :forbid_reuse, :http_version, :httpauth, :httpget, :httppost, + :infilesize, :interface, :keypasswd, :maxredirs, :nobody, :nosignal, + :postfieldsize, :postredir, :protocols, :proxy, :proxyauth, :proxyport, :proxytype, + :proxyuserpwd, :readdata, :readfunction, :redir_protocols, :ssl_verifyhost, + :ssl_verifypeer, :sslcert, :sslcerttype, :sslkey, :sslkeytype, :sslversion, + :timeout, :timeout_ms, :unrestricted_auth, :upload, :url, :useragent, + :userpwd, :verbose, :pipewait + ].each do |name| + describe "#{name}=" do + it "responds_to" do + expect(easy).to respond_to("#{name}=") + end + + it "sets option" do + expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks) + expect(Ethon::Curl).to receive(:set_option).with(name, anything, anything) + value = case name + when :http_version + :httpv1_0 + when :httpauth + :basic + when :protocols, :redir_protocols + :http + when :postredir + :post_301 + when :proxytype + :http + when :sslversion + :default + when :httppost + FFI::Pointer::NULL + else + 1 + end + easy.method("#{name}=").call(value) + end + end + end + + describe '#escape?' do + context 'by default' do + it 'returns true' do + expect(easy.escape?).to be_truthy + end + end + + context 'when #escape=nil' do + it 'returns true' do + easy.escape = nil + expect(easy.escape?).to be_truthy + end + end + + context 'when #escape=true' do + it 'returns true' do + easy.escape = true + expect(easy.escape?).to be_truthy + end + end + + context 'when #escape=false' do + it 'returns true' do + easy.escape = false + expect(easy.escape?).to be_falsey + end + end + end + + describe '#multipart?' do + context 'by default' do + it 'returns false' do + expect(easy.multipart?).to be_falsey + end + end + + context 'when #multipart=nil' do + it 'returns false' do + easy.multipart = nil + expect(easy.multipart?).to be_falsey + end + end + + context 'when #multipart=true' do + it 'returns true' do + easy.multipart = true + expect(easy.multipart?).to be_truthy + end + end + + context 'when #multipart=false' do + it 'returns false' do + easy.multipart = false + expect(easy.multipart?).to be_falsey + end + end + end + + describe "#httppost=" do + it "raises unless given a FFI::Pointer" do + expect{ easy.httppost = 1 }.to raise_error(Ethon::Errors::InvalidValue) + end + end + + context "when requesting" do + let(:url) { "localhost:3001" } + let(:timeout) { nil } + let(:timeout_ms) { nil } + let(:connecttimeout) { nil } + let(:connecttimeout_ms) { nil } + let(:userpwd) { nil } + + before do + easy.url = url + easy.timeout = timeout + easy.timeout_ms = timeout_ms + easy.connecttimeout = connecttimeout + easy.connecttimeout_ms = connecttimeout_ms + easy.userpwd = userpwd + easy.perform + end + + context "when userpwd" do + context "when contains /" do + let(:url) { "localhost:3001/auth_basic/test/te%2Fst" } + let(:userpwd) { "test:te/st" } + + it "works" do + expect(easy.response_code).to eq(200) + end + end + end + + context "when timeout" do + let(:timeout) { 1 } + + context "when request takes longer" do + let(:url) { "localhost:3001?delay=2" } + + it "times out" do + expect(easy.return_code).to eq(:operation_timedout) + end + end + end + + context "when connecttimeout" do + let(:connecttimeout) { 1 } + + context "when cannot connect" do + let(:url) { "localhost:3002" } + + it "times out" do + expect(easy.return_code).to eq(:couldnt_connect) + end + end + end + + if Ethon::Easy.supports_timeout_ms? + context "when timeout_ms" do + let(:timeout_ms) { 100 } + + context "when request takes longer" do + let(:url) { "localhost:3001?delay=1" } + + it "times out" do + expect(easy.return_code).to eq(:operation_timedout) + end + end + end + + context "when connecttimeout_ms" do + let(:connecttimeout_ms) { 100 } + + context "when cannot connect" do + let(:url) { "localhost:3002" } + + it "times out" do + # this can either lead to a timeout or couldnt connect depending on which happens first + expect([:couldnt_connect, :operation_timedout]).to include(easy.return_code) + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/queryable_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/queryable_spec.rb new file mode 100644 index 000000000..4ac78370f --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/queryable_spec.rb @@ -0,0 +1,234 @@ +# encoding: utf-8 +require 'spec_helper' + +describe Ethon::Easy::Queryable do + let(:hash) { {} } + let!(:easy) { Ethon::Easy.new } + let(:params) { Ethon::Easy::Params.new(easy, hash) } + + describe "#to_s" do + context "when query_pairs empty" do + before { params.instance_variable_set(:@query_pairs, []) } + + it "returns empty string" do + expect(params.to_s).to eq("") + end + end + + context "when query_pairs not empty" do + context "when escape" do + before do + params.escape = true + end + + { + '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', + ')' => '%29', ';' => '%3B', ':' => '%3A', '@' => '%40', + '&' => '%26', '=' => '%3D', '+' => '%2B', '$' => '%24', + ',' => '%2C', '/' => '%2F', '?' => '%3F', '#' => '%23', + '[' => '%5B', ']' => '%5D', + + '<' => '%3C', '>' => '%3E', '"' => '%22', '{' => '%7B', + '}' => '%7D', '|' => '%7C', '\\' => '%5C', '`' => '%60', + '^' => '%5E', '%' => '%25', ' ' => '%20', "\0" => '%00', + + 'まつもと' => '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8', + }.each do |value, percent| + it "turns #{value.inspect} into #{percent}" do + params.instance_variable_set(:@query_pairs, [[:a, value]]) + expect(params.to_s).to eq("a=#{percent}") + end + end + + { + '.' => '%2E', '-' => '%2D', '_' => '%5F', '~' => '%7E', + }.each do |value, percent| + it "leaves #{value.inspect} instead of turning into #{percent}" do + params.instance_variable_set(:@query_pairs, [[:a, value]]) + expect(params.to_s).to eq("a=#{value}") + end + end + end + + context "when no escape" do + before { params.instance_variable_set(:@query_pairs, [[:a, 1], [:b, 2]]) } + + it "returns concatenated query string" do + expect(params.to_s).to eq("a=1&b=2") + end + end + end + + context "when query_pairs contains a string" do + before { params.instance_variable_set(:@query_pairs, ["{a: 1}"]) } + + it "returns correct string" do + expect(params.to_s).to eq("{a: 1}") + end + end + end + + describe "#build_query_pairs" do + let(:pairs) { params.method(:build_query_pairs).call(hash) } + + context "when params is empty" do + it "returns empty array" do + expect(pairs).to eq([]) + end + end + + context "when params is string" do + let(:hash) { "{a: 1}" } + + it "wraps it in an array" do + expect(pairs).to eq([hash]) + end + end + + context "when params is simple hash" do + let(:hash) { {:a => 1, :b => 2} } + + it "transforms" do + expect(pairs).to include([:a, 1]) + expect(pairs).to include([:b, 2]) + end + end + + context "when params is a nested hash" do + let(:hash) { {:a => 1, :b => {:c => 2}} } + + it "transforms" do + expect(pairs).to include([:a, 1]) + expect(pairs).to include(["b[c]", 2]) + end + end + + context "when params contains an array" do + let(:hash) { {:a => 1, :b => [2, 3]} } + + context "by default" do + it "transforms" do + expect(pairs).to include([:a, 1]) + expect(pairs).to include(["b[0]", 2]) + expect(pairs).to include(["b[1]", 3]) + end + end + + context "when params_encoding is :rack" do + before { params.params_encoding = :rack } + it "transforms without indexes" do + expect(pairs).to include([:a, 1]) + expect(pairs).to include(["b[]", 2]) + expect(pairs).to include(["b[]", 3]) + end + end + + context "when params_encoding is :none" do + before { params.params_encoding = :none } + it "does no transformation" do + expect(pairs).to include([:a, 1]) + expect(pairs).to include([:b, [2, 3]]) + end + end + end + + context "when params contains something nested in an array" do + context "when string" do + let(:hash) { {:a => {:b => ["hello", "world"]}} } + + it "transforms" do + expect(pairs).to eq([["a[b][0]", "hello"], ["a[b][1]", "world"]]) + end + end + + context "when hash" do + let(:hash) { {:a => {:b => [{:c =>1}, {:d => 2}]}} } + + it "transforms" do + expect(pairs).to eq([["a[b][0][c]", 1], ["a[b][1][d]", 2]]) + end + end + + context "when file" do + let(:file) { File.open("spec/spec_helper.rb") } + let(:file_info) { params.method(:file_info).call(file) } + let(:hash) { {:a => {:b => [file]}} } + let(:mime_type) { file_info[1] } + + it "transforms" do + expect(pairs).to eq([["a[b][0]", file_info]]) + end + + context "when MIME" do + if defined?(MIME) + context "when mime type" do + it "sets mime type to text" do + expect(mime_type).to eq("application/x-ruby") + end + end + end + + context "when no mime type" do + let(:file) { Tempfile.new("fubar") } + + it "sets mime type to default application/octet-stream" do + expect(mime_type).to eq("application/octet-stream") + end + end + end + + context "when no MIME" do + before { hide_const("MIME") } + + it "sets mime type to default application/octet-stream" do + expect(mime_type).to eq("application/octet-stream") + end + end + end + end + + + context "when params contains file" do + let(:file) { Tempfile.new("fubar") } + let(:file_info) { params.method(:file_info).call(file) } + let(:hash) { {:a => 1, :b => file} } + + it "transforms" do + expect(pairs).to include([:a, 1]) + expect(pairs).to include([:b, file_info]) + end + end + + context "when params key contains a null byte" do + let(:hash) { {:a => "1\0" } } + + it "preserves" do + expect(pairs).to eq([[:a, "1\0"]]) + end + end + + context "when params value contains a null byte" do + let(:hash) { {"a\0" => 1 } } + + it "preserves" do + expect(pairs).to eq([["a\0", 1]]) + end + end + end + + describe "#empty?" do + context "when params empty" do + it "returns true" do + expect(params.empty?).to be_truthy + end + end + + context "when params not empty" do + let(:hash) { {:a => 1} } + + it "returns false" do + expect(params.empty?).to be_falsey + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/response_callbacks_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/response_callbacks_spec.rb new file mode 100644 index 000000000..eab1c144a --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/response_callbacks_spec.rb @@ -0,0 +1,151 @@ +require 'spec_helper' + +describe Ethon::Easy::ResponseCallbacks do + let(:easy) { Ethon::Easy.new } + + [:on_complete, :on_headers, :on_body, :on_progress].each do |callback_type| + describe "##{callback_type}" do + it "responds" do + expect(easy).to respond_to("#{callback_type}") + end + + context "when no block given" do + it "returns @#{callback_type}" do + expect(easy.send("#{callback_type}")).to eq([]) + end + end + + context "when block given" do + it "stores" do + easy.send(callback_type) { p 1 } + expect(easy.instance_variable_get("@#{callback_type}").size).to eq(1) + end + end + + context "when multiple blocks given" do + it "stores" do + easy.send(callback_type) { p 1 } + easy.send(callback_type) { p 2 } + expect(easy.instance_variable_get("@#{callback_type}").size).to eq(2) + end + end + end + end + + describe "#complete" do + before do + easy.on_complete {|r| String.new(r.url) } + end + + it "executes blocks and passes self" do + expect(String).to receive(:new).with(easy.url) + easy.complete + end + + context "when @on_complete nil" do + it "doesn't raise" do + easy.instance_variable_set(:@on_complete, nil) + expect{ easy.complete }.to_not raise_error + end + end + end + + describe "#headers" do + before do + easy.on_headers {|r| String.new(r.url) } + end + + it "executes blocks and passes self" do + expect(String).to receive(:new).with(easy.url) + easy.headers + end + + context "when @on_headers nil" do + it "doesn't raise" do + easy.instance_variable_set(:@on_headers, nil) + expect{ easy.headers }.to_not raise_error + end + end + end + + describe "#progress" do + context "when requesting for realz" do + it "executes callback" do + post = Ethon::Easy::Http::Post.new("http://localhost:3001", {:body => "bar=fu"}) + post.setup(easy) + @called = false + @has_dltotal = false + @has_ultotal = false + easy.on_progress { @called = true } + easy.on_progress { |dltotal, _, _, _| @has_dltotal ||= true } + easy.on_progress { |_, _, ultotal, _| @has_ultotal ||= true } + easy.perform + expect(@called).to be true + expect(@has_dltotal).to be true + expect(@has_ultotal).to be true + end + end + + context "when pretending" do + before do + @dltotal = nil + @dlnow = nil + @ultotal = nil + @ulnow = nil + easy.on_progress { |dltotal, dlnow, ultotal, ulnow| @dltotal = dltotal ; @dlnow = dlnow; @ultotal = ultotal; @ulnow = ulnow } + end + + it "executes blocks and passes dltotal" do + easy.progress(1, 2, 3, 4) + expect(@dltotal).to eq(1) + end + + it "executes blocks and passes dlnow" do + easy.progress(1, 2, 3, 4) + expect(@dlnow).to eq(2) + end + + it "executes blocks and passes ultotal" do + easy.progress(1, 2, 3, 4) + expect(@ultotal).to eq(3) + end + + it "executes blocks and passes ulnow" do + easy.progress(1, 2, 3, 4) + expect(@ulnow).to eq(4) + end + + context "when @on_progress nil" do + it "doesn't raise" do + easy.instance_variable_set(:@on_progress, nil) + expect{ easy.progress(1, 2, 3, 4) }.to_not raise_error + end + end + end + end + + describe "#body" do + before do + @chunk = nil + @r = nil + easy.on_body { |chunk, r| @chunk = chunk ; @r = r } + end + + it "executes blocks and passes self" do + easy.body("the chunk") + expect(@r).to be(easy) + end + + it "executes blocks and passes chunk" do + easy.body("the chunk") + expect(@chunk).to eq("the chunk") + end + + context "when @on_body nil" do + it "doesn't raise" do + easy.instance_variable_set(:@on_body, nil) + expect{ easy.body("the chunk") }.to_not raise_error + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy/util_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/util_spec.rb new file mode 100644 index 000000000..24ddef052 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy/util_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe Ethon::Easy::Util do + class Dummy + include Ethon::Easy::Util + end + + let(:klass) { Dummy.new } + + describe "escape_zero_byte" do + context "when value has no zero byte" do + let(:value) { "hello world" } + + it "returns same value" do + expect(klass.escape_zero_byte(value)).to be(value) + end + end + + context "when value has zero byte" do + let(:value) { "hello \0world" } + + it "returns escaped" do + expect(klass.escape_zero_byte(value)).to eq("hello \\0world") + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/easy_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/easy_spec.rb new file mode 100644 index 000000000..619c2edf5 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/easy_spec.rb @@ -0,0 +1,202 @@ +require 'spec_helper' + +describe Ethon::Easy do + let(:easy) { Ethon::Easy.new } + + describe ".new" do + it "inits curl" do + expect(Ethon::Curl).to receive(:init) + easy + end + + context "when options are empty" do + it "sets only callbacks" do + expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks) + expect(Ethon::Easy).to receive(:set_option).never + easy + end + end + + context "when options not empty" do + context "when followlocation is set" do + let(:options) { { :followlocation => true } } + let(:easy) { Ethon::Easy.new(options) } + + it "sets followlocation" do + expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks) + expect(Ethon::Curl).to receive(:set_option).with(:followlocation, true, anything) + easy + end + end + end + end + + describe "#set_attributes" do + context "when options are empty" do + it "sets only callbacks" do + expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks) + expect(Ethon::Easy).to receive(:set_option).never + easy + end + end + + context "when options aren't empty" do + context "when valid key" do + it "sets" do + expect(easy).to receive(:verbose=).with(true) + easy.set_attributes({:verbose => true}) + end + end + + context "when invalid key" do + it "raises invalid option error" do + expect{ easy.set_attributes({:fubar => 1}) }.to raise_error(Ethon::Errors::InvalidOption) + end + end + end + end + + describe "#reset" do + before { easy.url = "www.example.com" } + + it "resets url" do + easy.reset + expect(easy.url).to be_nil + end + + it "resets escape?" do + easy.escape = false + easy.reset + expect(easy.escape?).to be_truthy + end + + it "resets hash" do + easy.reset + expect(easy.instance_variable_get(:@hash)).to be_nil + end + + it "resets easy handle" do + expect(Ethon::Curl).to receive(:easy_reset) + easy.reset + end + + it "resets on_complete" do + easy.on_complete { p 1 } + easy.reset + expect(easy.on_complete).to be_empty + end + + it "resets on_headers" do + easy.on_headers { p 1 } + easy.reset + expect(easy.on_headers).to be_empty + end + + it "resets on_body" do + easy.on_body { p 1 } + easy.reset + expect(easy.on_body).to be_empty + end + end + + describe "#dup" do + let!(:easy) do + easy = Ethon::Easy.new + easy.url = "http://localhost:3001/" + easy.on_complete { 'on_complete' } + easy.on_headers { 'on_headers' } + easy.on_progress { 'on_progress' } + easy.response_body = 'test_body' + easy.response_headers = 'test_headers' + easy + end + let!(:e) { easy.dup } + + it "sets a new handle" do + expect(e.handle).not_to eq(easy.handle) + end + + it "preserves url" do + expect(e.url).to eq(easy.url) + end + + it "preserves on_complete callback" do + expect(e.on_complete).to be(easy.on_complete) + end + + it "preserves on_headers callback" do + expect(e.on_headers).to be(easy.on_headers) + end + + it 'preserves body_write_callback of original handle' do + expect { easy.perform }.to change { easy.response_body } + expect { easy.perform }.not_to change { e.response_body } + end + + it "preserves on_progress callback" do + expect(e.on_progress).to be(easy.on_progress) + end + + it 'sets new body_write_callback of duplicated handle' do + expect { e.perform }.to change { e.response_body } + expect { e.perform }.not_to change { easy.response_body } + end + + it 'preserves headers_write_callback of original handle' do + expect { easy.perform }.to change { easy.response_headers } + expect { easy.perform }.not_to change { e.response_headers } + end + + it 'sets new headers_write_callback of duplicated handle' do + expect { e.perform }.to change { e.response_headers } + expect { e.perform }.not_to change { easy.response_headers } + end + + it "resets response_body" do + expect(e.response_body).to be_empty + end + + it "resets response_headers" do + expect(e.response_headers).to be_empty + end + + it "sets response_body for duplicated Easy" do + e.perform + expect(e.response_body).not_to be_empty + end + + it "sets response_headers for duplicated Easy" do + e.perform + expect(e.response_headers).not_to be_empty + end + + it "preserves response_body for original Easy" do + e.perform + expect(easy.response_body).to eq('test_body') + end + + it "preserves response_headers for original Easy" do + e.perform + expect(easy.response_headers).to eq('test_headers') + end + end + + describe "#mirror" do + it "returns a Mirror" do + expect(easy.mirror).to be_a(Ethon::Easy::Mirror) + end + + it "builds from easy" do + expect(Ethon::Easy::Mirror).to receive(:from_easy).with(easy) + easy.mirror + end + end + + describe "#log_inspect" do + [ :url, :response_code, :return_code, :total_time ].each do |name| + it "contains #{name}" do + expect(easy.log_inspect).to match name.to_s + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/libc_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/libc_spec.rb new file mode 100644 index 000000000..0f8b7d41b --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/libc_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Ethon::Libc do + describe "#getdtablesize", :if => !Ethon::Curl.windows? do + it "returns an integer" do + expect(Ethon::Libc.getdtablesize).to be_a(Integer) + end + + it "returns bigger zero", :if => !Ethon::Curl.windows? do + expect(Ethon::Libc.getdtablesize).to_not be_zero + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/loggable_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/loggable_spec.rb new file mode 100644 index 000000000..c307c247a --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/loggable_spec.rb @@ -0,0 +1,21 @@ +require "spec_helper" + +describe Ethon::Loggable do + + describe "#logger=" do + + let(:logger) do + Logger.new($stdout).tap do |log| + log.level = Logger::INFO + end + end + + before do + Ethon.logger = logger + end + + it "sets the logger" do + expect(Ethon.logger).to eq(logger) + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/multi/operations_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/multi/operations_spec.rb new file mode 100644 index 000000000..f8c04236c --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/multi/operations_spec.rb @@ -0,0 +1,297 @@ +require 'spec_helper' + +describe Ethon::Multi::Operations do + let(:multi) { Ethon::Multi.new } + let(:easy) { Ethon::Easy.new } + let(:pointer) { FFI::MemoryPointer.new(:int) } + + describe "#handle" do + it "returns a pointer" do + expect(multi.handle).to be_a(FFI::Pointer) + end + end + + describe "#running_count" do + context "when hydra has no easy" do + it "returns nil" do + expect(multi.send(:running_count)).to be_nil + end + end + + context "when hydra has easy" do + before do + easy.url = "http://localhost:3001/" + multi.add(easy) + multi.send(:trigger, pointer) + end + + it "returns 1" do + expect(multi.send(:running_count)).to eq(1) + end + end + + context "when hydra has more easys" do + let(:another_easy) { Ethon::Easy.new } + + before do + easy.url = "http://localhost:3001/" + another_easy.url = "http://localhost:3001/" + multi.add(easy) + multi.add(another_easy) + multi.send(:trigger, pointer) + end + + it "returns 2" do + expect(multi.send(:running_count)).to eq(2) + end + end + end + + describe "#get_timeout" do + context "when code ok" do + let(:timeout) { 1 } + + before do + expect(Ethon::Curl).to receive(:multi_timeout).and_return(:ok) + multi.instance_variable_set(:@timeout, double(:read_long => timeout)) + end + + it "doesn't raise" do + expect{ multi.send(:get_timeout) }.to_not raise_error + end + + context "when timeout smaller zero" do + let(:timeout) { -1 } + + it "returns 1" do + expect(multi.send(:get_timeout)).to eq(1) + end + end + + context "when timeout bigger or equal zero" do + let(:timeout) { 2 } + + it "returns timeout" do + expect(multi.send(:get_timeout)).to eq(timeout) + end + end + end + + context "when code not ok" do + before { expect(Ethon::Curl).to receive(:multi_timeout).and_return(:not_ok) } + + it "raises MultiTimeout error" do + expect{ multi.send(:get_timeout) }.to raise_error(Ethon::Errors::MultiTimeout) + end + end + end + + describe "#set_fds" do + let(:timeout) { 1 } + let(:max_fd) { 1 } + + context "when code ok" do + before { expect(Ethon::Curl).to receive(:multi_fdset).and_return(:ok) } + + it "doesn't raise" do + expect{ multi.method(:set_fds).call(timeout) }.to_not raise_error + end + + context "when max_fd -1" do + let(:max_fd) { -1 } + + before do + multi.instance_variable_set(:@max_fd, double(:read_int => max_fd)) + expect(multi).to receive(:sleep).with(0.001) + end + + it "waits 100ms" do + multi.method(:set_fds).call(timeout) + end + end + + context "when max_fd not -1" do + context "when code smaller zero" do + before { expect(Ethon::Curl).to receive(:select).and_return(-1) } + + it "raises Select error" do + expect{ multi.method(:set_fds).call(timeout) }.to raise_error(Ethon::Errors::Select) + end + end + + context "when code bigger or equal zero" do + before { expect(Ethon::Curl).to receive(:select).and_return(0) } + + it "doesn't raise" do + expect{ multi.method(:set_fds).call(timeout) }.to_not raise_error + end + end + end + end + + context "when code not ok" do + before { expect(Ethon::Curl).to receive(:multi_fdset).and_return(:not_ok) } + + it "raises MultiFdset error" do + expect{ multi.method(:set_fds).call(timeout) }.to raise_error(Ethon::Errors::MultiFdset) + end + end + end + + describe "#perform" do + context "when no easy handles" do + it "returns nil" do + expect(multi.perform).to be_nil + end + + it "logs" do + expect(Ethon.logger).to receive(:debug).twice + multi.perform + end + end + + context "when easy handle" do + before do + easy.url = "http://localhost:3001/" + multi.add(easy) + end + + it "requests" do + multi.perform + end + + it "sets easy" do + multi.perform + expect(easy.response_code).to eq(200) + end + end + + context "when four easy handles" do + let(:easies) do + ary = [] + 4.times do + ary << another_easy = Ethon::Easy.new + another_easy.url = "http://localhost:3001/" + end + ary + end + + before do + easies.each { |e| multi.add(e) } + multi.perform + end + + it "sets response codes" do + expect(easies.all?{ |e| e.response_code == 200 }).to be_truthy + end + end + end + + describe "#ongoing?" do + context "when easy_handles" do + before { multi.easy_handles << 1 } + + context "when running_count not greater 0" do + before { multi.instance_variable_set(:@running_count, 0) } + + it "returns true" do + expect(multi.method(:ongoing?).call).to be_truthy + end + end + + context "when running_count greater 0" do + before { multi.instance_variable_set(:@running_count, 1) } + + it "returns true" do + expect(multi.method(:ongoing?).call).to be_truthy + end + end + end + + context "when no easy_handles" do + context "when running_count not greater 0" do + before { multi.instance_variable_set(:@running_count, 0) } + + it "returns false" do + expect(multi.method(:ongoing?).call).to be_falsey + end + end + + context "when running_count greater 0" do + before { multi.instance_variable_set(:@running_count, 1) } + + it "returns true" do + expect(multi.method(:ongoing?).call).to be_truthy + end + end + end + end + + describe "#init_vars" do + it "sets @timeout" do + expect(multi.instance_variable_get(:@timeout)).to be_a(FFI::MemoryPointer) + end + + it "sets @timeval" do + expect(multi.instance_variable_get(:@timeval)).to be_a(Ethon::Curl::Timeval) + end + + it "sets @fd_read" do + expect(multi.instance_variable_get(:@fd_read)).to be_a(Ethon::Curl::FDSet) + end + + it "sets @fd_write" do + expect(multi.instance_variable_get(:@fd_write)).to be_a(Ethon::Curl::FDSet) + end + + it "sets @fd_excep" do + expect(multi.instance_variable_get(:@fd_excep)).to be_a(Ethon::Curl::FDSet) + end + + it "sets @max_fd" do + expect(multi.instance_variable_get(:@max_fd)).to be_a(FFI::MemoryPointer) + end + end + + describe "#reset_fds" do + after { multi.method(:reset_fds).call } + + it "resets @fd_read" do + expect(multi.instance_variable_get(:@fd_read)).to receive(:clear) + end + + it "resets @fd_write" do + expect(multi.instance_variable_get(:@fd_write)).to receive(:clear) + end + + it "resets @fd_excep" do + expect(multi.instance_variable_get(:@fd_excep)).to receive(:clear) + end + end + + describe "#check" do + it { skip("untested") } + end + + describe "#run" do + it { skip("untested") } + end + + describe "#trigger" do + it "calls multi perform" do + expect(Ethon::Curl).to receive(:multi_perform) + multi.send(:trigger, pointer) + end + + it "sets running count" do + multi.instance_variable_set(:@running_count, nil) + multi.send(:trigger, pointer) + expect(multi.instance_variable_get(:@running_count)).to_not be_nil + end + + it "returns multi perform code" do + expect(Ethon::Curl).to receive(:multi_perform).and_return(:ok) + expect(multi.send(:trigger, pointer)).to eq(:ok) + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/multi/options_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/multi/options_spec.rb new file mode 100644 index 000000000..a651a5072 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/multi/options_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe Ethon::Multi::Options do + let(:multi) { Ethon::Multi.new } + + [ + :maxconnects, :pipelining, :socketdata, :socketfunction, + :timerdata, :timerfunction, :max_total_connections + ].each do |name| + describe "#{name}=" do + it "responds_to" do + expect(multi).to respond_to("#{name}=") + end + + it "sets option" do + expect(Ethon::Curl).to receive(:set_option).with(name, anything, anything, anything) + multi.method("#{name}=").call(1) + end + end + end + + describe "#value_for" do + context "when option in bool" do + context "when value true" do + let(:value) { true } + + it "returns 1" do + expect(multi.method(:value_for).call(value, :bool)).to eq(1) + end + end + + context "when value false" do + let(:value) { false } + + it "returns 0" do + expect(multi.method(:value_for).call(value, :bool)).to eq(0) + end + end + end + + + context "when value in int" do + let(:value) { "2" } + + it "returns value casted to int" do + expect(multi.method(:value_for).call(value, :int)).to eq(2) + end + end + + context "when value in unspecific_options" do + context "when value a string" do + let(:value) { "www.example.\0com" } + + it "returns zero byte escaped string" do + expect(multi.method(:value_for).call(value, nil)).to eq("www.example.\\0com") + end + end + + context "when value not a string" do + let(:value) { 1 } + + it "returns value" do + expect(multi.method(:value_for).call(value, nil)).to eq(1) + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/multi/stack_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/multi/stack_spec.rb new file mode 100644 index 000000000..933cfc81e --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/multi/stack_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +describe Ethon::Multi::Stack do + let(:multi) { Ethon::Multi.new } + let(:easy) { Ethon::Easy.new } + + describe "#add" do + context "when easy already added" do + before { multi.add(easy) } + + it "returns nil" do + expect(multi.add(easy)).to be_nil + end + end + + context "when easy new" do + it "adds easy to multi" do + expect(Ethon::Curl).to receive(:multi_add_handle).and_return(:ok) + multi.add(easy) + end + + it "adds easy to easy_handles" do + multi.add(easy) + expect(multi.easy_handles).to include(easy) + end + end + + context "when multi_add_handle fails" do + it "raises multi add error" do + expect(Ethon::Curl).to receive(:multi_add_handle).and_return(:bad_easy_handle) + expect{ multi.add(easy) }.to raise_error(Ethon::Errors::MultiAdd) + end + end + + context "when multi cleaned up before" do + it "raises multi add error" do + Ethon::Curl.multi_cleanup(multi.handle) + expect{ multi.add(easy) }.to raise_error(Ethon::Errors::MultiAdd) + end + end + end + + describe "#delete" do + context "when easy in easy_handles" do + before { multi.add(easy) } + + it "deletes easy from multi" do + expect(Ethon::Curl).to receive(:multi_remove_handle).and_return(:ok) + multi.delete(easy) + end + + it "deletes easy from easy_handles" do + multi.delete(easy) + expect(multi.easy_handles).to_not include(easy) + end + end + + context "when easy is not in easy_handles" do + it "does nothing" do + expect(Ethon::Curl).to receive(:multi_add_handle).and_return(:ok) + multi.add(easy) + end + + it "adds easy to easy_handles" do + multi.add(easy) + expect(multi.easy_handles).to include(easy) + end + end + + context "when multi_remove_handle fails" do + before { multi.add(easy) } + + it "raises multi remove error" do + expect(Ethon::Curl).to receive(:multi_remove_handle).and_return(:bad_easy_handle) + expect{ multi.delete(easy) }.to raise_error(Ethon::Errors::MultiRemove) + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/ethon/multi_spec.rb b/fluentd/vendored_gem_src/ethon/spec/ethon/multi_spec.rb new file mode 100644 index 000000000..7cc3b913c --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/ethon/multi_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Ethon::Multi do + describe ".new" do + it "inits curl" do + expect(Ethon::Curl).to receive(:init) + Ethon::Multi.new + end + + context "when options not empty" do + context "when pipelining is set" do + let(:options) { { :pipelining => true } } + + it "sets pipelining" do + expect_any_instance_of(Ethon::Multi).to receive(:pipelining=).with(true) + Ethon::Multi.new(options) + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/spec_helper.rb b/fluentd/vendored_gem_src/ethon/spec/spec_helper.rb new file mode 100644 index 000000000..e3ab9dc67 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/spec_helper.rb @@ -0,0 +1,27 @@ +$LOAD_PATH.unshift(File.dirname(__FILE__)) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) + +require 'bundler' +Bundler.setup +require "ethon" +require 'rspec' + +if defined? require_relative + require_relative 'support/localhost_server' + require_relative 'support/server' +else + require 'support/localhost_server' + require 'support/server' +end + +# Ethon.logger = Logger.new($stdout).tap do |log| +# log.level = Logger::DEBUG +# end + +RSpec.configure do |config| + # config.order = :rand + + config.before(:suite) do + LocalhostServer.new(TESTSERVER.new, 3001) + end +end diff --git a/fluentd/vendored_gem_src/ethon/spec/support/localhost_server.rb b/fluentd/vendored_gem_src/ethon/spec/support/localhost_server.rb new file mode 100644 index 000000000..c5a7508bc --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/support/localhost_server.rb @@ -0,0 +1,94 @@ +require 'rack' +require 'rack/handler/webrick' +require 'net/http' + +# The code for this is inspired by Capybara's server: +# http://github.com/jnicklas/capybara/blob/0.3.9/lib/capybara/server.rb +class LocalhostServer + READY_MESSAGE = "Server ready" + + class Identify + def initialize(app) + @app = app + end + + def call(env) + if env["PATH_INFO"] == "/__identify__" + [200, {}, [LocalhostServer::READY_MESSAGE]] + else + @app.call(env) + end + end + end + + attr_reader :port + + def initialize(rack_app, port = nil) + @port = port || find_available_port + @rack_app = rack_app + concurrently { boot } + wait_until(10, "Boot failed.") { booted? } + end + + private + + def find_available_port + server = TCPServer.new('127.0.0.1', 0) + server.addr[1] + ensure + server.close if server + end + + def boot + # Use WEBrick since it's part of the ruby standard library and is available on all ruby interpreters. + options = { :Port => port } + options.merge!(:AccessLog => [], :Logger => WEBrick::BasicLog.new(StringIO.new)) unless ENV['VERBOSE_SERVER'] + Rack::Handler::WEBrick.run(Identify.new(@rack_app), options) + end + + def booted? + res = ::Net::HTTP.get_response("localhost", '/__identify__', port) + if res.is_a?(::Net::HTTPSuccess) or res.is_a?(::Net::HTTPRedirection) + return res.body == READY_MESSAGE + end + rescue Errno::ECONNREFUSED, Errno::EBADF + return false + end + + def concurrently + if should_use_subprocess? + pid = Process.fork do + trap(:INT) { ::Rack::Handler::WEBrick.shutdown } + yield + exit # manually exit; otherwise this sub-process will re-run the specs that haven't run yet. + end + + at_exit do + Process.kill('INT', pid) + begin + Process.wait(pid) + rescue Errno::ECHILD + # ignore this error...I think it means the child process has already exited. + end + end + else + Thread.new { yield } + end + end + + def should_use_subprocess? + # !ENV['THREADED'] + false + end + + def wait_until(timeout, error_message, &block) + start_time = Time.now + + while true + return if yield + raise TimeoutError.new(error_message) if (Time.now - start_time) > timeout + sleep(0.05) + end + end +end + diff --git a/fluentd/vendored_gem_src/ethon/spec/support/server.rb b/fluentd/vendored_gem_src/ethon/spec/support/server.rb new file mode 100644 index 000000000..ca5ab9be8 --- /dev/null +++ b/fluentd/vendored_gem_src/ethon/spec/support/server.rb @@ -0,0 +1,114 @@ +#!/usr/bin/env ruby +require 'json' +require 'zlib' +require 'sinatra/base' + +TESTSERVER = Sinatra.new do + set :logging, nil + + fail_count = 0 + + post '/file' do + { + 'content-type' => params[:file][:type], + 'filename' => params[:file][:filename], + 'content' => params[:file][:tempfile].read, + 'request-content-type' => request.env['CONTENT_TYPE'] + }.to_json + end + + get '/multiple-headers' do + [200, { 'Set-Cookie' => %w[ foo bar ], 'Content-Type' => 'text/plain' }, ['']] + end + + get '/fail/:number' do + if fail_count >= params[:number].to_i + "ok" + else + fail_count += 1 + error 500, "oh noes!" + end + end + + get '/fail_forever' do + error 500, "oh noes!" + end + + get '/redirect' do + redirect '/' + end + + post '/redirect' do + redirect '/' + end + + get '/bad_redirect' do + redirect '/bad_redirect' + end + + get '/auth_basic/:username/:password' do + @auth ||= Rack::Auth::Basic::Request.new(request.env) + # Check that we've got a basic auth, and that it's credentials match the ones + # provided in the request + if @auth.provided? && @auth.basic? && @auth.credentials == [ params[:username], params[:password] ] + # auth is valid - confirm it + true + else + # invalid auth - request the authentication + response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth") + throw(:halt, [401, "Not authorized\n"]) + end + end + + get '/auth_ntlm' do + # we're just checking for the existence if NTLM auth header here. It's validation + # is too troublesome and really doesn't bother is much, it's up to libcurl to make + # it valid + response['WWW-Authenticate'] = 'NTLM' + is_ntlm_auth = /^NTLM/ =~ request.env['HTTP_AUTHORIZATION'] + true if is_ntlm_auth + throw(:halt, [401, "Not authorized\n"]) if !is_ntlm_auth + end + + get '/gzipped' do + req_env = request.env.to_json + z = Zlib::Deflate.new + gzipped_env = z.deflate(req_env, Zlib::FINISH) + z.close + response['Content-Encoding'] = 'gzip' + gzipped_env + end + + get '/**' do + sleep params["delay"].to_i if params.has_key?("delay") + request.env.merge!(:body => request.body.read).to_json + end + + head '/**' do + sleep params["delay"].to_i if params.has_key?("delay") + end + + put '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + post '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + delete '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + patch '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + options '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + route 'PURGE', '/**' do + request.env.merge!(:body => request.body.read).to_json + end +end diff --git a/fluentd/vendored_gem_src/syslog_protocol/Gemfile b/fluentd/vendored_gem_src/syslog_protocol/Gemfile new file mode 100644 index 000000000..e45e65f87 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/Gemfile @@ -0,0 +1,2 @@ +source :rubygems +gemspec diff --git a/fluentd/vendored_gem_src/syslog_protocol/README.md b/fluentd/vendored_gem_src/syslog_protocol/README.md new file mode 100644 index 000000000..c0c658f41 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/README.md @@ -0,0 +1,84 @@ +# Syslog protocol + +roughly conforms to the murky shade of grey known as http://www.faqs.org/rfcs/rfc3164.html + +## Examples + +### Manipulate packets manually + + require 'syslog_protocol' + + p = SyslogProtocol::Packet.new + p.hostname = "space_station" + p.facility = "kern" + p.severity = "warn" + p.tag = "test" + p.content = "flight control broken" + p.to_s + # => "<4>Aug 1 14:01:17 space_station flight control broken" + p.pri + # => 4 + p.facility + # => 0 + p.facility_name + # => "kern" + p.severity_name + # => "warn" + p.warn? + # => true + p.info? + # => false + + +### Use a Logger to generate packets + + require 'syslog_protocol' + + logger = SyslogProtocol::Logger.new("space_station", "uucp") + logger.debug("looking for uucp on board the space station") + # => "<67>Aug 1 14:02:29 space_station looking for uucp on board the space station" + logger.emerg("omg we cant find uucp on the space station") + # => "<64>Aug 1 14:03:56 space_station omg we cant find uucp on the space station" + + +### Parse packets + + require 'syslog_protocol' + + p = SyslogProtocol.parse("<34>Oct 11 22:14:15 space_station space is really getting to me") + p.facility + # => 4 + p.severity_name + # => "crit" + p.time + # => Sun Oct 11 22:14:15 -0700 2009 + p.content + # => "space is really getting to me" + + +### It yells at you for trying to abuse the protocol + + p = SyslogProtocol::Packet.new + p.facility = 34534534 + # => ArgumentError: Facility must be within 0-23 + p.hostname = "my host" + # => ArgumentError: Hostname may not contain spaces + p.hostname = "h\000stname" + # => ArgumentError: Hostname may only contain ASCII characters 33-126 + # ...etc. + # It will also unintelligently truncate messages > 1024 bytes so beware. + + +## Caveats + +Syslog is a terrible and loosely defined protocol. Many devices and programs do not +conform to it and so their packets may not be parsed correctly by this interpretation, +nor may the packets generated by this necessarily be recognized by other devices or programs ;) + +This is probably wrong and buggy, and i know the code is ugly, thanks. + +Good luck. + +## TODO + +* Update to more closely map to the ruby `syslog` API where possible diff --git a/fluentd/vendored_gem_src/syslog_protocol/Rakefile b/fluentd/vendored_gem_src/syslog_protocol/Rakefile new file mode 100644 index 000000000..d4f7da839 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/Rakefile @@ -0,0 +1,150 @@ +require 'rubygems' +require 'rake' +require 'date' + +############################################################################# +# +# Helper functions +# +############################################################################# + +def name + @name ||= Dir['*.gemspec'].first.split('.').first +end + +def version + line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/] + line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1] +end + +def date + Date.today.to_s +end + +def rubyforge_project + name +end + +def gemspec_file + "#{name}.gemspec" +end + +def gem_file + "#{name}-#{version}.gem" +end + +def replace_header(head, header_name) + head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"} +end + +############################################################################# +# +# Standard tasks +# +############################################################################# + +task :default => :test + +require 'rake/testtask' +Rake::TestTask.new(:test) do |test| + test.libs << 'lib' << 'test' + test.pattern = 'test/**/test_*.rb' + test.verbose = true +end + +desc "Generate RCov test coverage and open in your browser" +task :coverage do + require 'rcov' + sh "rm -fr coverage" + sh "rcov test/test_*.rb" + sh "open coverage/index.html" +end + +require 'rake/rdoctask' +Rake::RDocTask.new do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = "#{name} #{version}" + rdoc.rdoc_files.include('README*') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +desc "Open an irb session preloaded with this library" +task :console do + sh "irb -rubygems -r ./lib/#{name}.rb" +end + +############################################################################# +# +# Custom tasks (add your own tasks here) +# +############################################################################# + + + +############################################################################# +# +# Packaging tasks +# +############################################################################# + +desc "Create tag v#{version} and build and push #{gem_file} to Rubygems" +task :release => :build do + unless `git branch` =~ /^\* master$/ + puts "You must be on the master branch to release!" + exit! + end + sh "git commit --allow-empty -a -m 'Release #{version}'" + sh "git tag v#{version}" + sh "git push origin master" + sh "git push origin v#{version}" + sh "gem push pkg/#{name}-#{version}.gem" +end + +desc "Build #{gem_file} into the pkg directory" +task :build => :gemspec do + sh "mkdir -p pkg" + sh "gem build #{gemspec_file}" + sh "mv #{gem_file} pkg" +end + +desc "Generate #{gemspec_file}" +task :gemspec => :validate do + # read spec file and split out manifest section + spec = File.read(gemspec_file) + head, manifest, tail = spec.split(" # = MANIFEST =\n") + + # replace name version and date + replace_header(head, :name) + replace_header(head, :version) + replace_header(head, :date) + #comment this out if your rubyforge_project has a different name + replace_header(head, :rubyforge_project) + + # determine file list from git ls-files + files = `git ls-files`. + split("\n"). + sort. + reject { |file| file =~ /^\./ }. + reject { |file| file =~ /^(rdoc|pkg)/ }. + map { |file| " #{file}" }. + join("\n") + + # piece file back together and write + manifest = " s.files = %w[\n#{files}\n ]\n" + spec = [head, manifest, tail].join(" # = MANIFEST =\n") + File.open(gemspec_file, 'w') { |io| io.write(spec) } + puts "Updated #{gemspec_file}" +end + +desc "Validate #{gemspec_file}" +task :validate do + libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"] + unless libfiles.empty? + puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir." + exit! + end + unless Dir['VERSION*'].empty? + puts "A `VERSION` file at root level violates Gem best practices." + exit! + end +end diff --git a/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol.rb b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol.rb new file mode 100644 index 000000000..965c40e44 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol.rb @@ -0,0 +1,8 @@ +require 'syslog_protocol/common' +require 'syslog_protocol/packet' +require 'syslog_protocol/logger' +require 'syslog_protocol/parser' + +module SyslogProtocol + VERSION = '0.9.2' +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/common.rb b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/common.rb new file mode 100644 index 000000000..045d3658b --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/common.rb @@ -0,0 +1,79 @@ +module SyslogProtocol + # These hashes stolen from Syslog.pm + + FACILITIES = { + 'kern' => 0, + 'user' => 1, + 'mail' => 2, + 'daemon' => 3, + 'auth' => 4, + 'syslog' => 5, + 'lpr' => 6, + 'news' => 7, + 'uucp' => 8, + 'cron' => 9, + 'authpriv' => 10, + 'ftp' => 11, + 'ntp' => 12, + 'audit' => 13, + 'alert' => 14, + 'at' => 15, + 'local0' => 16, + 'local1' => 17, + 'local2' => 18, + 'local3' => 19, + 'local4' => 20, + 'local5' => 21, + 'local6' => 22, + 'local7' => 23 + } + + FACILITY_INDEX = { + 0 => 'kern', + 1 => 'user', + 2 => 'mail', + 3 => 'daemon', + 4 => 'auth', + 5 => 'syslog', + 6 => 'lpr', + 7 => 'news', + 8 => 'uucp', + 9 => 'cron', + 10 => 'authpriv', + 11 => 'ftp', + 12 => 'ntp', + 13 => 'audit', + 14 => 'alert', + 15 => 'at', + 16 => 'local0', + 17 => 'local1', + 18 => 'local2', + 19 => 'local3', + 20 => 'local4', + 21 => 'local5', + 22 => 'local6', + 23 => 'local7' + } + + SEVERITIES = { + 'emerg' => 0, + 'alert' => 1, + 'crit' => 2, + 'err' => 3, + 'warn' => 4, + 'notice' => 5, + 'info' => 6, + 'debug' => 7 + } + + SEVERITY_INDEX = { + 0 => 'emerg', + 1 => 'alert', + 2 => 'crit', + 3 => 'err', + 4 => 'warn', + 5 => 'notice', + 6 => 'info', + 7 => 'debug' + } +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/logger.rb b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/logger.rb new file mode 100644 index 000000000..6d4801ffe --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/logger.rb @@ -0,0 +1,21 @@ +module SyslogProtocol + class Logger + def initialize(hostname, tag, facility) + @packet = Packet.new + @packet.hostname = hostname + @packet.tag = tag + @packet.facility = facility + end + + SEVERITIES.each do |k,v| + define_method(k) do |content| + raise ArgumentError.new("Message may not be omitted") unless content and content.length > 0 + + p = @packet.dup + p.severity = k + p.content = content + p.assemble + end + end + end +end diff --git a/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/packet.rb b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/packet.rb new file mode 100644 index 000000000..20dae9227 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/packet.rb @@ -0,0 +1,135 @@ +module SyslogProtocol + class Packet + attr_reader :facility, :severity, :hostname, :tag + attr_accessor :time, :content + + def to_s + assemble + end + + def assemble(max_size = 1024) + unless @hostname and @facility and @severity and @tag + raise "Could not assemble packet without hostname, tag, facility, and severity" + end + data = "<#{pri}>#{generate_timestamp} #{@hostname} #{@tag}: #{@content}" + + if string_bytesize(data) > max_size + data = data.slice(0, max_size) + while string_bytesize(data) > max_size + data = data.slice(0, data.length - 1) + end + end + + data + end + + def facility=(f) + if f.is_a? Integer + if (0..23).include?(f) + @facility = f + else + raise ArgumentError.new "Facility must be within 0-23" + end + elsif f.is_a? String + if facility = FACILITIES[f] + @facility = facility + else + raise ArgumentError.new "'#{f}' is not a designated facility" + end + else + raise ArgumentError.new "Facility must be a designated number or string" + end + end + + def tag=(t) + unless t && t.is_a?(String) && t.length > 0 + raise ArgumentError, "Tag must not be omitted" + end + if t.length > 32 + raise ArgumentError, "Tag must not be longer than 32 characters" + end + if t =~ /\s/ + raise ArgumentError, "Tag may not contain spaces" + end + if t =~ /[^\x21-\x7E]/ + raise ArgumentError, "Tag may only contain ASCII characters 33-126" + end + + @tag = t + end + + def severity=(s) + if s.is_a? Integer + if (0..7).include?(s) + @severity = s + else + raise ArgumentError.new "Severity must be within 0-7" + end + elsif s.is_a? String + if severity = SEVERITIES[s] + @severity = severity + else + raise ArgumentError.new "'#{s}' is not a designated severity" + end + else + raise ArgumentError.new "Severity must be a designated number or string" + end + end + + def hostname=(h) + unless h and h.is_a? String and h.length > 0 + raise ArgumentError.new("Hostname may not be omitted") + end + if h =~ /\s/ + raise ArgumentError.new("Hostname may not contain spaces") + end + if h =~ /[^\x21-\x7E]/ + raise ArgumentError.new("Hostname may only contain ASCII characters 33-126") + end + @hostname = h + end + + def facility_name + FACILITY_INDEX[@facility] + end + + def severity_name + SEVERITY_INDEX[@severity] + end + + def pri + (@facility * 8) + @severity + end + + def pri=(p) + unless p.is_a? Integer and (0..191).include?(p) + raise ArgumentError.new "PRI must be a number between 0 and 191" + end + @facility = p / 8 + @severity = p - (@facility * 8) + end + + def generate_timestamp + time = @time || Time.now + # The timestamp format requires that a day with fewer than 2 digits have + # what would normally be a preceding zero, be instead an extra space. + day = time.strftime("%d") + day = day.sub(/^0/, ' ') if day =~ /^0\d/ + time.strftime("%b #{day} %H:%M:%S") + end + + if "".respond_to?(:bytesize) + def string_bytesize(string) + string.bytesize + end + else + def string_bytesize(string) + string.length + end + end + + SEVERITIES.each do |k,v| + define_method("#{k}?") { SEVERITIES[k] == @severity } + end + end +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/parser.rb b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/parser.rb new file mode 100644 index 000000000..a5f7db1b7 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/lib/syslog_protocol/parser.rb @@ -0,0 +1,57 @@ +require 'time' + +module SyslogProtocol + + def self.parse(msg, origin=nil) + packet = Packet.new + original_msg = msg.dup + pri = parse_pri(msg) + if pri and (pri = pri.to_i).is_a? Integer and (0..191).include?(pri) + packet.pri = pri + else + # If there isn't a valid PRI, treat the entire message as content + packet.pri = 13 + packet.time = Time.now + packet.hostname = origin || 'unknown' + packet.content = original_msg + return packet + end + time = parse_time(msg) + if time + packet.time = Time.parse(time) + else + packet.time = Time.now + end + hostname = parse_hostname(msg) + packet.hostname = hostname || origin + if m = msg.match(/^(\w+)(: | )(.*)$/) + packet.tag = m[1] + packet.content = m[3] + else + packet.tag = 'unknown' + packet.content = msg + end + packet + end + + private + + def self.parse_pri(msg) + pri = msg.slice!(/<(\d\d?\d?)>/) + pri = pri.slice(/\d\d?\d?/) if pri + if !pri or (pri =~ /^0/ and pri !~ /^0$/) + return nil + else + return pri + end + end + + def self.parse_time(msg) + msg.slice!(/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\s|[1-9])\d\s\d\d:\d\d:\d\d\s/) + end + + def self.parse_hostname(msg) + msg.slice!(/^[\x21-\x7E]+\s/).rstrip + end + +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/syslog_protocol.gemspec b/fluentd/vendored_gem_src/syslog_protocol/syslog_protocol.gemspec new file mode 100644 index 000000000..90a3e8b3e --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/syslog_protocol.gemspec @@ -0,0 +1,81 @@ +## This is the rakegem gemspec template. Make sure you read and understand +## all of the comments. Some sections require modification, and others can +## be deleted if you don't need them. Once you understand the contents of +## this file, feel free to delete any comments that begin with two hash marks. +## You can find comprehensive Gem::Specification documentation, at +## http://docs.rubygems.org/read/chapter/20 +Gem::Specification.new do |s| + s.specification_version = 2 if s.respond_to? :specification_version= + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.rubygems_version = '1.3.5' + + ## Leave these as is they will be modified for you by the rake gemspec task. + ## If your rubyforge_project name is different, then edit it and comment out + ## the sub! line in the Rakefile + s.name = 'syslog_protocol' + s.version = '0.9.2' + s.date = "2009-08-01" + # s.rubyforge_project = 'syslog_protocol' + + ## Make sure your summary is short. The description may be as long + ## as you like. + s.summary = "Syslog protocol parser and generator" + s.description = "Syslog protocol parser and generator" + + ## List the primary authors. If there are a bunch of authors, it's probably + ## better to set the email to an email list or something. If you don't have + ## a custom homepage, consider using your GitHub URL or the like. + s.authors = ["Jake Douglas", 'Eric Lindvall'] + s.email = [ "jakecdouglas@gmail.com", 'eric@5stops.com' ] + s.homepage = 'https://github.com/eric/syslog_protocol' + + ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as + ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb' + s.require_paths = %w[lib] + + ## This sections is only necessary if you have C extensions. + # s.require_paths << 'ext' + # s.extensions = %w[ext/extconf.rb] + + ## If your gem includes any executables, list them here. + # s.executables = ["name"] + # s.default_executable = 'name' + + ## Specify any RDoc options here. You'll want to add your README and + ## LICENSE files to the extra_rdoc_files list. + s.rdoc_options = ["--charset=UTF-8"] + s.extra_rdoc_files = %w[README.md] + + ## List your runtime dependencies here. Runtime dependencies are those + ## that are needed for an end user to actually USE your code. + # s.add_dependency('DEPNAME', [">= 1.1.0", "< 2.0.0"]) + + ## List your development dependencies here. Development dependencies are + ## those that are only needed during development + s.add_development_dependency('bacon', [ '~> 1.1.0' ]) + + ## Leave this section as-is. It will be automatically generated from the + ## contents of your Git repository via the gemspec task. DO NOT REMOVE + ## THE MANIFEST COMMENTS, they are used as delimiters by the task. + # = MANIFEST = + s.files = %w[ + Gemfile + README.md + Rakefile + lib/syslog_protocol.rb + lib/syslog_protocol/common.rb + lib/syslog_protocol/logger.rb + lib/syslog_protocol/packet.rb + lib/syslog_protocol/parser.rb + syslog_protocol.gemspec + test/helper.rb + test/test_logger.rb + test/test_packet.rb + test/test_parser.rb + ] + # = MANIFEST = + + ## Test files will be grabbed from the file list. Make sure the path glob + ## matches what you actually use. + s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ } +end diff --git a/fluentd/vendored_gem_src/syslog_protocol/test/helper.rb b/fluentd/vendored_gem_src/syslog_protocol/test/helper.rb new file mode 100644 index 000000000..2469737e5 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/test/helper.rb @@ -0,0 +1,13 @@ +$:.unshift File.expand_path('../../lib', __FILE__) + +unless ENV['BUNDLE_GEMFILE'] + require 'rubygems' + require 'bundler' + Bundler.setup + Bundler.require +end + +require 'bacon' +Bacon.summary_at_exit + +require 'syslog_protocol' \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/test/test_logger.rb b/fluentd/vendored_gem_src/syslog_protocol/test/test_logger.rb new file mode 100644 index 000000000..96226d42c --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/test/test_logger.rb @@ -0,0 +1,28 @@ +require File.expand_path('../helper', __FILE__) + +describe "syslog logger" do + + it "create a new logger with hostname and facility" do + lambda {@logger = SyslogProtocol::Logger.new("space_station", 'test', "local0")}.should.not.raise + end + + it "hostname and facility must conform to the requirements of a Packet" do + lambda {SyslogProtocol::Logger.new("space station", "some shit", 'test test')}.should.raise ArgumentError + end + + it "generates packets" do + # We have to set a time so we have a consistant timestamp to check against.. + p = @logger.instance_variable_get("@packet") + p.time = Time.now + ts = p.generate_timestamp + @logger.debug("vacuum tubez are operational").should.equal "<135>#{ts} space_station test: vacuum tubez are operational" + @logger.info("firing thrusters at 13 degrees").should.equal "<134>#{ts} space_station test: firing thrusters at 13 degrees" + @logger.notice("the hyper drive has been activated").should.equal "<133>#{ts} space_station test: the hyper drive has been activated" + @logger.warn("meteorites incoming!").should.equal "<132>#{ts} space_station test: meteorites incoming!" + @logger.err("vacuum tube 3 in hyper drive failed").should.equal "<131>#{ts} space_station test: vacuum tube 3 in hyper drive failed" + @logger.crit("wing struck by a meteorite!").should.equal "<130>#{ts} space_station test: wing struck by a meteorite!" + @logger.alert("LEAKING ATMOSPHERE").should.equal "<129>#{ts} space_station test: LEAKING ATMOSPHERE" + @logger.emerg("LEAKING ASTRONAUTS WE ARE DONE").should.equal "<128>#{ts} space_station test: LEAKING ASTRONAUTS WE ARE DONE" + end + +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/test/test_packet.rb b/fluentd/vendored_gem_src/syslog_protocol/test/test_packet.rb new file mode 100644 index 000000000..d5117550f --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/test/test_packet.rb @@ -0,0 +1,96 @@ +require File.expand_path('../helper', __FILE__) + +describe "a syslog packet" do + + @p = SyslogProtocol::Packet.new + + it "should embarrass a person who does not set the fields" do + lambda { @p.to_s }.should.raise RuntimeError + end + + it "hostname may not be omitted" do + lambda {@p.hostname = ""}.should.raise ArgumentError + end + + it "hostname may only contain ASCII characters 33-126 (no spaces!)" do + lambda {@p.hostname = "linux box"}.should.raise ArgumentError + lambda {@p.hostname = "\000" + "linuxbox"}.should.raise ArgumentError + lambda {@p.hostname = "space_station"}.should.not.raise + end + + it 'tag may only contain ASCII characters 33-126 (no spaces!)' do + lambda {@p.tag = "linux box"}.should.raise ArgumentError + lambda {@p.tag = "\000" + "linuxbox"}.should.raise ArgumentError + lambda {@p.tag = "test"}.should.not.raise + end + + it "facility may only be set within 0-23 or with a proper string name" do + lambda {@p.facility = 666}.should.raise ArgumentError + lambda {@p.facility = "mir space station"}.should.raise ArgumentError + + lambda {@p.facility = 16}.should.not.raise + @p.facility.should.equal 16 + lambda {@p.facility = 'local0'}.should.not.raise + @p.facility.should.equal 16 + end + + it "severity may only be set within 0-7 or with a proper string name" do + lambda {@p.severity = 9876}.should.raise ArgumentError + lambda {@p.severity = "omgbroken"}.should.raise ArgumentError + + lambda {@p.severity = 6}.should.not.raise + @p.severity.should.equal 6 + lambda {@p.severity = 'info'}.should.not.raise + @p.severity.should.equal 6 + end + + it "severity can be checked using 'some_severity?' methods" do + @p.info?.should.equal true + @p.alert?.should.equal false + @p.emerg?.should.equal false + end + + it "PRI is calculated from the facility and severity" do + @p.pri.should.equal 134 + end + + it "PRI may only be within 0-191" do + lambda {@p.pri = 22331}.should.raise ArgumentError + lambda {@p.pri = "foo"}.should.raise ArgumentError + end + + it "facility and severity are deduced and set from setting a valid PRI" do + @p.pri = 165 + @p.severity.should.equal 5 + @p.facility.should.equal 20 + end + + it "return the proper names for facility and severity" do + @p.severity_name.should.equal 'notice' + @p.facility_name.should.equal 'local4' + end + + it "set a message, which apparently can be anything" do + @p.content = "exploring ze black hole" + @p.content.should.equal "exploring ze black hole" + end + + it "timestamp must conform to the retarded format" do + @p.generate_timestamp.should.match /(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\s|[1-9])\d\s\d\d:\d\d:\d\d/ + end + + it "use the current time and assemble the packet" do + timestamp = @p.generate_timestamp + @p.to_s.should.equal "<165>#{timestamp} space_station test: exploring ze black hole" + end + + it "packets larger than 1024 will be truncated" do + @p.content = "space warp" * 1000 + if "".respond_to?(:bytesize) + @p.to_s.bytesize.should.equal 1024 + else + @p.to_s.size.should.equal 1024 + end + end + +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/syslog_protocol/test/test_parser.rb b/fluentd/vendored_gem_src/syslog_protocol/test/test_parser.rb new file mode 100644 index 000000000..a03b5e659 --- /dev/null +++ b/fluentd/vendored_gem_src/syslog_protocol/test/test_parser.rb @@ -0,0 +1,51 @@ +require File.expand_path('../helper', __FILE__) + +describe "syslog packet parser" do + + it "parse some valid packets" do + p = SyslogProtocol.parse("<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8") + p.facility.should.equal 4 + p.severity.should.equal 2 + p.pri.should.equal 34 + p.hostname.should.equal "mymachine" + p.tag.should.equal 'su' + p.content.should.equal "'su root' failed for lonvick on /dev/pts/8" + p.time.should.equal Time.parse("Oct 11 22:14:15") + + p = SyslogProtocol.parse("<13>Feb 5 17:32:18 10.0.0.99 test: Use the BFG!") + p.facility.should.equal 1 + p.severity.should.equal 5 + p.pri.should.equal 13 + p.hostname.should.equal "10.0.0.99" + p.tag.should.equal 'test' + p.content.should.equal "Use the BFG!" + p.time.should.equal Time.parse("Feb 5 17:32:18") + end + + it "treat a packet with no valid PRI as all content, setting defaults" do + p = SyslogProtocol.parse("nomnom") + p.facility.should.equal 1 + p.severity.should.equal 5 + p.pri.should.equal 13 + p.hostname.should.equal 'unknown' + p.content.should.equal "nomnom" + end + + it "PRI with preceding 0's shall be considered invalid" do + p = SyslogProtocol.parse("<045>Oct 11 22:14:15 space_station my PRI is not valid") + p.facility.should.equal 1 + p.severity.should.equal 5 + p.pri.should.equal 13 + p.hostname.should.equal 'unknown' + p.content.should.equal "<045>Oct 11 22:14:15 space_station my PRI is not valid" + end + + it "allow the user to pass an origin to be used as the hostname if packet is invalid" do + p = SyslogProtocol.parse("<045>Oct 11 22:14:15 space_station my PRI is not valid", '127.0.0.1') + p.facility.should.equal 1 + p.severity.should.equal 5 + p.pri.should.equal 13 + p.hostname.should.equal '127.0.0.1' + p.content.should.equal "<045>Oct 11 22:14:15 space_station my PRI is not valid" + end +end \ No newline at end of file diff --git a/fluentd/vendored_gem_src/typhoeus/.rspec b/fluentd/vendored_gem_src/typhoeus/.rspec new file mode 100644 index 000000000..838fd5743 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/.rspec @@ -0,0 +1,4 @@ +--tty +--color +--format documentation +--backtrace diff --git a/fluentd/vendored_gem_src/typhoeus/.travis.yml b/fluentd/vendored_gem_src/typhoeus/.travis.yml new file mode 100644 index 000000000..dc0c9df00 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/.travis.yml @@ -0,0 +1,26 @@ +language: ruby +script: "bundle exec rake" +rvm: + - 1.9.3 + - 2.0.0 + - 2.1.10 + - 2.2.10 + - 2.3.8 + - 2.4.7 + - 2.5.6 + - 2.6.4 + - ruby-head + - jruby-head + - jruby-18mode + - jruby-19mode +matrix: + fast_finish: true + allow_failures: + - rvm: ruby-head + - rvm: jruby-head + - rvm: ree + include: + - rvm: 1.8.7 + dist: precise + - rvm: 1.9.2 + dist: trusty diff --git a/fluentd/vendored_gem_src/typhoeus/CHANGELOG.md b/fluentd/vendored_gem_src/typhoeus/CHANGELOG.md new file mode 100644 index 000000000..223e4bc79 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/CHANGELOG.md @@ -0,0 +1,406 @@ +# Changelog + +## Master + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.4.0...master) + +## 1.4.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.1.2...v1.4.0) + +#### 1 feature +- Faraday adapter exceptions namespace compatibility with Faraday v1 ([@iMacTia](https://github.com/iMacTia) in [#616](https://github.com/typhoeus/typhoeus/pull/616)) + +#### 3 Others +- Yard warning fixes ([@olleolleolle](https://github.com/olleolleolle) in [#622](https://github.com/typhoeus/typhoeus/pull/622)) +- Add more Ruby versions in CI matrix ([@olleolleolle](https://github.com/olleolleolle) in [#623](https://github.com/typhoeus/typhoeus/pull/623)) +- Use of argument passed in function instead of `attr_reader` ([@v-kolesnikov](https://github.com/v-kolesnikov) in [#625](https://github.com/typhoeus/typhoeus/pull/625)) + +## 1.1.2 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.1.1...v1.1.2) + +## 1.1.1 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.1.0...v1.1.1) + +## 1.1.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.0.2...v1.1.0) + +* Unless specified `Expect` header is set to be empty to avoid `100 continue` + to be set when using `PUT` +* Add global config option `Typhoeus::Config.proxy` + +## 1.0.2 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.0.1...v1.0.2) + +## 1.0.1 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.0.0...v1.0.1) + +## 1.0.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.8.0...v1.0.0) + +## 0.8.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.7.3...v0.8.0) + +* `EasyFactory`: Reduced object allocations and method calls during deprecated + option handling and option sanitization. + ([Tasos Laskos](https://github.com/zapotek)) +* `Response` ([Tasos Laskos](https://github.com/zapotek)) + * `Header` + * `#process_pair`: Halved `#set_value` calls. + * `#set_value`: Minimized `Hash` accesses. + * `#parse`: Use `String#start_with?` instead of `Regexp` match. + * `#process_line`: Optimized key/value sanitization. + * `Status` + * `#timed_out?`: Only return `true` when `#return_code` is `operation_timedout`. + +## 0.7.3 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.7.2...v0.7.3) + +* Add on_body callbacks individually to allow Ethon to recognize the return code + +## 0.7.2 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.7.1...v0.7.2) + +* Allow arrays to be passed to Expectation#and_return + ([JP Moral](https://github.com/jpmoral)) + +* Added getter for `redirect_time` value. + ([Adrien Jarthon](https://github.com/jarthod)) + +## 0.7.1 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.7.0...v0.7.1) + +Bugfixes: + +* Forking may cause libcurl sockets to be shared with child processes, causing HTTP requests to be interleaved + ([Rolf Timmermans](https://github.com/rolftimmermans), [\#436](https://github.com/typhoeus/typhoeus/pull/426)) + +## 0.7.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.7.0.pre1...v0.7.0) + +Bugfixes: + +* Call on_headers and on_body when using stubbed responses. + +## 0.7.0.pre1 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.9...v0.7.0.pre1) + +Enhancements: + +* Improving timeout behavior and documentation. `no_signal` is now set per default! + ([Jonas Wagner](https://github.com/jwagner), [\#398](https://github.com/typhoeus/typhoeus/pull/398)) + +## 0.6.8 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.7...v0.6.8) + +Bugfixes: + +* Fix Faraday 0.9 compatibility. + ([Gleb Mazovetskiy](https://github.com/glebm), [\#357](https://github.com/typhoeus/typhoeus/pull/357)) +* Fix Request#hash for different key orders. + ([Matthew Schulkind](https://github.com/mschulkind), [\#344](https://github.com/typhoeus/typhoeus/pull/344)) + +Enhancements: + +* Use an updated Ethon version. Note that from now on the `mime-types` is no longer a Ethon dependency. The gem will be still used if available to determine the mime type of a file which is uploaded. That means you have to have take care of the gem installation yourself. +* Use SVG for status badges in README. + ([Sean Linsley](https://github.com/seanlinsley), [\#353](https://github.com/typhoeus/typhoeus/pull/353)) +* Missing quotes in README example code. + ([Jason R. Clark](https://github.com/jasonrclark), [\#351](https://github.com/typhoeus/typhoeus/pull/351)) +* Specs for Faraday adapter. + ([michaelavila](https://github.com/michaelavila), [\#348](https://github.com/typhoeus/typhoeus/pull/348)) +* Clarify wording in README. + ([Sean Linsley](https://github.com/seanlinsley), [\#347](https://github.com/typhoeus/typhoeus/pull/347)) +* Make caching easier for non-memory caches. + ([Matthew Schulkind](https://github.com/mschulkind), [\#345](https://github.com/typhoeus/typhoeus/pull/345)) +* Spec refactoring. + ([Matthew Schulkind](https://github.com/mschulkind), [\#343](https://github.com/typhoeus/typhoeus/pull/343)) + +## 0.6.7 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.6...v0.6.7) + +Enhancements: + +* Add response streaming. + ([\#339](https://github.com/typhoeus/typhoeus/pull/339)) + +## 0.6.6 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.5...v0.6.6) + +## 0.6.5 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.4...v0.6.5) + +## 0.6.4 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.3...v0.6.4) + +The changelog entries are coming soon! + +## 0.6.3 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.2...v0.6.3) + +Enhancements: + +* Cache hydra per thread. +* Various documentation improvements. + ([craiglittle](https://github.com/craiglittle)) +* Add support for lazy construction of responses from stubbed requests. + ([ryankindermann](https://github.com/ryankinderman), [\#275](https://github.com/typhoeus/typhoeus/pull/275)) + +## 0.6.2 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.1...v0.6.2) + +Enhancements: + +* Reintroduce a global cache. +* `Request#handled_response` falls back to the original response. + ([turnerking](https://github.com/turnerking), [\#272](https://github.com/typhoeus/typhoeus/pull/272)) +* When `Errors::NoStub` is raised the `url` is displayed. + ([dschneider](https://github.com/dschneider), [\#276](https://github.com/typhoeus/typhoeus/pull/276)) +* Make `Request#hash` consistent. +* Add `.rvmrc` and `ctags` to `.gitignore`. + ([ryankindermann](https://github.com/ryankinderman), [\#274](https://github.com/typhoeus/typhoeus/pull/274)) + +## 0.6.1 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.0...v0.6.1) + +Enhancements: + +* Updated ethon version which allows to set multiple protocols. + +## 0.6.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.4...v0.6.0) + +Enhancements: + +* `Request#url` now also contains the url parameters. +* Use updated ethon version which provides access to protocols and redir_protocols in response to [libcurl SASL buffer overflow vulnerability](http://curl.haxx.se/docs/adv_20130206.html) + +Bugfixes: + +* Corrected ssl options for the faraday adapter. +* The before hook now correctly returns the response. + ([Mattias Putman](https://github.com/challengee), [\#268](https://github.com/typhoeus/typhoeus/pull/268)) +* Benchmark is working again. + +## 0.5.4 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.3...v0.5.4) + +Enhancements: + +* Make sure response_code is an integer. +* When setting an header through vcr or webmock it becomes a `Typhoeus::Response::Header`. +* Provide a Rack middleware to decode nested Typhoeus arrays properly. + ([Dwayne Macgowan](https://github.com/dwaynemac), [\#224](https://github.com/typhoeus/typhoeus/issues/224)) +* Handled response is available again. +* Rename parameter `url` to `base_url`. See discussion here: [\#250](https://github.com/typhoeus/typhoeus/issues/250). + ([bkimble](https://github.com/bkimble), [\#256](https://github.com/typhoeus/typhoeus/pull/256)) +* Provide O(1) header access. + * Work around ruby 1.8.7 limitations. + ([Chris Johnson](https://github.com/findchris), [\#227](https://github.com/typhoeus/typhoeus/pull/227) ) + * Provide symbol access. + +## 0.5.3 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.2...v0.5.3) + +Enhancements: + +* When checking options in Expecation#matches? also consider Request#options. + +Bugfixes: + +* Do not break backwards compatibility with case insensitive headers access. +* Make sure hydra behaves correct in case of before hooks. + +## 0.5.2 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.1...v0.5.2) + +Enhancements: + +* Do not check the return_code in Response#success? when response is mocked. +* Check for memoization, stubbing, before hooks are delayed to Hydra#run. It + was on Hydra#queue before and led to strange behavior because if the request + was stubbed, it was wrapped up in queue already. There was no way to add + callbacks after queue thatswhy. This is now different, since everything happens + in run, just as you expect. + +## 0.5.1 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.0...v0.5.1) + +Enhancements: + +* Downcase header keys for easier access + ( [\#227](https://github.com/typhoeus/typhoeus/issues/227) ) +* Using an updated Ethon version. + +## 0.5.0 + +[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.4.2...v0.5.0) + +Major Changes: + +* Ethon integration + * Params are url params and a body is always a body for every request type + * The options you can set might have a slightly other names, as Ethon sticks to + libcurl names. See + [Easy.new](http://rubydoc.info/github/typhoeus/ethon/Ethon/Easy#initialize-instance_method) + for a description. + * Request parameter and body are properly encoded (only POST multiform body is not) + * No more header sanitizing. Before: `:headers => { 'user_agent' => 'Custom' }` was modified to + `:headers => { 'User-Agent' => 'Custom' }` + * `Typhoeus::Easy` and `Typhoeus::Multi` are now `Ethon::Easy` and `Ethon::Multi` + +* Request shortcuts: `Typhoeus.get("www.google.de")` +* Global configuration: +```ruby +Typhoeus.configure do |config| + config.verbose = true + config.memoize = true +end +``` +* No more `Response#headers_hash`, instead `Response#headers` returning the last + header and response#redirections returning the responses with headers + generated through redirections +* Instead of defining the same callbacks on every request, you can define global callbacks: +```ruby +Typhoeus.on_complete { p "yay" } +``` +* The stubbing interface changed slightly. You now have the same syntax as for requests: +```ruby +Typhoeus.stub(url, options).and_return(response) +``` +* The following things were removed because they do not seemed to be used at all. Ping me if you disagree! + * `Typhoeus::Filter` + * `Typhoeus::Remote` + * `Typhoeus::RemoteMethod` + * `Typhoeus::RemoteProxyObject` + * build in cache interface + +Enhancements: + +* Documentation + ( [Alex P](https://github.com/ifesdjeen), [\#188](https://github.com/typhoeus/typhoeus/issues/188) ) +* Request#on\_complete can hold multiple blocks. +* Request#eql? recognizes when header/params/body has a different order, but still same keys and values + ( [Alex P](https://github.com/ifesdjeen), [\#194](https://github.com/typhoeus/typhoeus/issues/194) ) + +Bug Fixes: + +* Zero bytes in strings are escaped for libcurl +* Add support for socks5 hostname proxy type + ( [eweathers](https://github.com/eweathers), [\#183](https://github.com/typhoeus/typhoeus/issues/183) ) +* Post body is encoded + ( [Rohan Deshpande](https://github.com/rdeshpande), [\#143](https://github.com/typhoeus/typhoeus/issues/143) ) +* Set default user agent + ( [Steven Shingler](https://github.com/sshingler), [\#176](https://github.com/typhoeus/typhoeus/issues/176) ) + +## 0.4.2 +* A header hotfix + +## 0.4.1 +* Fix verifypeer and verifyhost options +* Fix header sending + +## 0.4.0 +* Make a GET even when a body is given +* Deprecated User Agent setter removed +* Allow cache key basis overwrite (John Crepezzi, #147) +* FFI integration (Daniel Cavanagh, #151) +* Refactor upload code (Marnen Laibow-Koser, #152) +* Fix travis-ci build (Ezekiel Templin, #160) + +## 0.3.3 +* Make sure to call the Easy::failure callback on all non-success http response codes, even invalid ones. [balexis] +* Use bytesize instead of length to determine Content-Length [dlamacchia] +* Added SSL version option to Easy/Request [michelbarbosa/dbalatero] + +## 0.3.2 +* Fix array params to be consistent with HTTP spec [gridaphobe] +* traversal\_to\_params\_hash should use the escape option [itsmeduncan] +* Fix > 1024 open file descriptors [mschulkind] +* Fixed a bug with internally queued requests being dropped [mschulkind] +* Use gemspec in bundler to avoid duplication [mschulkind] +* Run internally queued requests in FIFO order [mschulkind] +* Moved Typhoeus::VERSION to a separate file, to fix rake build\_native [mschulkind] +* Fixed problems related to put requests with empty bodies [skaes, GH-84] +* Added CURLOPT\_INTERFACE option via Request#interface=. [spiegela] +* Added Tempfile support to Form#process! [richievos] +* Hydra won't forget to accept gzip/deflate encoding [codesnik] +* Accept and convert strings to integers in Typhoeus::Request#initialize for timeout/cache\_timeout/connect\_timeout values when using ruby 1.9.x. [djnawara] +* Added interface for registering stub finders [myronmarston] +* Fixed header stubbing [myronmarston] +* Added PKCS12 support [jodell] +* Make a request with handlers marshallable [bernerdschaefer] +* Upgraded to RSpec 2 [bernerdschaefer] +* Fix HTTP status edge-case [balexis] +* Expose primary\_ip to easy object [balexis] + +## 0.2.4 +* Fix form POSTs to only use multipart for file uploads, otherwise use application/x-www-form-urlencoded [dbalatero] + +## 0.2.3 +* Code duplication in Typhoeus::Form led to nested URL param errors on POST only. Fixed [dbalatero] + +## 0.2.2 +* Fixed a problem with nested URL params encoding incorrectly [dbalatero] + +## 0.2.1 +* Added extended proxy support [Zapotek, GH-46] +* eliminated compile time warnings by using proper type declarations [skaes, GH-54] +* fixed broken calls to rb\_raise [skaes, GH-54] +* prevent leaking of curl easy handles when exceptions are raised (either from typhoeus itself or user callbacks) [skaes, GH-54] +* fixed Easy#timed\_out? using curl return codes [skaes, GH-54] +* provide curl return codes and corresponding curl error messages on classes Easy and Request [skaes, GH-54] +* allow VCR to whitelist hosts in Typhoeus stubbing/mocking [myronmarston, GH-57] +* added timed\_out? documentation, method to Response [dbalatero, GH-34] +* added abort to Hydra to prematurely stop a hydra.run [Zapotek] +* added file upload support for POST requests [jtarchie, GH-59] + +## 0.2.0 +* Fix warning in Request#headers from attr\_accessor +* Params with array values were not parsing into the format that rack expects [GH-39, smartocci] +* Removed Rack as a dependency [GH-45] +* Added integration hooks for VCR! + +## 0.1.31 +* Fixed bug in setting compression encoding [morhekil] +* Exposed authentication control methods through Request interface [morhekil] + +## 0.1.30 +* Exposed CURLOPT\_CONNECTTIMEOUT\_MS to Requests [balexis] + +## 0.1.29 +* Fixed a memory corruption with using CURLOPT\_POSTFIELDS [gravis, +32531d0821aecc4] + +## 0.1.28 +* Added SSL cert options for Typhoeus::Easy [GH-25, gravis] +* Ported SSL cert options to Typhoeus::Request interface [gravis] +* Added support for any HTTP method (purge for Varnish) [ryana] + +## 0.1.27 +* Added rack as dependency, added dev dependencies to Rakefile [GH-21] diff --git a/fluentd/vendored_gem_src/typhoeus/CONTRIBUTING.md b/fluentd/vendored_gem_src/typhoeus/CONTRIBUTING.md new file mode 100644 index 000000000..667e8a32e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/CONTRIBUTING.md @@ -0,0 +1,20 @@ +We love pull requests. Here's a quick guide: + +1. Fork the repo. + +2. Run the tests. We only take pull requests with passing tests, and it's great +to know that you have a clean slate: `bundle && bundle exec rake` + +3. Add a test for your change. Only refactoring and documentation changes +require no new tests. If you are adding functionality or fixing a bug, we need +a test! + +4. Make the test pass. + +5. Push to your fork and submit a pull request. + +And in case we didn't emphasize it enough: we love tests! + +## Issue triage [![Open Source Helpers](https://www.codetriage.com/typhoeus/typhoeus/badges/users.svg)](https://www.codetriage.com/typhoeus/typhoeus) + +You can contribute by triaging issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to typhoeus on CodeTriage](https://www.codetriage.com/typhoeus/typhoeus). diff --git a/fluentd/vendored_gem_src/typhoeus/Gemfile b/fluentd/vendored_gem_src/typhoeus/Gemfile new file mode 100644 index 000000000..dd662d708 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/Gemfile @@ -0,0 +1,32 @@ +source "https://rubygems.org" +gemspec + +if Gem.ruby_version < Gem::Version.new("2.0.0") + gem "rake", "< 11" + gem "json", "< 2" +else + gem "json" + gem "rake" +end + +group :development, :test do + gem "rspec", "~> 3.0" + + gem "sinatra", "~> 1.3" + + if Gem.ruby_version >= Gem::Version.new("1.9.0") + gem "faraday", ">= 0.9" + gem "dalli", "~> 2.0" + end + + gem "redis", "~> 3.0" + + if RUBY_PLATFORM == "java" + gem "spoon" + end + + unless ENV["CI"] + gem "guard-rspec", "~> 0.7" + gem 'rb-fsevent', '~> 0.9.1' + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/Guardfile b/fluentd/vendored_gem_src/typhoeus/Guardfile new file mode 100644 index 000000000..f0db2992b --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/Guardfile @@ -0,0 +1,9 @@ +# vim:set filetype=ruby: +guard( + "rspec", + all_after_pass: false, + cli: "--fail-fast --tty --format documentation --colour") do + + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |match| "spec/#{match[1]}_spec.rb" } +end diff --git a/fluentd/vendored_gem_src/typhoeus/LICENSE b/fluentd/vendored_gem_src/typhoeus/LICENSE new file mode 100644 index 000000000..387fac572 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2010 Paul Dix +Copyright (c) 2011 David Balatero +Copyright (c) 2012-2016 Hans Hasselberg + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/fluentd/vendored_gem_src/typhoeus/README.md b/fluentd/vendored_gem_src/typhoeus/README.md new file mode 100644 index 000000000..1bbab54a0 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/README.md @@ -0,0 +1,584 @@ +# Typhoeus [![Build Status](https://img.shields.io/travis/typhoeus/typhoeus/master.svg)](https://travis-ci.org/typhoeus/typhoeus) [![Code Climate](https://img.shields.io/codeclimate/maintainability/typhoeus/typhoeus.svg)](https://codeclimate.com/github/typhoeus/typhoeus) [![Gem Version](https://img.shields.io/gem/v/typhoeus.svg)](https://rubygems.org/gems/typhoeus) + +Like a modern code version of the mythical beast with 100 serpent heads, Typhoeus runs HTTP requests in parallel while cleanly encapsulating handling logic. + +## Example + +A single request: + +```ruby +Typhoeus.get("www.example.com", followlocation: true) +``` + +Parallel requests: + +```ruby +hydra = Typhoeus::Hydra.new +10.times.map{ hydra.queue(Typhoeus::Request.new("www.example.com", followlocation: true)) } +hydra.run +``` + +## Installation +Add the following line to your Gemfile: +``` +gem "typhoeus" +``` +Then run `bundle install` + +Or install it yourself as: + +``` +gem install typhoeus +``` + +## Project Tracking + +* [Documentation](http://rubydoc.info/github/typhoeus/typhoeus/frames/Typhoeus) (GitHub master) +* [Mailing list](http://groups.google.com/group/typhoeus) + +## Usage + +### Introduction + +The primary interface for Typhoeus is comprised of three classes: Request, Response, and Hydra. Request represents an HTTP request object, response represents an HTTP response, and Hydra manages making parallel HTTP connections. + +```ruby +request = Typhoeus::Request.new( + "www.example.com", + method: :post, + body: "this is a request body", + params: { field1: "a field" }, + headers: { Accept: "text/html" } +) +``` + +We can see from this that the first argument is the url. The second is a set of options. +The options are all optional. The default for `:method` is `:get`. + +When you want to send URL parameters, you can use `:params` hash to do so. Please note that in case of you should send a request via `x-www-form-urlencoded` parameters, you need to use `:body` hash instead. `params` are for URL parameters and `:body` is for the request body. + +#### Sending requests through the proxy + +Add a proxy url to the list of options: + +```ruby +options = {proxy: 'http://myproxy.org'} +req = Typhoeus::Request.new(url, options) +``` + +If your proxy requires authentication, add it with `proxyuserpwd` option key: + +```ruby +options = {proxy: 'http://proxyurl.com', proxyuserpwd: 'user:password'} +req = Typhoeus::Request.new(url, options) +``` + +Note that `proxyuserpwd` is a colon-separated username and password, in the vein of basic auth `userpwd` option. + + +You can run the query either on its own or through the hydra: + +``` ruby +request.run +#=> +``` + +```ruby +hydra = Typhoeus::Hydra.hydra +hydra.queue(request) +hydra.run +``` + +The response object will be set after the request is run. + +```ruby +response = request.response +response.code +response.total_time +response.headers +response.body +``` + +### Making Quick Requests + +Typhoeus has some convenience methods for performing single HTTP requests. The arguments are the same as those you pass into the request constructor. + +```ruby +Typhoeus.get("www.example.com") +Typhoeus.head("www.example.com") +Typhoeus.put("www.example.com/posts/1", body: "whoo, a body") +Typhoeus.patch("www.example.com/posts/1", body: "a new body") +Typhoeus.post("www.example.com/posts", body: { title: "test post", content: "this is my test"}) +Typhoeus.delete("www.example.com/posts/1") +Typhoeus.options("www.example.com") +``` +#### Sending params in the body with PUT +When using POST the content-type is set automatically to 'application/x-www-form-urlencoded'. That's not the case for any other method like PUT, PATCH, HEAD and so on, irrespective of whether you are using body or not. To get the same result as POST, i.e. a hash in the body coming through as params in the receiver, you need to set the content-type as shown below: +```ruby +Typhoeus.put("www.example.com/posts/1", + headers: {'Content-Type'=> "application/x-www-form-urlencoded"}, + body: {title:"test post updated title", content: "this is my updated content"} + ) +``` + +### Handling HTTP errors + +You can query the response object to figure out if you had a successful +request or not. Here’s some example code that you might use to handle errors. +The callbacks are executed right after the request is finished, make sure to define +them before running the request. + +```ruby +request = Typhoeus::Request.new("www.example.com", followlocation: true) + +request.on_complete do |response| + if response.success? + # hell yeah + elsif response.timed_out? + # aw hell no + log("got a time out") + elsif response.code == 0 + # Could not get an http response, something's wrong. + log(response.return_message) + else + # Received a non-successful http response. + log("HTTP request failed: " + response.code.to_s) + end +end + +request.run +``` + +This also works with serial (blocking) requests in the same fashion. Both +serial and parallel requests return a Response object. + +### Handling file uploads + +A File object can be passed as a param for a POST request to handle uploading +files to the server. Typhoeus will upload the file as the original file name +and use Mime::Types to set the content type. + +```ruby +Typhoeus.post( + "http://localhost:3000/posts", + body: { + title: "test post", + content: "this is my test", + file: File.open("thesis.txt","r") + } +) +``` + +### Streaming the response body + +Typhoeus can stream responses. When you're expecting a large response, +set the `on_body` callback on a request. Typhoeus will yield to the callback +with chunks of the response, as they're read. When you set an `on_body` callback, +Typhoeus will not store the complete response. + +```ruby +downloaded_file = File.open 'huge.iso', 'wb' +request = Typhoeus::Request.new("www.example.com/huge.iso") +request.on_headers do |response| + if response.code != 200 + raise "Request failed" + end +end +request.on_body do |chunk| + downloaded_file.write(chunk) +end +request.on_complete do |response| + downloaded_file.close + # Note that response.body is "" +end +request.run +``` + +If you need to interrupt the stream halfway, +you can return the `:abort` symbol from the `on_body` block, example: + +```ruby +request.on_body do |chunk| + buffer << chunk + :abort if buffer.size > 1024 * 1024 +end +``` + +This will properly stop the stream internally and avoid any memory leak which +may happen if you interrupt with something like a `return`, `throw` or `raise`. + +### Making Parallel Requests + +Generally, you should be running requests through hydra. Here is how that looks: + +```ruby +hydra = Typhoeus::Hydra.hydra + +first_request = Typhoeus::Request.new("http://example.com/posts/1") +first_request.on_complete do |response| + third_url = response.body + third_request = Typhoeus::Request.new(third_url) + hydra.queue third_request +end +second_request = Typhoeus::Request.new("http://example.com/posts/2") + +hydra.queue first_request +hydra.queue second_request +hydra.run # this is a blocking call that returns once all requests are complete +``` + +The execution of that code goes something like this. The first and second requests are built and queued. When hydra is run the first and second requests run in parallel. When the first request completes, the third request is then built and queued, in this example based on the result of the first request. The moment it is queued Hydra starts executing it. Meanwhile the second request would continue to run (or it could have completed before the first). Once the third request is done, `hydra.run` returns. + +How to get an array of response bodies back after executing a queue: + +```ruby +hydra = Typhoeus::Hydra.new +requests = 10.times.map { + request = Typhoeus::Request.new("www.example.com", followlocation: true) + hydra.queue(request) + request +} +hydra.run + +responses = requests.map { |request| + request.response.body +} +``` +`hydra.run` is a blocking request. You can also use the `on_complete` callback to handle each request as it completes: + +```ruby +hydra = Typhoeus::Hydra.new +10.times do + request = Typhoeus::Request.new("www.example.com", followlocation: true) + request.on_complete do |response| + #do_something_with response + end + hydra.queue(request) +end +hydra.run +``` + +### Making Parallel Requests with Faraday + Typhoeus + +```ruby +require 'faraday' + +conn = Faraday.new(:url => 'http://httppage.com') do |builder| + builder.request :url_encoded + builder.response :logger + builder.adapter :typhoeus +end + +conn.in_parallel do + response1 = conn.get('/first') + response2 = conn.get('/second') + + # these will return nil here since the + # requests have not been completed + response1.body + response2.body +end + +# after it has been completed the response information is fully available +# response1.status, etc +response1.body +response2.body +``` + +### Specifying Max Concurrency + +Hydra will also handle how many requests you can make in parallel. Things will get flakey if you try to make too many requests at the same time. The built in limit is 200. When more requests than that are queued up, hydra will save them for later and start the requests as others are finished. You can raise or lower the concurrency limit through the Hydra constructor. + +```ruby +Typhoeus::Hydra.new(max_concurrency: 20) +``` + +### Memoization + +Hydra memoizes requests within a single run call. You have to enable memoization. +This will result in a single request being issued. However, the on_complete handlers of both will be called. + +```ruby +Typhoeus::Config.memoize = true + +hydra = Typhoeus::Hydra.new(max_concurrency: 1) +2.times do + hydra.queue Typhoeus::Request.new("www.example.com") +end +hydra.run +``` + +This will result in two requests. + +```ruby +Typhoeus::Config.memoize = false + +hydra = Typhoeus::Hydra.new(max_concurrency: 1) +2.times do + hydra.queue Typhoeus::Request.new("www.example.com") +end +hydra.run +``` + +### Caching + +Typhoeus includes built in support for caching. In the following example, if there is a cache hit, the cached object is passed to the on_complete handler of the request object. + +```ruby +class Cache + def initialize + @memory = {} + end + + def get(request) + @memory[request] + end + + def set(request, response) + @memory[request] = response + end +end + +Typhoeus::Config.cache = Cache.new + +Typhoeus.get("www.example.com").cached? +#=> false +Typhoeus.get("www.example.com").cached? +#=> true +``` + +For use with [Dalli](https://github.com/mperham/dalli): + +```ruby +dalli = Dalli::Client.new(...) +Typhoeus::Config.cache = Typhoeus::Cache::Dalli.new(dalli) +``` + +For use with Rails: + +```ruby +Typhoeus::Config.cache = Typhoeus::Cache::Rails.new +``` + +For use with [Redis](https://github.com/redis/redis-rb): + +```ruby +redis = Redis.new(...) +Typhoeus::Config.cache = Typhoeus::Cache::Redis.new(redis) +``` + +All three of these adapters take an optional keyword argument `default_ttl`, which sets a default +TTL on cached responses (in seconds), for requests which do not have a cache TTL set. + +You may also selectively choose not to cache by setting `cache` to `false` on a request or to use +a different adapter. + +```ruby +cache = Cache.new +Typhoeus.get("www.example.com", cache: cache) +``` + +### Direct Stubbing + +Hydra allows you to stub out specific urls and patterns to avoid hitting +remote servers while testing. + +```ruby +response = Typhoeus::Response.new(code: 200, body: "{'name' : 'paul'}") +Typhoeus.stub('www.example.com').and_return(response) + +Typhoeus.get("www.example.com") == response +#=> true +``` + +The queued request will hit the stub. You can also specify a regex to match urls. + +```ruby +response = Typhoeus::Response.new(code: 200, body: "{'name' : 'paul'}") +Typhoeus.stub(/example/).and_return(response) + +Typhoeus.get("www.example.com") == response +#=> true +``` + +You may also specify an array for the stub to return sequentially. + +```ruby +Typhoeus.stub('www.example.com').and_return([response1, response2]) + +Typhoeus.get('www.example.com') == response1 #=> true +Typhoeus.get('www.example.com') == response2 #=> true +``` + +When testing make sure to clear your expectations or the stubs will persist between tests. The following can be included in your spec_helper.rb file to do this automatically. + +```ruby +RSpec.configure do |config| + config.before :each do + Typhoeus::Expectation.clear + end +end +``` + +### Timeouts + +No exceptions are raised on HTTP timeouts. You can check whether a request timed out with the following method: + +```ruby +Typhoeus.get("www.example.com", timeout: 1).timed_out? +``` + +Timed out responses also have their success? method return false. + +There are two different timeouts available: [`timeout`](http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTTIMEOUT) +and [`connecttimeout`](http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTCONNECTTIMEOUT). +`timeout` is the time limit for the entire request in seconds. +`connecttimeout` is the time limit for just the connection phase, again in seconds. + +There are two additional more fine grained options `timeout_ms` and +`connecttimeout_ms`. These options offer millisecond precision but are not always available (for instance on linux if `nosignal` is not set to true). + +When you pass a floating point `timeout` (or `connecttimeout`) Typhoeus will set `timeout_ms` for you if it has not been defined. The actual timeout values passed to curl will always be rounded up. + +DNS timeouts of less than one second are not supported unless curl is compiled with an asynchronous resolver. + +The default `timeout` is 0 (zero) which means curl never times out during transfer. The default `connecttimeout` is 300 seconds. A `connecttimeout` of 0 will also result in the default `connecttimeout` of 300 seconds. + +### Following Redirections + +Use `followlocation: true`, eg: + +```ruby +Typhoeus.get("www.example.com", followlocation: true) +``` + +### Basic Authentication + +```ruby +Typhoeus::Request.get("www.example.com", userpwd: "user:password") +``` + +### Compression + +```ruby +Typhoeus.get("www.example.com", accept_encoding: "gzip") +``` + +The above has a different behavior than setting the header directly in the header hash, eg: +```ruby +Typhoeus.get("www.example.com", headers: {"Accept-Encoding" => "gzip"}) +``` + +Setting the header hash directly will not include the `--compressed` flag in the libcurl command and therefore libcurl will not decompress the response. If you want the `--compressed` flag to be added automatically, set `:accept_encoding` Typhoeus option. + + +### Cookies + +```ruby +Typhoeus::Request.get("www.example.com", cookiefile: "/path/to/file", cookiejar: "/path/to/file") +``` + +Here, `cookiefile` is a file to read cookies from, and `cookiejar` is a file to write received cookies to. +If you just want cookies enabled, you need to pass the same filename for both options. + +### Other CURL options + +Are available and documented [here](http://rubydoc.info/github/typhoeus/ethon/Ethon/Easy/Options) + +### SSL + +SSL comes built in to libcurl so it’s in Typhoeus as well. If you pass in a +url with "https" it should just work assuming that you have your [cert +bundle](http://curl.haxx.se/docs/caextract.html) in order and the server is +verifiable. You must also have libcurl built with SSL support enabled. You can +check that by doing this: + +``` +curl --version +``` + +Now, even if you have libcurl built with OpenSSL you may still have a messed +up cert bundle or if you’re hitting a non-verifiable SSL server then you’ll +have to disable peer verification to make SSL work. Like this: + +```ruby +Typhoeus.get("https://www.example.com", ssl_verifypeer: false) +``` + +If you are getting "SSL: certificate subject name does not match target host +name" from curl (ex:- you are trying to access to b.c.host.com when the +certificate subject is \*.host.com). You can disable host verification. Like +this: + +```ruby +# host checking enabled +Typhoeus.get("https://www.example.com", ssl_verifyhost: 2) +# host checking disabled +Typhoeus.get("https://www.example.com", ssl_verifyhost: 0) +``` + +### Verbose debug output + +It’s sometimes useful to see verbose output from curl. You can enable it on a per-request basis: + +```ruby +Typhoeus.get("http://example.com", verbose: true) +``` + +or globally: + +```ruby +Typhoeus::Config.verbose = true +``` + +Just remember that libcurl prints it’s debug output to the console (to +STDERR), so you’ll need to run your scripts from the console to see it. + +### Default User Agent Header + +In many cases, all HTTP requests made by an application require the same User-Agent header set. Instead of supplying it on a per-request basis by supplying a custom header, it is possible to override it for all requests using: + + +```ruby +Typhoeus::Config.user_agent = "custom user agent" +``` + +### Running the specs + +Running the specs should be as easy as: + +``` +bundle install +bundle exec rake +``` +## Semantic Versioning + +This project conforms to [semver](http://semver.org/). + +## LICENSE + +(The MIT License) + +Copyright © 2009-2010 [Paul Dix](http://www.pauldix.net/) + +Copyright © 2011-2012 [David Balatero](https://github.com/dbalatero/) + +Copyright © 2012-2016 [Hans Hasselberg](http://github.com/i0rek/) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/fluentd/vendored_gem_src/typhoeus/Rakefile b/fluentd/vendored_gem_src/typhoeus/Rakefile new file mode 100644 index 000000000..d5693a5df --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/Rakefile @@ -0,0 +1,38 @@ +require "bundler" +Bundler.setup + +require "rake" +require "rspec/core/rake_task" +$LOAD_PATH.unshift File.expand_path("../lib", __FILE__) +require "typhoeus/version" + +task :gem => :build +task :build do + system "gem build typhoeus.gemspec" +end + +task :install => :build do + system "gem install typhoeus-#{Typhoeus::VERSION}.gem" +end + +task :release => :build do + system "git tag -a v#{Typhoeus::VERSION} -m 'Tagging #{Typhoeus::VERSION}'" + system "git push --tags" + system "gem push typhoeus-#{Typhoeus::VERSION}.gem" +end + +RSpec::Core::RakeTask.new(:spec) do |t| + t.verbose = false + t.ruby_opts = "-W -I./spec -rspec_helper" +end + +desc "Start up the test servers" +task :start do + require_relative 'spec/support/boot' + begin + Boot.start_servers(:rake) + rescue Exception + end +end + +task :default => :spec diff --git a/fluentd/vendored_gem_src/typhoeus/UPGRADE.md b/fluentd/vendored_gem_src/typhoeus/UPGRADE.md new file mode 100644 index 000000000..28c7f1d2e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/UPGRADE.md @@ -0,0 +1,55 @@ +# Upgrade guide + +## 0.5 + +### Options + +Fix the option names, because some were renamed. The errors should point you in the right direction: + +```ruby +Typhoeus.get("www.example.com", follow_location: true) +# Ethon::Errors::InvalidOption: The option: follow_location is invalid. +# Please try followlocation instead of follow_location. +# ... [Backtrace] + +Typhoeus.get("www.example.com", followlocation: true).code +#=> 200 +``` + +### Headers + +`Response#headers` returns a hash now and replaces `Response#headers_hash`, use `Response#response_headers` for the raw string: + +```ruby +Typhoeus.get("www.example.com", followlocation: true).headers +#=> { +# "date"=>"Tue, 06 Nov 2012 09:07:27 GMT", +# "server"=>"Apache/2.2.3 (CentOS)", +# "last-modified"=>"Wed, 09 Feb 2011 17:13:15 GMT", +# "vary"=>"Accept-Encoding", +# "connection"=>"close", +# "content-type"=>"text/html; charset=UTF-8" +# } + +Typhoeus.get("www.example.com", followlocation: true).response_headers +#=> "HTTP/1.0 302 Found\r\nLocation: http://www.iana.org/domains/example/ [...]" +``` + +### Params vs body + +Make sure every request sends proper params and body (especially POST/PUT). `:params` becomes url parameter and `:body` request body. Before params for POST was smashed into the body. + +### Configuration + +Create a global configuration in case you want to turn on verbose, memoize or block_connection: + +```ruby +Typhoeus.configure do |config| + config.verbose = true + config.memoize = true +end +``` + +### Docs + +When in doubt, read the [docs](http://rubydoc.info/github/typhoeus/typhoeus/frames/Typhoeus) or the [code](https://www.github.com/typhoeus). diff --git a/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus.rb b/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus.rb new file mode 100644 index 000000000..dd9361170 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus.rb @@ -0,0 +1 @@ +require "rack/typhoeus/middleware/params_decoder" diff --git a/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder.rb b/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder.rb new file mode 100644 index 000000000..cbd10f38e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder.rb @@ -0,0 +1,57 @@ +require 'rack/typhoeus/middleware/params_decoder/helper' + +module Rack + module Typhoeus + module Middleware + + # This Rack middleware takes care of the proper deserialization of + # the nested params encoded by Typhoeus. + # + # @example Require the railtie when using Rails. + # require 'typhoeus/railtie' + # + # @example Include the middleware for Rack based applications. + # use Rack::Typhoeus::Middleware::ParamsDecoder + # + # @example Use the helper directly. Not recommended as b/c the interface might change. + # require 'rack/typhoeus/middleware/params_decoder/helper' + # include Rack::Typhoeus::Middleware::ParamsDecoder::Helper + # decode!(params) + # + # @author Dwayne Macgowan + # @since 0.5.4 + class ParamsDecoder + include ParamsDecoder::Helper + + def initialize(app) + @app = app + end + + def call(env) + req = Rack::Request.new(env) + decode(req.params).each_pair { |k, v| update_params req, k, v } + @app.call(env) + end + + private + + # Persist params change in environment. Extracted from: + # https://github.com/rack/rack/blob/master/lib/rack/request.rb#L243 + def update_params(req, k, v) + found = false + if req.GET.has_key?(k) + found = true + req.GET[k] = v + end + if req.POST.has_key?(k) + found = true + req.POST[k] = v + end + unless found + req.GET[k] = v + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder/helper.rb b/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder/helper.rb new file mode 100644 index 000000000..0542328aa --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/rack/typhoeus/middleware/params_decoder/helper.rb @@ -0,0 +1,76 @@ +module Rack + module Typhoeus + module Middleware + class ParamsDecoder + module Helper + + # Recursively decodes Typhoeus encoded arrays in given Hash. + # + # @example Use directly in a Rails controller. + # class ApplicationController + # before_filter :decode_typhoeus_arrays + # end + # + # @author Dwayne Macgowan + # + def decode_typhoeus_arrays + decode!(params) + end + + # Recursively decodes Typhoeus encoded arrays in given Hash. + # + # @param hash [Hash]. This Hash will be modified! + # + # @return [Hash] Hash with properly decoded nested arrays. + def decode!(hash) + return hash unless hash.is_a?(Hash) + hash.each_pair do |key,value| + if value.is_a?(Hash) + decode!(value) + hash[key] = convert(value) + end + end + hash + end + + def decode(hash) + decode!(hash.dup) + end + + private + + # Checks if Hash is an Array encoded as a Hash. + # Specifically will check for the Hash to have this + # form: {'0' => v0, '1' => v1, .., 'n' => vN } + # + # @param hash [Hash] + # + # @return [Boolean] True if its a encoded Array, else false. + def encoded?(hash) + return false if hash.empty? + if hash.keys.size > 1 + keys = hash.keys.map{|i| i.to_i if i.respond_to?(:to_i)}.sort + keys == hash.keys.size.times.to_a + else + hash.keys.first =~ /0/ + end + end + + # If the Hash is an array encoded by typhoeus an array is returned + # else the self is returned + # + # @param hash [Hash] The Hash to convert into an Array. + # + # @return [Arraya/Hash] + def convert(hash) + if encoded?(hash) + hash.sort{ |a, b| a[0].to_i <=> b[0].to_i }.map{ |key, value| value } + else + hash + end + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus.rb new file mode 100644 index 000000000..1e2226a2e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus.rb @@ -0,0 +1,143 @@ +require 'digest/sha2' +require 'ethon' + +require 'typhoeus/config' +require 'typhoeus/easy_factory' +require 'typhoeus/errors' +require 'typhoeus/expectation' +require 'typhoeus/hydra' +require 'typhoeus/pool' +require 'typhoeus/request' +require 'typhoeus/response' +require 'typhoeus/version' + +# If we are using any Rack-based application, then we need the Typhoeus rack +# middleware to ensure our app is running properly. +if defined?(Rack) + require "rack/typhoeus" +end + +# If the Redis gem is available, load the redis cache adapter +if defined?(Redis) + require "typhoeus/cache/redis" +end + +# If the Dalli gem is available, load the Dalli cache adapter +if defined?(Dalli) + require "typhoeus/cache/dalli" +end + +# If we are using Rails, load the Rails cache adapter +if defined?(Rails) + require "typhoeus/cache/rails" +end + +# If we are using Rails, then we will include the Typhoeus railtie. +# if defined?(Rails) +# require "typhoeus/railtie" +# end + +# Typhoeus is a HTTP client library based on Ethon which +# wraps libcurl. Sitting on top of libcurl makes Typhoeus +# very reliable and fast. +# +# There are some gems using Typhoeus like +# {https://github.com/myronmarston/vcr VCR}, +# {https://github.com/bblimke/webmock WebMock} or +# {https://github.com/technoweenie/faraday Faraday}. VCR +# and WebMock provide their own adapter whereas +# Faraday relies on {Faraday::Adapter::Typhoeus} +# since Typhoeus version 0.5. +# +# @example (see Typhoeus::Request) +# @example (see Typhoeus::Hydra) +# +# @see Typhoeus::Request +# @see Typhoeus::Hydra +# @see Faraday::Adapter::Typhoeus +# +# @since 0.5.0 +module Typhoeus + extend Request::Actions + extend Request::Callbacks::Types + + # The default Typhoeus user agent. + USER_AGENT = "Typhoeus - https://github.com/typhoeus/typhoeus" + + # Set the Typhoeus configuration options by passing a block. + # + # @example (see Typhoeus::Config) + # + # @yield [ Typhoeus::Config ] + # + # @return [ Typhoeus::Config ] The configuration. + # + # @see Typhoeus::Config + def self.configure + yield Config + end + + # Stub out a specific request. + # + # @example (see Typhoeus::Expectation) + # + # @param [ String ] base_url The url to stub out. + # @param [ Hash ] options The options to stub out. + # + # @return [ Typhoeus::Expectation ] The expecatation. + # + # @see Typhoeus::Expectation + def self.stub(base_url, options = {}, &block) + expectation = Expectation.all.find{ |e| e.base_url == base_url && e.options == options } + if expectation.nil? + expectation = Expectation.new(base_url, options) + Expectation.all << expectation + end + + expectation.and_return(&block) unless block.nil? + expectation + end + + # Add before callbacks. + # + # @example Add before callback. + # Typhoeus.before { |request| p request.base_url } + # + # @param [ Block ] block The callback. + # + # @yield [ Typhoeus::Request ] + # + # @return [ Array ] All before blocks. + def self.before(&block) + @before ||= [] + @before << block if block_given? + @before + end + + # Execute given block as if block connection is turned off. + # The old block connection state is restored afterwards. + # + # @example Make a real request, no matter if it's blocked. + # Typhoeus::Config.block_connection = true + # Typhoeus.get("www.example.com").code + # #=> raise Typhoeus::Errors::NoStub + # + # Typhoeus.with_connection do + # Typhoeus.get("www.example.com").code + # #=> :ok + # end + # + # @yield Yields control to the block after disabling block_connection. + # Afterwards, the block_connection is set to its original + # value. + # @return [ Object ] Returns the return value of the block. + # + # @see Typhoeus::Config.block_connection + def self.with_connection + old = Config.block_connection + Config.block_connection = false + result = yield if block_given? + Config.block_connection = old + result + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/adapters/faraday.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/adapters/faraday.rb new file mode 100644 index 000000000..84520109f --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/adapters/faraday.rb @@ -0,0 +1,180 @@ +require 'faraday' + +module Faraday # :nodoc: + class Adapter # :nodoc: + + # Adapter to use Faraday with Typhoeus. + # + # @example Use Typhoeus. + # require 'faraday' + # require 'typhoeus' + # require 'typhoeus/adapters/faraday' + # + # conn = Faraday.new(url: "www.example.com") do |faraday| + # faraday.adapter :typhoeus + # + # # You can include Typhoeus options to be used for every request + # # faraday.adapter :typhoeus, forbid_reuse: true, maxredirs: 1 + # end + # + # response = conn.get("/") + class Typhoeus < Faraday::Adapter + self.supports_parallel = true + + (class << self; self; end).instance_eval do + remove_method :setup_parallel_manager if method_defined? :setup_parallel_manager + end + + remove_method :call if method_defined? :call + remove_method :perform_request if method_defined? :perform_request + remove_method :request if method_defined? :request + remove_method :read_body if method_defined? :read_body + remove_method :configure_ssl if method_defined? :configure_ssl + remove_method :configure_proxy if method_defined? :configure_proxy + remove_method :configure_timeout if method_defined? :configure_timeout + remove_method :configure_socket if method_defined? :configure_socket + remove_method :parallel? if method_defined? :parallel? + + # Initialize the Typhoeus adapter + # + # @param [ App ] app Farday app + # @option [ Hash ] adapter_options Typhoeus options + # + # @return [ void ] + def initialize(app, adapter_options = {}) + super(app) + @adapter_options = adapter_options + end + + # Setup Hydra with provided options. + # + # @example Setup Hydra. + # Faraday::Adapter::Typhoeus.setup_parallel_manager + # #=> # + # + # @param (see Typhoeus::Hydra#initialize) + # @option (see Typhoeus::Hydra#initialize) + # + # @return [ Typhoeus::Hydra ] The hydra. + def self.setup_parallel_manager(options = {}) + ::Typhoeus::Hydra.new(options) + end + + dependency 'typhoeus' + + # Hook into Faraday and perform the request with Typhoeus. + # + # @param [ Hash ] env The environment. + # + # @return [ void ] + def call(env) + super + perform_request env + @app.call env + end + + private + + def perform_request(env) + if parallel?(env) + env[:parallel_manager].queue request(env) + else + request(env).run + end + end + + def request(env) + read_body env + + req = typhoeus_request(env) + + configure_ssl req, env + configure_proxy req, env + configure_timeout req, env + configure_socket req, env + + req.on_complete do |resp| + if resp.timed_out? + env[:typhoeus_timed_out] = true + unless parallel?(env) + raise Faraday::TimeoutError, "request timed out" + end + elsif (resp.response_code == 0) || ((resp.return_code != :ok) && !resp.mock?) + env[:typhoeus_connection_failed] = true + env[:typhoeus_return_message] = resp.return_message + unless parallel?(env) + raise Faraday::ConnectionFailed, resp.return_message + end + end + + save_response(env, resp.code, resp.body) do |response_headers| + response_headers.parse resp.response_headers + end + # in async mode, :response is initialized at this point + env[:response].finish(env) if parallel?(env) + end + + req + end + + def typhoeus_request(env) + opts = { + :method => env[:method], + :body => env[:body], + :headers => env[:request_headers] + }.merge(@adapter_options) + + ::Typhoeus::Request.new(env[:url].to_s, opts) + end + + def read_body(env) + env[:body] = env[:body].read if env[:body].respond_to? :read + end + + def configure_ssl(req, env) + ssl = env[:ssl] + + verify_p = (ssl && ssl.fetch(:verify, true)) + + ssl_verifyhost = verify_p ? 2 : 0 + req.options[:ssl_verifyhost] = ssl_verifyhost + req.options[:ssl_verifypeer] = verify_p + req.options[:sslversion] = ssl[:version] if ssl[:version] + req.options[:sslcert] = ssl[:client_cert] if ssl[:client_cert] + req.options[:sslkey] = ssl[:client_key] if ssl[:client_key] + req.options[:cainfo] = ssl[:ca_file] if ssl[:ca_file] + req.options[:capath] = ssl[:ca_path] if ssl[:ca_path] + client_cert_passwd_key = [:client_cert_passwd, :client_certificate_password].detect { |name| ssl.key?(name) } + req.options[:keypasswd] = ssl[client_cert_passwd_key] if client_cert_passwd_key + end + + def configure_proxy(req, env) + proxy = env[:request][:proxy] + return unless proxy + + req.options[:proxy] = "#{proxy[:uri].scheme}://#{proxy[:uri].host}:#{proxy[:uri].port}" + + if proxy[:user] && proxy[:password] + req.options[:proxyauth] = :any + req.options[:proxyuserpwd] = "#{proxy[:user]}:#{proxy[:password]}" + end + end + + def configure_timeout(req, env) + env_req = env[:request] + req.options[:timeout_ms] = (env_req[:timeout] * 1000).to_i if env_req[:timeout] + req.options[:connecttimeout_ms] = (env_req[:open_timeout] * 1000).to_i if env_req[:open_timeout] + end + + def configure_socket(req, env) + if bind = env[:request][:bind] + req.options[:interface] = bind[:host] + end + end + + def parallel?(env) + !!env[:parallel_manager] + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/dalli.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/dalli.rb new file mode 100644 index 000000000..5a09b10ab --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/dalli.rb @@ -0,0 +1,28 @@ +module Typhoeus + module Cache + # This module provides a simple way to cache HTTP responses using Dalli. + class Dalli + # @example Set Dalli as the Typhoeus cache backend + # Typhoeus::Config.cache = Typhoeus::Cache::Dalli.new + # + # @param [ Dalli::Client ] client + # A connection to the cache server. Defaults to `Dalli::Client.new` + # @param [ Hash ] options + # Options + # @option options [ Integer ] :default_ttl + # The default TTL of cached responses in seconds, for requests which do not set a cache_ttl. + def initialize(client = ::Dalli::Client.new, options = {}) + @client = client + @default_ttl = options[:default_ttl] + end + + def get(request) + @client.get(request.cache_key) + end + + def set(request, response) + @client.set(request.cache_key, response, request.cache_ttl || @default_ttl) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/rails.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/rails.rb new file mode 100644 index 000000000..10835e77d --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/rails.rb @@ -0,0 +1,28 @@ +module Typhoeus + module Cache + # This module provides a simple way to cache HTTP responses in using the Rails cache. + class Rails + # @example Use the Rails cache setup to cache Typhoeus responses. + # Typhoeus::Config.cache = Typhoeus::Cache::Rails.new + # + # @param [ ActiveSupport::Cache::Store ] cache + # A Rails cache backend. Defaults to Rails.cache. + # @param [ Hash ] options + # Options + # @option options [ Integer ] :default_ttl + # The default TTL of cached responses in seconds, for requests which do not set a cache_ttl. + def initialize(cache = ::Rails.cache, options = {}) + @cache = cache + @default_ttl = options[:default_ttl] + end + + def get(request) + @cache.read(request) + end + + def set(request, response) + @cache.write(request.cache_key, response, :expires_in => request.cache_ttl || @default_ttl) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/redis.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/redis.rb new file mode 100644 index 000000000..e54ca4ef4 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/cache/redis.rb @@ -0,0 +1,35 @@ +module Typhoeus + module Cache + # This module provides a simple way to cache HTTP responses in Redis. + class Redis + # @example Set Redis as the Typhoeus cache backend + # Typhoeus::Config.cache = Typhoeus::Cache::Redis.new + # + # @param [ Redis ] redis + # A connection to Redis. Defaults to `Redis.new`, which uses the + # `REDIS_URL` environment variable to connect + # @param [ Hash ] options + # Options + # @option options [ Integer ] :default_ttl + # The default TTL of cached responses in seconds, for requests which do not set a cache_ttl. + def initialize(redis = ::Redis.new, options = {}) + @redis = redis + @default_ttl = options[:default_ttl] + end + + def get(request) + serialized_response = @redis.get(request.cache_key) + return unless serialized_response + Marshal.load(serialized_response) + end + + def set(request, response) + ttl = request.cache_ttl || @default_ttl + key = request.cache_key + serialized_response = Marshal.dump(response) + @redis.set(key, serialized_response) + @redis.expire(key, ttl) if ttl + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/config.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/config.rb new file mode 100644 index 000000000..f05491c59 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/config.rb @@ -0,0 +1,69 @@ +module Typhoeus + + # The Typhoeus configuration used to set global + # options. + # @example Set the configuration options within a block. + # Typhoeus.configure do |config| + # config.verbose = true + # end + # + # @example Set the configuration directly. + # Typhoeus::Config.verbose = true + module Config + extend self + + # Defines whether the connection is blocked. + # Defaults to false. When set to true, only + # stubbed requests are allowed. A + # {Typhoeus::Errors::NoStub} error is raised, + # when trying to do a real request. It's possible + # to work around inside + # {Typhoeus.with_connection}. + # + # @return [ Boolean ] + # + # @see Typhoeus::Request::BlockConnection + # @see Typhoeus::Hydra::BlockConnection + # @see Typhoeus#with_connection + # @see Typhoeus::Errors::NoStub + attr_accessor :block_connection + + # Defines whether GET requests are memoized when using the {Typhoeus::Hydra}. + # + # @return [ Boolean ] + # + # @see Typhoeus::Hydra + # @see Typhoeus::Hydra::Memoizable + attr_accessor :memoize + + # Defines whether curls debug output is shown. + # Unfortunately it prints to stderr. + # + # @return [ Boolean ] + # + # @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTVERBOSE + attr_accessor :verbose + + # Defines whether requests are cached. + # + # @return [ Object ] + # + # @see Typhoeus::Hydra::Cacheable + # @see Typhoeus::Request::Cacheable + attr_accessor :cache + + # Defines whether to use a default user agent. + # + # @return [ String ] + # + # @see Typhoeus::Request#set_defaults + attr_accessor :user_agent + + # Defines wether to use a proxy server for every request. + # + # @return [ String ] + # + # @see Typhoeus::Request#set_defaults + attr_accessor :proxy + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/easy_factory.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/easy_factory.rb new file mode 100644 index 000000000..84c713141 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/easy_factory.rb @@ -0,0 +1,180 @@ +require 'set' + +module Typhoeus + + # This is a Factory for easies to be used in the hydra. + # Before an easy is ready to be added to a multi the + # on_complete callback to be set. + # This is done by this class. + # + # @api private + class EasyFactory + + RENAMED_OPTIONS = { + :auth_method => :httpauth, + :connect_timeout => :connecttimeout, + :encoding => :accept_encoding, + :follow_location => :followlocation, + :max_redirects => :maxredirs, + :proxy_type => :proxytype, + :ssl_cacert => :cainfo, + :ssl_capath => :capath, + :ssl_cert => :sslcert, + :ssl_cert_type => :sslcerttype, + :ssl_key => :sslkey, + :ssl_key_password => :keypasswd, + :ssl_key_type => :sslkeytype, + :ssl_version => :sslversion, + } + + CHANGED_OPTIONS = { + :disable_ssl_host_verification => :ssl_verifyhost, + :disable_ssl_peer_verification => :ssl_verifypeer, + :proxy_auth_method => :proxyauth, + } + + REMOVED_OPTIONS = Set.new([:cache_key_basis, :cache_timeout, :user_agent]) + + SANITIZE_IGNORE = Set.new([:method, :cache_ttl, :cache]) + SANITIZE_TIMEOUT = Set.new([:timeout_ms, :connecttimeout_ms]) + + # Returns the request provided. + # + # @return [ Typhoeus::Request ] + attr_reader :request + + # Returns the hydra provided. + # + # @return [ Typhoeus::Hydra ] + attr_reader :hydra + + # Create an easy factory. + # + # @example Create easy factory. + # Typhoeus::Hydra::EasyFactory.new(request, hydra) + # + # @param [ Request ] request The request to build an easy for. + # @param [ Hydra ] hydra The hydra to build an easy for. + def initialize(request, hydra = nil) + @request = request + @hydra = hydra + end + + # Return the easy in question. + # + # @example Return easy. + # easy_factory.easy + # + # @return [ Ethon::Easy ] The easy. + def easy + @easy ||= Typhoeus::Pool.get + end + + # Fabricated easy. + # + # @example Prepared easy. + # easy_factory.get + # + # @return [ Ethon::Easy ] The easy. + def get + begin + easy.http_request( + request.base_url.to_s, + request.options.fetch(:method, :get), + sanitize(request.options) + ) + rescue Ethon::Errors::InvalidOption => e + help = provide_help(e.message.match(/:\s(\w+)/)[1]) + raise $!, "#{$!}#{help}", $!.backtrace + end + set_callback + easy + end + + private + + def sanitize(options) + # set nosignal to true by default + # this improves thread safety and timeout behavior + sanitized = {:nosignal => true} + options.each do |k,v| + s = k.to_sym + next if SANITIZE_IGNORE.include?(s) + if new_option = RENAMED_OPTIONS[k.to_sym] + warn("Deprecated option #{k}. Please use #{new_option} instead.") + sanitized[new_option] = v + # sanitize timeouts + elsif SANITIZE_TIMEOUT.include?(s) + if !v.integer? + warn("Value '#{v}' for option '#{k}' must be integer.") + end + sanitized[k] = v.ceil + else + sanitized[k] = v + end + end + + sanitize_timeout!(sanitized, :timeout) + sanitize_timeout!(sanitized, :connecttimeout) + + sanitized + end + + def sanitize_timeout!(options, timeout) + timeout_ms = :"#{timeout}_ms" + if options[timeout] && options[timeout].round != options[timeout] + if !options[timeout_ms] + options[timeout_ms] = (options[timeout]*1000).ceil + end + options[timeout] = options[timeout].ceil + end + options + end + + # Sets on_complete callback on easy in order to be able to + # track progress. + # + # @example Set callback. + # easy_factory.set_callback + # + # @return [ Ethon::Easy ] The easy. + def set_callback + if request.streaming? + response = nil + easy.on_headers do |easy| + response = Response.new(Ethon::Easy::Mirror.from_easy(easy).options) + request.execute_headers_callbacks(response) + end + request.on_body.each do |callback| + easy.on_body do |chunk, easy| + callback.call(chunk, response) + end + end + else + easy.on_headers do |easy| + request.execute_headers_callbacks(Response.new(Ethon::Easy::Mirror.from_easy(easy).options)) + end + end + request.on_progress.each do |callback| + easy.on_progress do |dltotal, dlnow, ultotal, ulnow, easy| + callback.call(dltotal, dlnow, ultotal, ulnow, response) + end + end + easy.on_complete do |easy| + request.finish(Response.new(easy.mirror.options)) + Typhoeus::Pool.release(easy) + if hydra && !hydra.queued_requests.empty? + hydra.dequeue_many + end + end + end + + def provide_help(option) + if new_option = CHANGED_OPTIONS[option.to_sym] + "\nPlease try #{new_option} instead of #{option}." if new_option + elsif REMOVED_OPTIONS.include?(option.to_sym) + "\nThe option #{option} was removed." + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors.rb new file mode 100644 index 000000000..5ad2c5d3d --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors.rb @@ -0,0 +1,9 @@ +require 'typhoeus/errors/typhoeus_error' +require 'typhoeus/errors/no_stub' + +module Typhoeus + + # This namespace contains all errors raised by Typhoeus. + module Errors + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/no_stub.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/no_stub.rb new file mode 100644 index 000000000..d04534cee --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/no_stub.rb @@ -0,0 +1,12 @@ +module Typhoeus + module Errors + + # Raises when block connection is turned on + # and making a real request. + class NoStub < TyphoeusError + def initialize(request) + super("The connection is blocked and no stub defined: #{request.url}") + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/typhoeus_error.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/typhoeus_error.rb new file mode 100644 index 000000000..1550b4088 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/errors/typhoeus_error.rb @@ -0,0 +1,8 @@ +module Typhoeus + module Errors + + # Default typhoeus error class for all custom errors. + class TyphoeusError < StandardError + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/expectation.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/expectation.rb new file mode 100644 index 000000000..a8ae36859 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/expectation.rb @@ -0,0 +1,217 @@ +module Typhoeus + + # This class represents an expectation. It is part + # of the stubbing mechanism. An expectation contains + # a url and options, like a request. They are compared + # to the request url and options in order to evaluate + # whether they match. If that's the case, the attached + # responses are returned one by one. + # + # @example Stub a request and get specified response. + # expected = Typhoeus::Response.new + # Typhoeus.stub("www.example.com").and_return(expected) + # + # actual = Typhoeus.get("www.example.com") + # expected == actual + # #=> true + # + # @example Stub a request and get a lazily-constructed response containing data from actual widgets that exist in the system when the stubbed request is made. + # Typhoeus.stub("www.example.com/widgets") do + # actual_widgets = Widget.all + # Typhoeus::Response.new( + # :body => actual_widgets.inject([]) do |ids, widget| + # ids << widget.id + # end.join(",") + # ) + # end + # + # @example Stub a request and get a lazily-constructed response in the format requested. + # Typhoeus.stub("www.example.com") do |request| + # accept = (request.options[:headers]||{})['Accept'] || "application/json" + # format = accept.split(",").first + # body_obj = { 'things' => [ { 'id' => 'foo' } ] } + # + # Typhoeus::Response.new( + # :headers => { + # 'Content-Type' => format + # }, + # :body => SERIALIZERS[format].serialize(body_obj) + # ) + # end + class Expectation + + # @api private + attr_reader :base_url + + # @api private + attr_reader :options + + # @api private + attr_reader :from + + class << self + + # Returns all expectations. + # + # @example Return expectations. + # Typhoeus::Expectation.all + # + # @return [ Array ] The expectations. + def all + @expectations ||= [] + end + + # Clears expectations. This is handy while + # testing, and you want to make sure that + # you don't get canned responses. + # + # @example Clear expectations. + # Typhoeus::Expectation.clear + def clear + all.clear + end + + # Returns stubbed response matching the + # provided request. + # + # @example Find response + # Typhoeus::Expectation.response_for(request) + # + # @return [ Typhoeus::Response ] The stubbed response from a + # matching expectation, or nil if no matching expectation + # is found. + # + # @api private + def response_for(request) + expectation = find_by(request) + return nil if expectation.nil? + + expectation.response(request) + end + + # @api private + def find_by(request) + all.find do |expectation| + expectation.matches?(request) + end + end + end + + # Creates an expectation. + # + # @example Create expectation. + # Typhoeus::Expectation.new(base_url) + # + # @return [ Expectation ] The created expectation. + # + # @api private + def initialize(base_url, options = {}) + @base_url = base_url + @options = options + @response_counter = 0 + @from = nil + end + + # Set from value to mark an expectaion. Useful for + # other libraries, e.g. WebMock. + # + # @example Mark expectation. + # expectation.from(:webmock) + # + # @param [ String ] value Value to set. + # + # @return [ Expectation ] Returns self. + # + # @api private + def stubbed_from(value) + @from = value + self + end + + # Specify what should be returned, + # when this expectation is hit. + # + # @example Add response. + # expectation.and_return(response) + # + # @return [ void ] + def and_return(response=nil, &block) + new_response = (response.nil? ? block : response) + responses.push(*new_response) + end + + # Checks whether this expectation matches + # the provided request. + # + # @example Check if request matches. + # expectation.matches? request + # + # @param [ Request ] request The request to check. + # + # @return [ Boolean ] True when matches, else false. + # + # @api private + def matches?(request) + url_match?(request.base_url) && options_match?(request) + end + + # Return canned responses. + # + # @example Return responses. + # expectation.responses + # + # @return [ Array ] The responses. + # + # @api private + def responses + @responses ||= [] + end + + # Return the response. When there are + # multiple responses, they are returned one + # by one. + # + # @example Return response. + # expectation.response + # + # @return [ Response ] The response. + # + # @api private + def response(request) + response = responses.fetch(@response_counter, responses.last) + if response.respond_to?(:call) + response = response.call(request) + end + @response_counter += 1 + response.mock = @from || true + response + end + + private + + # Check whether the options matches the request options. + # I checks options and original options. + def options_match?(request) + (options ? options.all?{ |k,v| request.original_options[k] == v || request.options[k] == v } : true) + end + + # Check whether the base_url matches the request url. + # The base_url can be a string, regex or nil. String and + # regexp are checked, nil is always true, else false. + # + # Nil serves as a placeholder in case you want to match + # all urls. + def url_match?(request_url) + case base_url + when String + base_url == request_url + when Regexp + base_url === request_url + when nil + true + else + false + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra.rb new file mode 100644 index 000000000..079698125 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra.rb @@ -0,0 +1,95 @@ +require 'typhoeus/hydra/addable' +require 'typhoeus/hydra/before' +require 'typhoeus/hydra/cacheable' +require 'typhoeus/hydra/block_connection' +require 'typhoeus/hydra/memoizable' +require 'typhoeus/hydra/queueable' +require 'typhoeus/hydra/runnable' +require 'typhoeus/hydra/stubbable' + +module Typhoeus + + # Hydra manages making parallel HTTP requests. This + # is achieved by using libcurls multi interface: + # http://curl.haxx.se/libcurl/c/libcurl-multi.html + # The benefits are that you don't have to worry running + # the requests by yourself. + # + # Hydra will also handle how many requests you can + # make in parallel. Things will get flakey if you + # try to make too many requests at the same time. + # The built in limit is 200. When more requests than + # that are queued up, hydra will save them for later + # and start the requests as others are finished. You + # can raise or lower the concurrency limit through + # the Hydra constructor. + # + # Regarding the asynchronous behavior of the hydra, + # it is important to know that this is completely hidden + # from the developer and you are free to apply + # whatever technique you want to your code. That should not + # conflict with libcurls internal concurrency mechanism. + # + # @example Use the hydra to do multiple requests. + # hydra = Typhoeus::Hydra.new + # requests = (0..9).map{ Typhoeus::Request.new("www.example.com") } + # requests.each{ |request| hydra.queue(request) } + # hydra.run + # + # @note Callbacks are going to delay the request + # execution. + class Hydra + include Hydra::Addable + include Hydra::Runnable + include Hydra::Memoizable + include Hydra::Cacheable + include Hydra::BlockConnection + include Hydra::Stubbable + include Hydra::Before + include Hydra::Queueable + + # @example Set max_concurrency. + # Typhoeus::Hydra.new(max_concurrency: 20) + attr_accessor :max_concurrency + + # @api private + attr_reader :multi + + class << self + + # Returns a memoized hydra instance. + # + # @example Get a hydra. + # Typhoeus::Hydra.hydra + # + # @return [Typhoeus::Hydra] A new hydra. + def hydra + Thread.current[:typhoeus_hydra] ||= new + end + end + + # Create a new hydra. All + # {http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method Ethon::Multi#initialize} + # options are also available. + # + # @example Create a hydra. + # Typhoeus::Hydra.new + # + # @example Create a hydra with max_concurrency. + # Typhoeus::Hydra.new(max_concurrency: 20) + # + # @param [ Hash ] options The options hash. + # + # @option options :max_concurrency [ Integer ] Number + # of max concurrent connections to create. Default is + # 200. + # + # @see http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method + # Ethon::Multi#initialize + def initialize(options = {}) + @options = options + @max_concurrency = Integer(@options.fetch(:max_concurrency, 200)) + @multi = Ethon::Multi.new(options.reject{|k,_| k==:max_concurrency}) + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/addable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/addable.rb new file mode 100644 index 000000000..1a86960d5 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/addable.rb @@ -0,0 +1,23 @@ +module Typhoeus + class Hydra + + # This module handles the request adding on + # hydra. + # + # @api private + module Addable + + # Adds request to multi. + # + # @example Add request. + # hydra.add(request) + # + # @param [ Typhoeus::Request ] request to add. + # + # @return [ void ] + def add(request) + multi.add(EasyFactory.new(request, self).get) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/before.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/before.rb new file mode 100644 index 000000000..75e92138a --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/before.rb @@ -0,0 +1,31 @@ +module Typhoeus + class Hydra + + # This module provides a way to hook into before + # a request gets queued in hydra. This is very powerful + # and you should be careful because when you accidently + # return a falsy value the request won't be executed. + # + # @api private + module Before + + # Overrride add in order to execute callbacks in + # Typhoeus.before. Will break and return when a + # callback returns nil, false or a response. Calls super + # otherwise. + # + # @example Add the request. + # hydra.add(request) + def add(request) + Typhoeus.before.each do |callback| + value = callback.call(request) + if value.nil? || value == false || value.is_a?(Response) + dequeue + return value + end + end + super + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/block_connection.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/block_connection.rb new file mode 100644 index 000000000..9f3bd2f21 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/block_connection.rb @@ -0,0 +1,35 @@ +module Typhoeus + class Hydra + + # This module handles the blocked connection request mode on + # the hydra side, where only stubbed requests + # are allowed. + # Connection blocking needs to be turned on: + # Typhoeus.configure do |config| + # config.block_connection = true + # end + # + # When trying to do real requests a NoStub error + # is raised. + # + # @api private + module BlockConnection + + # Overrides add in order to check before if block connection + # is turned on. If thats the case a NoStub error is + # raised. + # + # @example Add the request. + # hydra.add(request) + # + # @param [ Request ] request The request to enqueue. + def add(request) + if request.blocked? + raise Typhoeus::Errors::NoStub.new(request) + else + super + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/cacheable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/cacheable.rb new file mode 100644 index 000000000..74c7f3045 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/cacheable.rb @@ -0,0 +1,15 @@ +module Typhoeus + class Hydra + module Cacheable + def add(request) + if request.cacheable? && response = request.cached_response + response.cached = true + request.finish(response) + dequeue + else + super + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/memoizable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/memoizable.rb new file mode 100644 index 000000000..0402a868c --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/memoizable.rb @@ -0,0 +1,56 @@ +module Typhoeus + class Hydra + + # This module handles the GET request memoization + # on the hydra side. Memoization needs to be turned + # on: + # Typhoeus.configure do |config| + # config.memoize = true + # end + # + # @api private + module Memoizable + + # Return the memory. + # + # @example Return the memory. + # hydra.memory + # + # @return [ Hash ] The memory. + def memory + @memory ||= {} + end + + # Overrides add in order to check before if request + # is memoizable and already in memory. If thats the case, + # super is not called, instead the response is set and + # the on_complete callback called. + # + # @example Add the request. + # hydra.add(request) + # + # @param [ Request ] request The request to add. + # + # @return [ Request ] The added request. + def add(request) + if request.memoizable? && memory.has_key?(request) + response = memory[request] + request.finish(response, true) + dequeue + else + super + end + end + + # Overrides run to make sure the memory is cleared after + # each run. + # + # @example Run hydra. + # hydra.run + def run + super + memory.clear + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/queueable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/queueable.rb new file mode 100644 index 000000000..b53dc6778 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/queueable.rb @@ -0,0 +1,83 @@ +module Typhoeus + class Hydra + + # This module handles the request queueing on + # hydra. + # + # @api private + module Queueable + + # Return the queued requests. + # + # @example Return queued requests. + # hydra.queued_requests + # + # @return [ Array ] The queued requests. + def queued_requests + @queued_requests ||= [] + end + + # Abort the current hydra run as good as + # possible. This means that it only + # clears the queued requests and can't do + # anything about already running requests. + # + # @example Abort hydra. + # hydra.abort + def abort + queued_requests.clear + end + + # Enqueues a request in order to be performed + # by the hydra. This can even be done while + # the hydra is running. Also sets hydra on + # request. + # + # @example Queue request. + # hydra.queue(request) + def queue(request) + request.hydra = self + queued_requests << request + end + + # Pushes a request to the front of the queue, + # to be performed by the hydra. Also sets hydra + # on request + # + # @example Queue reques. + # hydra.queue_front(request) + def queue_front(request) + request.hydra = self + queued_requests.unshift request + end + + # Removes a request from queued_requests and + # adds it to the hydra in order to be + # performed next. + # + # @example Dequeue request. + # hydra.dequeue + # + # @since 0.6.4 + def dequeue + add(queued_requests.shift) unless queued_requests.empty? + end + + # Removes requests from queued_requests and + # adds them to the hydra until max_concurrency + # is reached. + # + # @example Dequeue requests. + # hydra.dequeue_many + # + # @since 0.6.8 + def dequeue_many + number = multi.easy_handles.count + until number == max_concurrency || queued_requests.empty? + add(queued_requests.shift) + number += 1 + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/runnable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/runnable.rb new file mode 100644 index 000000000..9c2ad5193 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/runnable.rb @@ -0,0 +1,19 @@ +module Typhoeus + class Hydra + + # This module contains logic to run a hydra. + module Runnable + + # Start the hydra run. + # + # @example Start hydra run. + # hydra.run + # + # @return [ Symbol ] Return value from multi.perform. + def run + dequeue_many + multi.perform + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/stubbable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/stubbable.rb new file mode 100644 index 000000000..930997c94 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/hydra/stubbable.rb @@ -0,0 +1,28 @@ +module Typhoeus + class Hydra + + # This module handles stubbing on the hydra side. + # It plays well with the block_connection configuration, + # which raises when you make a request which is not stubbed. + # + # @api private + module Stubbable + + # Override add in order to check for matching expecations. + # When an expecation is found, super is not called. Instead a + # canned response is assigned to the request. + # + # @example Add the request. + # hydra.add(request) + def add(request) + if response = Expectation.response_for(request) + request.execute_headers_callbacks(response) + request.on_body.each{ |callback| callback.call(response.body, response) } + request.finish(response) + else + super + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/pool.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/pool.rb new file mode 100644 index 000000000..552a73f2b --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/pool.rb @@ -0,0 +1,70 @@ +require 'thread' + +module Typhoeus + + # The easy pool stores already initialized + # easy handles for future use. This is useful + # because creating them is expensive. + # + # @api private + module Pool + @mutex = Mutex.new + @pid = Process.pid + + # Releases easy into the pool. The easy handle is + # reset before it gets back in. + # + # @example Release easy. + # Typhoeus::Pool.release(easy) + def self.release(easy) + easy.cookielist = "flush" # dump all known cookies to 'cookiejar' + easy.cookielist = "all" # remove all cookies from memory for this handle + easy.reset + @mutex.synchronize { easies << easy } + end + + # Return an easy from the pool. + # + # @example Return easy. + # Typhoeus::Pool.get + # + # @return [ Ethon::Easy ] The easy. + def self.get + @mutex.synchronize do + if @pid == Process.pid + easies.pop + else + # Process has forked. Clear all easies to avoid sockets being + # shared between processes. + @pid = Process.pid + easies.clear + nil + end + end || Ethon::Easy.new + end + + # Clear the pool + def self.clear + @mutex.synchronize { easies.clear } + end + + # Use yielded easy, will be released automatically afterwards. + # + # @example Use easy. + # Typhoeus::Pool.with_easy do |easy| + # # use easy + # end + def self.with_easy(&block) + easy = get + yield easy + ensure + release(easy) if easy + end + + private + + def self.easies + @easies ||= [] + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/railtie.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/railtie.rb new file mode 100644 index 000000000..ee95f2a23 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/railtie.rb @@ -0,0 +1,12 @@ +require "typhoeus" + +module Rails + module Typhoeus + class Railtie < Rails::Railtie + # Need to include the Typhoeus middleware. + initializer "include the identity map" do |app| + app.config.middleware.use "Rack::Typhoeus::Middleware::ParamsDecoder" + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request.rb new file mode 100644 index 000000000..c41ee7b8d --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request.rb @@ -0,0 +1,221 @@ +require 'zlib' +require 'digest/sha1' +require 'typhoeus/request/actions' +require 'typhoeus/request/before' +require 'typhoeus/request/block_connection' +require 'typhoeus/request/cacheable' +require 'typhoeus/request/callbacks' +require 'typhoeus/request/marshal' +require 'typhoeus/request/memoizable' +require 'typhoeus/request/operations' +require 'typhoeus/request/responseable' +require 'typhoeus/request/streamable' +require 'typhoeus/request/stubbable' + +module Typhoeus + + # This class represents a request. + # + # @example (see #initialize) + # + # @example Make a request with the shortcut. + # response = Typhoeus.get("www.example.com") + # + # @see (see #initialize) + class Request + extend Request::Actions + include Request::Callbacks::Types + include Request::Callbacks + include Request::Streamable + include Request::Marshal + include Request::Operations + include Request::Responseable + include Request::Memoizable + include Request::Cacheable + include Request::BlockConnection + include Request::Stubbable + include Request::Before + + # Returns the provided base url. + # + # @return [ String ] + attr_accessor :base_url + + # Returns options, which includes default parameters. + # + # @return [ Hash ] + attr_accessor :options + + # Returns the hydra in which the request ran, if any. + # + # @return [ Typhoeus::Hydra ] + # + # @api private + attr_accessor :hydra + + # Returns the original options provided. + # + # @return [ Hash ] + # + # @api private + attr_accessor :original_options + + # @return [ Boolean ] + # + # @api private + attr_accessor :block_connection + + # Creates a new request. + # + # @example Simplest request. + # response = Typhoeus::Request.new("www.example.com").run + # + # @example Request with url parameters. + # response = Typhoeus::Request.new( + # "www.example.com", + # params: {a: 1} + # ).run + # + # @example Request with a body. + # response = Typhoeus::Request.new( + # "www.example.com", + # body: {b: 2} + # ).run + # + # @example Request with parameters and body. + # response = Typhoeus::Request.new( + # "www.example.com", + # params: {a: 1}, + # body: {b: 2} + # ).run + # + # @example Create a request and allow follow redirections. + # response = Typhoeus::Request.new( + # "www.example.com", + # followlocation: true + # ).run + # + # @param [ String ] base_url The url to request. + # @param [ options ] options The options. + # + # @option options [ Hash ] :params Translated + # into url parameters. + # @option options [ Hash ] :body Translated + # into HTTP POST request body. + # + # @return [ Typhoeus::Request ] The request. + # + # @note See {http://rubydoc.info/github/typhoeus/ethon/Ethon/Easy/Options Ethon::Easy::Options} for more options. + # + # @see Typhoeus::Hydra + # @see Typhoeus::Response + # @see Typhoeus::Request::Actions + def initialize(base_url, options = {}) + @base_url = base_url + @original_options = options + @options = options.dup + + set_defaults + end + + # Return the url. + # In contrast to base_url which returns the value you specified, url returns + # the full url including the parameters. + # + # @example Get the url. + # request.url + # + # @since 0.5.5 + def url + easy = EasyFactory.new(self).get + url = easy.url + Typhoeus::Pool.release(easy) + url + end + + # Returns whether other is equal to self. + # + # @example Are request equal? + # request.eql?(other_request) + # + # @param [ Object ] other The object to check. + # + # @return [ Boolean ] Returns true if equal, else false. + # + # @api private + def eql?(other) + self.class == other.class && + self.base_url == other.base_url && + fuzzy_hash_eql?(self.options, other.options) + end + + # Overrides Object#hash. + # + # @return [ Integer ] The integer representing the request. + # + # @api private + def hash + Zlib.crc32 cache_key + end + + # Returns a cache key for use with caching methods that required a string + # for a key. Will get used by ActiveSupport::Cache stores automatically. + # + # @return [ String ] The cache key. + def cache_key + Digest::SHA1.hexdigest "#{self.class.name}#{base_url}#{hashable_string_for(options)}" + end + + # Mimics libcurls POST body generation. This is not accurate, but good + # enough for VCR. + # + # @return [ String ] The encoded body. + # otherwise. + # + # @api private + def encoded_body + Ethon::Easy::Form.new(nil, options[:body]).to_s + end + + private + + # Checks if two hashes are equal or not, discarding + # first-level hash order. + # + # @param [ Hash ] left + # @param [ Hash ] right hash to check for equality + # + # @return [ Boolean ] Returns true if hashes have + # same values for same keys and same length, + # even if the keys are given in a different order. + def fuzzy_hash_eql?(left, right) + return true if (left == right) + + (left.count == right.count) && left.inject(true) do |res, kvp| + res && (kvp[1] == right[kvp[0]]) + end + end + + def hashable_string_for(obj) + case obj + when Hash + hashable_string_for(obj.sort_by {|sub_obj| sub_obj.first.to_s}) + when Array + obj.map {|sub_obj| hashable_string_for(sub_obj)}.to_s + else + obj.to_s + end + end + + # Sets default header and verbose when turned on. + def set_defaults + default_user_agent = Config.user_agent || Typhoeus::USER_AGENT + + options[:headers] = {'User-Agent' => default_user_agent}.merge(options[:headers] || {}) + options[:headers]['Expect'] ||= '' + options[:verbose] = Typhoeus::Config.verbose if options[:verbose].nil? && !Typhoeus::Config.verbose.nil? + options[:maxredirs] ||= 50 + options[:proxy] = Typhoeus::Config.proxy unless options.has_key?(:proxy) || Typhoeus::Config.proxy.nil? + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/actions.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/actions.rb new file mode 100644 index 000000000..b7974d8ae --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/actions.rb @@ -0,0 +1,125 @@ +module Typhoeus + class Request + + # Module containing logic about shortcuts to + # http methods. Like + # Typhoeus.get("www.example.com") + module Actions + + # Make a get request. + # + # @example Make get request. + # Typhoeus.get("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option (see Typhoeus::Request#initialize) + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def get(base_url, options = {}) + Request.new(base_url, options.merge(:method => :get)).run + end + + # Make a post request. + # + # @example Make post request. + # Typhoeus.post("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option (see Typhoeus::Request#initialize) + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def post(base_url, options = {}) + Request.new(base_url, options.merge(:method => :post)).run + end + + # Make a put request. + # + # @example Make put request. + # Typhoeus.put("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option options :params [ Hash ] Params hash which + # is attached to the base_url. + # @option options :body [ Hash ] Body hash which + # becomes a PUT request body. + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def put(base_url, options = {}) + Request.new(base_url, options.merge(:method => :put)).run + end + + # Make a delete request. + # + # @example Make delete request. + # Typhoeus.delete("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option (see Typhoeus::Request#initialize) + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def delete(base_url, options = {}) + Request.new(base_url, options.merge(:method => :delete)).run + end + + # Make a head request. + # + # @example Make head request. + # Typhoeus.head("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option (see Typhoeus::Request#initialize) + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def head(base_url, options = {}) + Request.new(base_url, options.merge(:method => :head)).run + end + + # Make a patch request. + # + # @example Make patch request. + # Typhoeus.patch("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option (see Typhoeus::Request#initialize) + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def patch(base_url, options = {}) + Request.new(base_url, options.merge(:method => :patch)).run + end + + # Make a options request. + # + # @example Make options request. + # Typhoeus.options("www.example.com") + # + # @param (see Typhoeus::Request#initialize) + # + # @option (see Typhoeus::Request#initialize) + # + # @return (see Typhoeus::Response#initialize) + # + # @note (see Typhoeus::Request#initialize) + def options(base_url, options = {}) + Request.new(base_url, options.merge(:method => :options)).run + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/before.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/before.rb new file mode 100644 index 000000000..d6ad7653e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/before.rb @@ -0,0 +1,30 @@ +module Typhoeus + class Request + + # This module provides a way to hook into before + # a request runs. This is very powerful + # and you should be careful because when you accidently + # return a falsy value the request won't be executed. + # + # @api private + module Before + + # Overrride run in order to execute callbacks in + # Typhoeus.before. Will break and return when a + # callback returns nil or false. Calls super + # otherwise. + # + # @example Run the request. + # request.run + def run + Typhoeus.before.each do |callback| + value = callback.call(self) + if value.nil? || value == false || value.is_a?(Response) + return response + end + end + super + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/block_connection.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/block_connection.rb new file mode 100644 index 000000000..7fc966ba6 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/block_connection.rb @@ -0,0 +1,52 @@ +module Typhoeus + class Request + + # This module handles the blocked connection request mode on + # the request side, where only stubbed requests + # are allowed. + # Connection blocking needs to be turned on: + # Typhoeus.configure do |config| + # config.block_connection = true + # end + # + # When trying to do real requests a NoStub error + # is raised. + # + # @api private + module BlockConnection + + # Overrides run in order to check before if block connection + # is turned on. If thats the case a NoStub error is + # raised. + # + # @example Run request. + # request.run + # + # @raise [Typhoeus::Errors::NoStub] If connection is blocked + # and no stub defined. + def run + if blocked? + raise Typhoeus::Errors::NoStub.new(self) + else + super + end + end + + # Returns wether a request is blocked or not. Takes + # request.block_connection and Typhoeus::Config.block_connection + # into consideration. + # + # @example Blocked? + # request.blocked? + # + # @return [ Boolean ] True if blocked, false else. + def blocked? + if block_connection.nil? + Typhoeus::Config.block_connection + else + block_connection + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/cacheable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/cacheable.rb new file mode 100644 index 000000000..74a41a9e8 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/cacheable.rb @@ -0,0 +1,38 @@ +module Typhoeus + class Request + module Cacheable + def response=(response) + cache.set(self, response) if cacheable? && !response.cached? + super + end + + def cacheable? + cache + end + + def run + if response = cached_response + response.cached = true + finish(response) + else + super + end + end + + def cached_response + cacheable? && cache.get(self) + end + + def cache_ttl + options[:cache_ttl] + end + + private + + def cache + return nil if options[:cache] === false + options[:cache] || Typhoeus::Config.cache + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/callbacks.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/callbacks.rb new file mode 100644 index 000000000..cc2cc1ead --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/callbacks.rb @@ -0,0 +1,151 @@ +module Typhoeus + class Request + + # This module contains the logic for the response callbacks. + # + # You can set multiple callbacks, which are then executed + # in the same order. + # + # request.on_complete { |response| p 1 } + # request.on_complete { |response| p 2 } + # request.execute_callbacks + # #=> 1 + # #=> 2 + # + # You can clear the callbacks: + # + # request.on_complete { |response| p 1 } + # request.on_complete { |response| p 2 } + # request.on_complete.clear + # request.execute_callbacks + # #=> nil + # + # @note If you're using the Hydra to execute multiple + # requests, then callbacks are delaying the + # request execution. + module Callbacks + + module Types # :nodoc: + # Set on_complete callback. + # + # @example Set on_complete. + # request.on_complete { |response| p "yay" } + # + # @param [ Block ] block The block to execute. + # + # @yield [ Typhoeus::Response ] + # + # @return [ Array ] All on_complete blocks. + def on_complete(&block) + @on_complete ||= [] + @on_complete << block if block_given? + @on_complete + end + + # Set on_success callback. + # + # @example Set on_success. + # request.on_success { |response| p "yay" } + # + # @param [ Block ] block The block to execute. + # + # @yield [ Typhoeus::Response ] + # + # @return [ Array ] All on_success blocks. + def on_success(&block) + @on_success ||= [] + @on_success << block if block_given? + @on_success + end + + # Set on_failure callback. + # + # @example Set on_failure. + # request.on_failure { |response| p "yay" } + # + # @param [ Block ] block The block to execute. + # + # @yield [ Typhoeus::Response ] + # + # @return [ Array ] All on_failure blocks. + def on_failure(&block) + @on_failure ||= [] + @on_failure << block if block_given? + @on_failure + end + + # Set on_headers callback. + # + # @example Set on_headers. + # request.on_headers { |response| p "yay" } + # + # @param [ Block ] block The block to execute. + # + # @yield [ Typhoeus::Response ] + # + # @return [ Array ] All on_headers blocks. + def on_headers(&block) + @on_headers ||= [] + @on_headers << block if block_given? + @on_headers + end + + # Set on_progress callback. + # + # @example Set on_progress. + # request.on_progress do |dltotal, dlnow, ultotal, ulnow| + # puts "dltotal (#{dltotal}), dlnow (#{dlnow}), ultotal (#{ultotal}), ulnow (#{ulnow})" + # end + # + # @param [ Block ] block The block to execute. + # + # @yield [ Typhoeus::Response ] + # + # @return [ Array ] All on_progress blocks. + def on_progress(&block) + @on_progress ||= [] + @on_progress << block if block_given? + @on_progress + end + end + + # Execute the headers callbacks and yields response. + # + # @example Execute callbacks. + # request.execute_headers_callbacks + # + # @return [ Array ] The results of the on_headers callbacks. + # + # @api private + def execute_headers_callbacks(response) + (Typhoeus.on_headers + on_headers).map do |callback| + callback.call(response) + end + end + + # Execute necessary callback and yields response. This + # include in every case on_complete and on_progress, on_success + # if successful and on_failure if not. + # + # @example Execute callbacks. + # request.execute_callbacks + # + # @return [ void ] + # + # @api private + def execute_callbacks + callbacks = Typhoeus.on_complete + Typhoeus.on_progress + on_complete + on_progress + + if response && response.success? + callbacks += Typhoeus.on_success + on_success + elsif response + callbacks += Typhoeus.on_failure + on_failure + end + + callbacks.each do |callback| + self.response.handled_response = callback.call(self.response) + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/marshal.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/marshal.rb new file mode 100644 index 000000000..3c8387cec --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/marshal.rb @@ -0,0 +1,22 @@ +module Typhoeus + class Request + + # This module contains custom serializer. + module Marshal + + # Return the important data needed to serialize this Request, except the + # request callbacks and `hydra`, since they cannot be marshalled. + def marshal_dump + unmarshallable = %w(@on_complete @on_success @on_failure @on_progress @on_headers @on_body @hydra) + (instance_variables - unmarshallable - unmarshallable.map(&:to_sym)).map do |name| + [name, instance_variable_get(name)] + end + end + + # Load. + def marshal_load(attributes) + attributes.each { |name, value| instance_variable_set(name, value) } + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/memoizable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/memoizable.rb new file mode 100644 index 000000000..c09ab1061 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/memoizable.rb @@ -0,0 +1,38 @@ +module Typhoeus + class Request + + # This module handles the GET request memoization + # on the request side. Memoization needs to be turned + # on: + # Typhoeus.configure do |config| + # config.memoize = true + # end + # + # @api private + module Memoizable + + # Override response setter and memoizes response + # if the request is memoizable. + # + # @param [ Response ] response The response to set. + # + # @example Set response. + # request.response = response + def response=(response) + hydra.memory[self] = response if memoizable? + super + end + + # Return whether a request is memoizable. + # + # @example Is request memoizable? + # request.memoizable? + # + # @return [ Boolean ] Return true if memoizable, false else. + def memoizable? + Typhoeus::Config.memoize && + (options[:method].nil? || options[:method] == :get) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/operations.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/operations.rb new file mode 100644 index 000000000..a461aa4a6 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/operations.rb @@ -0,0 +1,40 @@ +module Typhoeus + class Request + + # This module contains everything what is necessary + # to make a single request. + module Operations + + # Run a request. + # + # @example Run a request. + # Typhoeus::Request.new("www.example.com").run + # + # @return [ Response ] The response. + def run + easy = EasyFactory.new(self).get + easy.perform + response + end + + # Sets a response, the request on the response + # and executes the callbacks. + # + # @param [Typhoeus::Response] response The response. + # @param [Boolean] bypass_memoization Wether to bypass + # memoization or not. Decides how the response is set. + # + # @return [Typhoeus::Response] The response. + def finish(response, bypass_memoization = nil) + if bypass_memoization + @response = response + else + self.response = response + end + self.response.request = self + execute_callbacks + response + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/responseable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/responseable.rb new file mode 100644 index 000000000..2b91a6dd7 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/responseable.rb @@ -0,0 +1,29 @@ +module Typhoeus + class Request + + # This module contains logic for having a reponse + # getter and setter. + module Responseable + + # Set the response. + # + # @example Set response. + # request.response = response + # + # @param [ Response ] value The response to set. + def response=(value) + @response = value + end + + # Return the response. + # + # @example Return response. + # request.response + # + # @return [ Response ] The response. + def response + @response ||= nil + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/streamable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/streamable.rb new file mode 100644 index 000000000..0cfaa48f2 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/streamable.rb @@ -0,0 +1,34 @@ +module Typhoeus + class Request + + # This module contians the logic for response streaming. + module Streamable + + # Set on_body callback. + # + # This callback will be called each time a portion of the body is read from the socket. + # Setting an on_body callback will cause the response body to be empty. + # + # @example Set on_body. + # request.on_body { |body_chunk, response| puts "Got #{body_chunk.bytesize} bytes" } + # + # @param [ Block ] block The block to execute. + # + # @yield [ Typhoeus::Response, String ] + # + # @return [ Array ] All on_body blocks. + def on_body(&block) + @on_body ||= [] + @on_body << block if block_given? + @on_body + end + + # Is this request using streaming? + # + # @return [ Boolean ] True if any on_body blocks have been set. + def streaming? + defined?(@on_body) && @on_body.any? + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/stubbable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/stubbable.rb new file mode 100644 index 000000000..ee4255788 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/request/stubbable.rb @@ -0,0 +1,30 @@ +module Typhoeus + class Request + + # This module handles stubbing on the request side. + # It plays well with the block_connection configuration, + # which raises when you make a request which is not stubbed. + # + # @api private + module Stubbable + + # Override run in order to check for matching expectations. + # When an expectation is found, super is not called. Instead a + # canned response is assigned to the request. + # + # @example Run the request. + # request.run + # + # @return [ Response ] The response. + def run + if response = Expectation.response_for(self) + execute_headers_callbacks(response) + self.on_body.each{ |callback| callback.call(response.body, response) } + finish(response) + else + super + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response.rb new file mode 100644 index 000000000..efa7dbd3d --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response.rb @@ -0,0 +1,68 @@ +require 'typhoeus/response/header' +require 'typhoeus/response/informations' +require 'typhoeus/response/status' +require 'typhoeus/response/cacheable' + +module Typhoeus + + # This class represents the response. + class Response + include Response::Informations + include Response::Status + include Response::Cacheable + + # Remembers the corresponding request. + # + # @example Get request. + # request = Typhoeus::Request.new("www.example.com") + # response = request.run + # request == response.request + # #=> true + # + # @return [ Typhoeus::Request ] + attr_accessor :request + + # The provided options, which contain all the + # informations about the request. + # + # @return [ Hash ] + attr_accessor :options + + # Set the handled response. + attr_writer :handled_response + + # @api private + attr_writer :mock + + # Create a new response. + # + # @example Create a response. + # Response.new + # + # @param [ Hash ] options The options hash. + # + # @return [ Response ] The new response. + def initialize(options = {}) + @options = options + @headers = Header.new(options[:headers]) if options[:headers] + end + + # Returns whether this request is mocked + # or not. + # + # @api private + def mock + defined?(@mock) ? @mock : options[:mock] + end + alias :mock? :mock + + # Returns the handled_response if it has + # been defined; otherwise, returns the response + # + # @return [ Object ] The result of callbacks + # done on the response or the original response. + def handled_response + @handled_response || self + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/cacheable.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/cacheable.rb new file mode 100644 index 000000000..0170171cd --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/cacheable.rb @@ -0,0 +1,14 @@ +module Typhoeus + class Response + module Cacheable + + # Set the cache status, if we got response from cache + # it will have cached? == true + attr_writer :cached + + def cached? + defined?(@cached) ? !!@cached : false + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/header.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/header.rb new file mode 100644 index 000000000..11580abc7 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/header.rb @@ -0,0 +1,105 @@ +require 'delegate' + +module Typhoeus + class Response + + # This class represents the response header. + # It can be accessed like a hash. + # Values can be strings (normal case) or arrays of strings (for duplicates headers) + # + # @api private + class Header < DelegateClass(Hash) + + # Create a new header. + # + # @example Create new header. + # Header.new(raw) + # + # @param [ String ] raw The raw header. + def initialize(raw) + super({}) + @raw = raw + @sanitized = {} + parse + end + + def [](key) + fetch(key) { @sanitized[key.to_s.downcase] } + end + + # Parses the raw header. + # + # @example Parse header. + # header.parse + def parse + case @raw + when Hash + raw.each do |k, v| + process_pair(k, v) + end + when String + raw.split(/\r?\n(?!\s)/).each do |header| + header.strip! + next if header.empty? || header.start_with?( 'HTTP/' ) + process_line(header) + end + end + end + + private + + # Processes line and saves the result. + # + # @return [ void ] + def process_line(header) + key, value = header.split(':', 2) + process_pair(key.strip, (value ? value.strip.gsub(/\r?\n\s*/, ' ') : '')) + end + + # Sets key value pair for self and @sanitized. + # + # @return [ void ] + def process_pair(key, value) + set_value(key, value, self) + @sanitized[key.downcase] = self[key] + end + + # Sets value for key in specified hash + # + # @return [ void ] + def set_value(key, value, hash) + current_value = hash[key] + if current_value + if current_value.is_a? Array + current_value << value + else + hash[key] = [current_value, value] + end + else + hash[key] = value + end + end + + # Returns the raw header or empty string. + # + # @example Return raw header. + # header.raw + # + # @return [ String ] The raw header. + def raw + @raw || '' + end + + # Sets the default proc for the specified hash independent of the Ruby version. + # + # @return [ void ] + def set_default_proc_on(hash, default_proc) + if hash.respond_to?(:default_proc=) + hash.default_proc = default_proc + else + hash.replace(Hash.new(&default_proc).merge(hash)) + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/informations.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/informations.rb new file mode 100644 index 000000000..73544dd89 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/informations.rb @@ -0,0 +1,248 @@ +module Typhoeus + class Response + + # This module contains logic about informations + # on a response. + module Informations + + # Return libcurls return value. + # + # @example Get return_code. + # response.return_code + # + # @return [ Symbol ] The return_code. + def return_code + options[:return_code] + end + + # Returns a string describing the return. + # + # @example Get return_message. + # response.return_message + # + # @return [ String ] The return_message. + # + # @since 0.6.2 + def return_message + Ethon::Curl.easy_strerror(return_code) if return_code + end + + # Return the http response body. + # + # @example Get response_body. + # response.response_body + # + # @return [ String ] The response_body. + def response_body + options[:response_body] || options[:body] + end + alias :body :response_body + + # Return the http response headers. + # + # @example Get response_headers. + # response.response_headers + # + # @return [ String ] The response_headers. + def response_headers + return options[:response_headers] if options[:response_headers] + if mock? && h = options[:headers] + status_code = return_code || "200" + reason_phrase = status_code == "200" ? "OK" : "Mock Reason Phrase" + status_line = "HTTP/1.1 #{status_code} #{reason_phrase}" + actual_headers = h.map{ |k,v| [k, v.respond_to?(:join) ? v.join(',') : v] }. + map{ |e| "#{e.first}: #{e.last}" } + + [status_line, *actual_headers].join("\r\n") + end + end + + # Return the last received HTTP, FTP or SMTP response code. + # The value will be zero if no server response code has + # been received. Note that a proxy's CONNECT response should + # be read with http_connect_code and not this. + # + # @example Get response_code. + # response.response_code + # + # @return [ Integer ] The response_code. + def response_code + (options[:response_code] || options[:code]).to_i + end + alias :code :response_code + + # Return the available http auth methods. + # Bitmask indicating the authentication method(s) + # available. + # + # @example Get httpauth_avail. + # response.httpauth_avail + # + # @return [ Integer ] The bitmask. + def httpauth_avail + options[:httpauth_avail] + end + + + # Return the total time in seconds for the previous + # transfer, including name resolving, TCP connect etc. + # + # @example Get total_time. + # response.total_time + # + # @return [ Float ] The total_time. + def total_time + options[:total_time] || options[:time] + end + alias :time :total_time + + # Return the time, in seconds, it took from the start + # until the first byte is received by libcurl. This + # includes pretransfer time and also the time the + # server needs to calculate the result. + # + # @example Get starttransfer_time. + # response.starttransfer_time + # + # @return [ Float ] The starttransfer_time. + def starttransfer_time + options[:starttransfer_time] || options[:start_transfer_time] + end + alias :start_transfer_time :starttransfer_time + + # Return the time, in seconds, it took from the start + # until the SSL/SSH connect/handshake to the remote + # host was completed. This time is most often very near + # to the pre transfer time, except for cases such as HTTP + # pipelining where the pretransfer time can be delayed + # due to waits in line for the pipeline and more. + # + # @example Get appconnect_time. + # response.appconnect_time + # + # @return [ Float ] The appconnect_time. + def appconnect_time + options[:appconnect_time] || options[:app_connect_time] + end + alias :app_connect_time :appconnect_time + + # Return the time, in seconds, it took from the start + # until the file transfer is just about to begin. This + # includes all pre-transfer commands and negotiations + # that are specific to the particular protocol(s) involved. + # It does not involve the sending of the protocol- + # specific request that triggers a transfer. + # + # @example Get pretransfer_time. + # response.pretransfer_time + # + # @return [ Float ] The pretransfer_time. + def pretransfer_time + options[:pretransfer_time] + end + + # Return the time, in seconds, it took from the start + # until the connect to the remote host (or proxy) was completed. + # + # @example Get connect_time. + # response.connect_time + # + # @return [ Float ] The connect_time. + def connect_time + options[:connect_time] + end + + # Return the time, in seconds, it took from the + # start until the name resolving was completed. + # + # @example Get namelookup_time. + # response.namelookup_time + # + # @return [ Float ] The namelookup_time. + def namelookup_time + options[:namelookup_time] || options[:name_lookup_time] + end + alias :name_lookup_time :namelookup_time + + # Return the time, in seconds, it took for all redirection steps + # include name lookup, connect, pretransfer and transfer before the + # final transaction was started. time_redirect shows the complete + # execution time for multiple redirections. + # + # @example Get redirect_time. + # response.redirect_time + # + # @return [ Float ] The redirect_time. + def redirect_time + options[:redirect_time] + end + + # Return the last used effective url. + # + # @example Get effective_url. + # response.effective_url + # + # @return [ String ] The effective_url. + def effective_url + options[:effective_url] + end + + # Return the string holding the IP address of the most recent + # connection done with this curl handle. This string + # may be IPv6 if that's enabled. + # + # @example Get primary_ip. + # response.primary_ip + # + # @return [ String ] The primary_ip. + def primary_ip + options[:primary_ip] + end + + # Return the total number of redirections that were + # actually followed + # + # @example Get redirect_count. + # response.redirect_count + # + # @return [ Integer ] The redirect_count. + def redirect_count + options[:redirect_count] + end + + def request_size + options[:request_size] + end + + def debug_info + options[:debug_info] + end + + # Returns the response header. + # + # @example Return headers. + # response.headers + # + # @return [ Typhoeus::Header ] The response header. + def headers + return Header.new(options[:headers]) if mock? && options[:headers] + return nil if response_headers.nil? && !defined?(@headers) + @headers ||= Header.new(response_headers.split("\r\n\r\n").last) + end + alias :headers_hash :headers + + # Return all redirections in between as multiple + # responses with header. + # + # @example Return redirections. + # response.redirections + # + # @return [ Array ] The redirections + def redirections + return [] unless response_headers + response_headers.split("\r\n\r\n")[0..-2].map{ |h| Response.new(:response_headers => h) } + end + end + end +end + diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/status.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/status.rb new file mode 100644 index 000000000..e1840f4a9 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/response/status.rb @@ -0,0 +1,106 @@ +module Typhoeus + class Response + + # This module contains logic about the http + # status. + module Status + + # Return the status message if present. + # + # @example Return status message. + # reesponse.status_message + # + # @return [ String ] The message. + def status_message + return @status_message if defined?(@status_message) && @status_message + return options[:status_message] unless options[:status_message].nil? + + # HTTP servers can choose not to include the explanation to HTTP codes. The RFC + # states this (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4): + # Except when responding to a HEAD request, the server SHOULD include an entity containing + # an explanation of the error situation [...] + # This means 'HTTP/1.1 404' is as valid as 'HTTP/1.1 404 Not Found' and we have to handle it. + # + # Regexp doc: http://rubular.com/r/eAr1oVYsVa + if first_header_line != nil and first_header_line[/\d{3} (.*)$/, 1] != nil + @status_message = first_header_line[/\d{3} (.*)$/, 1].chomp + else + @status_message = nil + end + end + + # Return the http version. + # + # @example Return http version. + # response.http_version + # + # @return [ String ] The http version. + def http_version + @http_version ||= first_header_line ? first_header_line[/HTTP\/(\S+)/, 1] : nil + end + + # Return whether the response is a success. + # + # @example Return if the response was successful. + # response.success? + # + # @return [ Boolean ] Return true if successful, false else. + def success? + (mock || return_code == :ok) && response_code && has_good_response_code? + end + + # Return whether the response is a failure. + # + # @example Return if the response was failed. + # response.failure? + # + # @return [ Boolean ] Return true if failure, false else. + def failure? + (mock || return_code == :internal_server_error) && response_code && has_bad_response_code? + end + + # Return wether the response is modified. + # + # @example Return if the response was modified. + # response.modified? + # + # @return [ Boolean ] Return true if modified, false else. + def modified? + (mock || return_code == :ok) && response_code && response_code != 304 + end + + # Return whether the response is timed out. + # + # @example Return if the response timed out. + # response.timed_out? + # + # @return [ Boolean ] Return true if timed out, false else. + def timed_out? + return_code == :operation_timedout + end + + private + + # :nodoc: + def first_header_line + @first_header_line ||= begin + if response_headers.to_s.include?("\r\n\r\n") + response_headers.to_s.split("\r\n\r\n").last.split("\r\n").first + else + response_headers.to_s.split("\r\n").first + end + end + end + + # :nodoc: + def has_good_response_code? + response_code >= 200 && response_code < 300 + end + + # :nodoc: + def has_bad_response_code? + !has_good_response_code? + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/version.rb b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/version.rb new file mode 100644 index 000000000..048f091e1 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/lib/typhoeus/version.rb @@ -0,0 +1,5 @@ +module Typhoeus + + # The current Typhoeus version. + VERSION = '1.4.0' +end diff --git a/fluentd/vendored_gem_src/typhoeus/perf/profile.rb b/fluentd/vendored_gem_src/typhoeus/perf/profile.rb new file mode 100644 index 000000000..29ec9c2ee --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/perf/profile.rb @@ -0,0 +1,14 @@ +require 'typhoeus' +require 'ruby-prof' + +calls = 50 +base_url = "http://127.0.0.1:3000/" + +RubyProf.start +calls.times do |i| + Typhoeus::Request.get(base_url+i.to_s) +end +result = RubyProf.stop + +printer = RubyProf::FlatPrinter.new(result) +printer.print(STDOUT) diff --git a/fluentd/vendored_gem_src/typhoeus/perf/vs_nethttp.rb b/fluentd/vendored_gem_src/typhoeus/perf/vs_nethttp.rb new file mode 100644 index 000000000..305f9feb7 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/perf/vs_nethttp.rb @@ -0,0 +1,64 @@ +require 'typhoeus' +require 'net/http' +require 'open-uri' +require 'benchmark' + +URL = "http://localhost:300" +hydra = Typhoeus::Hydra.new(max_concurrency: 3) + +if defined? require_relative + require_relative '../spec/support/localhost_server.rb' + require_relative '../spec/support/server.rb' +else + require '../spec/support/localhost_server.rb' + require '../spec/support/server.rb' +end +LocalhostServer.new(TESTSERVER.new, 3000) +LocalhostServer.new(TESTSERVER.new, 3001) +LocalhostServer.new(TESTSERVER.new, 3002) + +def url_for(i) + "#{URL}#{i%3}/" +end + +Benchmark.bm do |bm| + + [1000].each do |calls| + puts "[ #{calls} requests ]" + + bm.report("net/http ") do + calls.times do |i| + uri = URI.parse(url_for(i)) + Net::HTTP.get_response(uri) + end + end + + bm.report("open ") do + calls.times do |i| + open(url_for(i)) + end + end + + bm.report("request ") do + calls.times do |i| + Typhoeus::Request.get(url_for(i)) + end + end + + bm.report("hydra ") do + calls.times do |i| + hydra.queue(Typhoeus::Request.new(url_for(i))) + end + hydra.run + end + + bm.report("hydra memoize ") do + Typhoeus::Config.memoize = true + calls.times do |i| + hydra.queue(Typhoeus::Request.new(url_for(i))) + end + hydra.run + Typhoeus::Config.memoize = false + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb new file mode 100644 index 000000000..3aee759a9 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb @@ -0,0 +1,156 @@ +require 'spec_helper' +require "rack/typhoeus" + +describe "Rack::Typhoeus::Middleware::ParamsDecoder::Helper" do + + let(:klass) do + Class.new do + include Rack::Typhoeus::Middleware::ParamsDecoder::Helper + end.new + end + + describe "#decode" do + let(:decoded) { klass.decode(params) } + let(:params) { { :array => {'0' => :a, '1' => :b } } } + + it "decodes" do + expect(decoded[:array]).to match_array([:a, :b]) + end + + it "doesn't modify" do + expect(decoded).to_not be(params) + end + end + + describe "#decode!" do + let(:decoded) { klass.decode!(params) } + + context "when hash" do + context "when encoded" do + context "when simple" do + let(:params) { { :array => {'0' => :a, '1' => :b } } } + + it "decodes" do + expect(decoded[:array]).to match_array([:a, :b]) + end + + it "modifies" do + expect(decoded).to eq(params) + end + end + + context "when longer and more complex" do + let(:params) do + { + :ids => { + "0" => "407304", + "1" => "407305", + "2" => "407306", + "3" => "407307", + "4" => "407308", + "5" => "407309", + "6" => "407310", + "7" => "407311", + "8" => "407312", + "9" => "407313", + "10" => "327012" + } + } + end + + it "decodes ensuring arrays maintain their original order" do + expect(decoded[:ids]).to eq(["407304", "407305", "407306", "407307", "407308", "407309", "407310", "407311", "407312", "407313", "327012"]) + end + end + + context "when nested" do + let(:params) do + { :array => { '0' => 0, '1' => { '0' => 'sub0', '1' => 'sub1' } } } + end + + it "decodes" do + expect(decoded[:array]).to include(0) + expect(decoded[:array].find{|e| e.is_a?(Array)}).to( + match_array(['sub0', 'sub1']) + ) + end + + it "modifies" do + expect(decoded).to eq(params) + end + end + end + + context "when not encoded" do + let(:params) { {:a => :a} } + + it "doesn't modify" do + expect(decoded).to be(params) + end + end + end + + context "when no hash" do + let(:params) { "a" } + + it "returns self" do + expect(decoded).to be(params) + end + end + end + + describe "#encoded?" do + let(:encoded) { klass.send(:encoded?, params) } + + context "when there is only one key" do + context "and its 0" do + let(:params){ {'0' => 1} } + it 'returns true' do + expect(encoded).to be_truthy + end + end + context "and its not 0" do + let(:params){ {'some-key' => 1}} + it 'returns false' do + expect(encoded).to be_falsey + end + end + end + + context "when keys are ascending numbers starting with zero" do + let(:params) { Hash[12.times.map {|i| [i, (i+65).chr]}] } + + it "returns true" do + expect(encoded).to be_truthy + end + end + + context "when keys are not ascending numbers starting with zero" do + let(:params) { {:a => 1} } + + it "returns false" do + expect(encoded).to be_falsey + end + end + end + + describe "#convert" do + let(:converted) { klass.send(:convert, params) } + + context "when encoded" do + let(:params) { {'0' => :a, '1' => :b} } + + it "returns values" do + expect(converted).to match_array([:a, :b]) + end + end + + context "when not encoded" do + let(:params) { {:a => :a} } + + it "returns unmodified" do + expect(converted).to be(params) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder_spec.rb new file mode 100644 index 000000000..187da9f25 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/rack/typhoeus/middleware/params_decoder_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe "Rack::Typhoeus::Middleware::ParamsDecoder" do + + before(:all) do + require "rack/typhoeus" + end + + let(:app) do + double + end + + let(:env) do + double + end + + let(:klass) do + Rack::Typhoeus::Middleware::ParamsDecoder + end + + describe "#call" do + end + + context "when requesting" do + let(:response) { Typhoeus.get("localhost:3001", :params => {:x => [:a]}) } + + it "transforms parameters" do + expect(response.body).to include("query_hash\":{\"x\":[\"a\"]}") + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/spec_helper.rb b/fluentd/vendored_gem_src/typhoeus/spec/spec_helper.rb new file mode 100644 index 000000000..73302cce5 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/spec_helper.rb @@ -0,0 +1,29 @@ +$LOAD_PATH.unshift(File.dirname(__FILE__)) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) + +require "bundler" +Bundler.setup +require "typhoeus" +require "rspec" + +Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f } + +RSpec.configure do |config| + config.order = :rand + + config.before(:suite) do + LocalhostServer.new(TESTSERVER.new, 3001) + end + + config.after do + Typhoeus::Pool.clear + Typhoeus::Expectation.clear + Typhoeus.before.clear + Typhoeus.on_complete.clear + Typhoeus.on_success.clear + Typhoeus.on_failure.clear + Typhoeus::Config.verbose = false + Typhoeus::Config.block_connection = false + Typhoeus::Config.memoize = false + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/support/localhost_server.rb b/fluentd/vendored_gem_src/typhoeus/spec/support/localhost_server.rb new file mode 100644 index 000000000..c5a7508bc --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/support/localhost_server.rb @@ -0,0 +1,94 @@ +require 'rack' +require 'rack/handler/webrick' +require 'net/http' + +# The code for this is inspired by Capybara's server: +# http://github.com/jnicklas/capybara/blob/0.3.9/lib/capybara/server.rb +class LocalhostServer + READY_MESSAGE = "Server ready" + + class Identify + def initialize(app) + @app = app + end + + def call(env) + if env["PATH_INFO"] == "/__identify__" + [200, {}, [LocalhostServer::READY_MESSAGE]] + else + @app.call(env) + end + end + end + + attr_reader :port + + def initialize(rack_app, port = nil) + @port = port || find_available_port + @rack_app = rack_app + concurrently { boot } + wait_until(10, "Boot failed.") { booted? } + end + + private + + def find_available_port + server = TCPServer.new('127.0.0.1', 0) + server.addr[1] + ensure + server.close if server + end + + def boot + # Use WEBrick since it's part of the ruby standard library and is available on all ruby interpreters. + options = { :Port => port } + options.merge!(:AccessLog => [], :Logger => WEBrick::BasicLog.new(StringIO.new)) unless ENV['VERBOSE_SERVER'] + Rack::Handler::WEBrick.run(Identify.new(@rack_app), options) + end + + def booted? + res = ::Net::HTTP.get_response("localhost", '/__identify__', port) + if res.is_a?(::Net::HTTPSuccess) or res.is_a?(::Net::HTTPRedirection) + return res.body == READY_MESSAGE + end + rescue Errno::ECONNREFUSED, Errno::EBADF + return false + end + + def concurrently + if should_use_subprocess? + pid = Process.fork do + trap(:INT) { ::Rack::Handler::WEBrick.shutdown } + yield + exit # manually exit; otherwise this sub-process will re-run the specs that haven't run yet. + end + + at_exit do + Process.kill('INT', pid) + begin + Process.wait(pid) + rescue Errno::ECHILD + # ignore this error...I think it means the child process has already exited. + end + end + else + Thread.new { yield } + end + end + + def should_use_subprocess? + # !ENV['THREADED'] + false + end + + def wait_until(timeout, error_message, &block) + start_time = Time.now + + while true + return if yield + raise TimeoutError.new(error_message) if (Time.now - start_time) > timeout + sleep(0.05) + end + end +end + diff --git a/fluentd/vendored_gem_src/typhoeus/spec/support/memory_cache.rb b/fluentd/vendored_gem_src/typhoeus/spec/support/memory_cache.rb new file mode 100644 index 000000000..15cc56bf1 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/support/memory_cache.rb @@ -0,0 +1,15 @@ +class MemoryCache + attr_reader :memory + + def initialize + @memory = {} + end + + def get(request) + memory[request] + end + + def set(request, response) + memory[request] = response + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/support/server.rb b/fluentd/vendored_gem_src/typhoeus/spec/support/server.rb new file mode 100644 index 000000000..b7f6f0639 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/support/server.rb @@ -0,0 +1,116 @@ +#!/usr/bin/env ruby +require 'json' +require 'zlib' +require 'sinatra/base' +require 'rack/typhoeus' + +TESTSERVER = Sinatra.new do + set :logging, false + use Rack::Typhoeus::Middleware::ParamsDecoder + + fail_count = 0 + + post '/file' do + { + 'content-type' => params[:file][:type], + 'filename' => params[:file][:filename], + 'content' => params[:file][:tempfile].read, + 'request-content-type' => request.env['CONTENT_TYPE'] + }.to_json + end + + get '/multiple-headers' do + [200, { 'Set-Cookie' => %w[ foo bar ], 'Content-Type' => 'text/plain' }, ['']] + end + + get '/cookies-test' do + [200, { 'Set-Cookie' => %w(foo=bar bar=foo), 'Content-Type' => 'text/plain' }, ['']] + end + + get '/cookies-test2' do + [200, { 'Set-Cookie' => %w(foo2=bar bar2=foo), 'Content-Type' => 'text/plain' }, ['']] + end + + get '/fail/:number' do + if fail_count >= params[:number].to_i + "ok" + else + fail_count += 1 + error 500, "oh noes!" + end + end + + get '/fail_forever' do + error 500, "oh noes!" + end + + get '/redirect' do + redirect '/' + end + + get '/bad_redirect' do + redirect '/bad_redirect' + end + + get '/auth_basic/:username/:password' do + @auth ||= Rack::Auth::Basic::Request.new(request.env) + # Check that we've got a basic auth, and that it's credentials match the ones + # provided in the request + if @auth.provided? && @auth.basic? && @auth.credentials == [ params[:username], params[:password] ] + # auth is valid - confirm it + true + else + # invalid auth - request the authentication + response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth") + throw(:halt, [401, "Not authorized\n"]) + end + end + + get '/auth_ntlm' do + # we're just checking for the existence if NTLM auth header here. It's validation + # is too troublesome and really doesn't bother is much, it's up to libcurl to make + # it valid + response['WWW-Authenticate'] = 'NTLM' + is_ntlm_auth = /^NTLM/ =~ request.env['HTTP_AUTHORIZATION'] + true if is_ntlm_auth + throw(:halt, [401, "Not authorized\n"]) if !is_ntlm_auth + end + + get '/gzipped' do + req_env = request.env.to_json + z = Zlib::Deflate.new + gzipped_env = z.deflate(req_env, Zlib::FINISH) + z.close + response['Content-Encoding'] = 'gzip' + gzipped_env + end + + get '/**' do + sleep params["delay"].to_i if params.has_key?("delay") + request.env.merge!(:body => request.body.read).to_json + end + + head '/**' do + sleep params["delay"].to_i if params.has_key?("delay") + end + + put '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + post '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + delete '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + patch '/**' do + request.env.merge!(:body => request.body.read).to_json + end + + options '/**' do + request.env.merge!(:body => request.body.read).to_json + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/adapters/faraday_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/adapters/faraday_spec.rb new file mode 100644 index 000000000..716fb76d0 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/adapters/faraday_spec.rb @@ -0,0 +1,339 @@ +if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("1.9.0") + require 'spec_helper' + require 'typhoeus/adapters/faraday' + + describe Faraday::Adapter::Typhoeus do + let(:base_url) { "http://localhost:3001" } + let(:adapter) { described_class.new(nil) } + let(:request) { Typhoeus::Request.new(base_url) } + let(:conn) do + Faraday.new(:url => base_url) do |faraday| + faraday.adapter :typhoeus + end + end + let(:response) { conn.get("/") } + + context "when parallel" do + it "returns a faraday response" do + response = nil + conn.in_parallel { response = conn.get("/") } + expect(response).to be_a(Faraday::Response) + end + + it "succeeds" do + response = nil + conn.in_parallel { response = conn.get("/") } + expect(response.status).to be(200) + end + end + + context "when not parallel" do + it "returns a faraday response" do + expect(response).to be_a(Faraday::Response) + end + + it "succeeds" do + expect(response.status).to be(200) + end + end + + context "when a response is stubbed" do + before do + stub = Typhoeus::Response.new \ + :code => 200, + :headers => { "Foo" => "2", "Bar" => "3" }, + :body => "Hello", + :mock => true + + Typhoeus.stub(base_url + '/').and_return(stub) + end + + it 'stubs the status code' do + expect(response.status).to eq(200) + end + + it 'stubs the response body' do + expect(response.body).to eq("Hello") + end + + it 'stubs the headers' do + expect(response.headers).to eq("Foo" => "2", "Bar" => "3") + end + end + + describe "#initialize" do + let(:request) { adapter.method(:typhoeus_request).call({}) } + + context "when typhoeus request options specified" do + let(:adapter) { described_class.new(nil, { :forbid_reuse => true, :maxredirs => 1 }) } + + it "should set option for request" do + expect(request.options[:forbid_reuse]).to be_truthy + expect(request.options[:maxredirs]).to eq(1) + end + end + end + + describe "#perform_request" do + let(:env) { {} } + + context "when body" do + let(:env) { { :body => double(:read => "body") } } + + it "reads body" do + expect(adapter.method(:read_body).call(env)).to eq("body") + end + end + + context "parallel_manager" do + context "when given" do + let(:env) { { :parallel_manager => double(:queue => true), :ssl => {}, :request => {} } } + + it "uses" do + adapter.method(:perform_request).call(env) + end + end + + context "when not given" do + let(:env) { { :method => :get, :ssl => {}, :request => {} } } + + it "falls back to single" do + expect(Typhoeus::Request).to receive(:new).and_return(double(:options => {}, :on_complete => [], :run => true)) + adapter.method(:perform_request).call(env) + end + end + end + end + + describe "#request" do + let(:env) do + { :url => "url", :method => :get, :body => "body", :request_headers => {}, :ssl => {}, :request => {} } + end + + let(:request) { adapter.method(:request).call(env) } + + it "returns request" do + expect(request).to be_a(Typhoeus::Request) + end + + it "sets url" do + expect(request.base_url).to eq("url") + end + + it "sets http method" do + expect(request.original_options[:method]).to eq(:get) + end + + it "sets body" do + expect(request.original_options[:body]).to eq("body") + end + + it "sets headers" do + expect(request.original_options[:headers]).to eq({}) + end + + it "sets on_complete callback" do + expect(request.on_complete.size).to eq(1) + end + end + + context "when the connection failed" do + before do + stub = Typhoeus::Response.new \ + :response_code => 0, + :return_code => 0, + :mock => true + + Typhoeus.stub(base_url + '/').and_return(stub) + end + + context "when parallel" do + it "isn't successful" do + response = nil + conn.in_parallel { response = conn.get("/") } + expect(response.success?).to be_falsey + end + + it "translates the response code into an error message" do + response = nil + conn.in_parallel { response = conn.get("/") } + expect(response.env[:typhoeus_return_message]).to eq("No error") + end + end + + context "when not parallel" do + it "raises an error" do + expect { conn.get("/") }.to raise_error(Faraday::ConnectionFailed, "No error") + end + end + end + + describe "#configure_socket" do + let(:env) { { :request => { :bind => { :host => "interface" } } } } + + before { adapter.method(:configure_socket).call(request, env) } + + context "when host" do + it "sets interface" do + expect(request.options[:interface]).to eq("interface") + end + end + end + + describe "#configure_timeout" do + before { adapter.method(:configure_timeout).call(request, env) } + + context "when timeout" do + let(:env) { { :request => { :timeout => 1 } } } + + it "sets timeout_ms" do + expect(request.options[:timeout_ms]).to eq(1000) + end + end + + context "when open_timeout" do + let(:env) { { :request => { :open_timeout => 1 } } } + + it "sets connecttimeout_ms" do + expect(request.options[:connecttimeout_ms]).to eq(1000) + end + end + end + + describe "#configure_proxy" do + before { adapter.method(:configure_proxy).call(request, env) } + + context "when proxy" do + let(:env) { { :request => { :proxy => { :uri => double(:scheme => 'http', :host => "localhost", :port => "3001") } } } } + + it "sets proxy" do + expect(request.options[:proxy]).to eq("http://localhost:3001") + end + + context "when username and password" do + let(:env) do + { :request => { :proxy => { + :uri => double(:scheme => 'http', :host => :a, :port => :b), + :user => "a", + :password => "b" + } } } + end + + it "sets proxyuserpwd" do + expect(request.options[:proxyuserpwd]).to eq("a:b") + end + end + end + end + + describe "#configure_ssl" do + before { adapter.method(:configure_ssl).call(request, env) } + + context "when version" do + let(:env) { { :ssl => { :version => "a" } } } + + it "sets sslversion" do + expect(request.options[:sslversion]).to eq("a") + end + end + + context "when client_cert" do + let(:env) { { :ssl => { :client_cert => "a" } } } + + it "sets sslcert" do + expect(request.options[:sslcert]).to eq("a") + end + end + + context "when client_key" do + let(:env) { { :ssl => { :client_key => "a" } } } + + it "sets sslkey" do + expect(request.options[:sslkey]).to eq("a") + end + end + + context "when ca_file" do + let(:env) { { :ssl => { :ca_file => "a" } } } + + it "sets cainfo" do + expect(request.options[:cainfo]).to eq("a") + end + end + + context "when ca_path" do + let(:env) { { :ssl => { :ca_path => "a" } } } + + it "sets capath" do + expect(request.options[:capath]).to eq("a") + end + end + + context "when client_cert_passwd" do + let(:env) { { :ssl => { :client_cert_passwd => "a" } } } + + it "sets keypasswd to the value of client_cert_passwd" do + expect(request.options[:keypasswd]).to eq("a") + end + end + + context "when client_certificate_password" do + let(:env) { { :ssl => { :client_certificate_password => "a" } } } + + it "sets keypasswd to the value of client_cert_passwd" do + expect(request.options[:keypasswd]).to eq("a") + end + end + + context "when no client_cert_passwd" do + let(:env) { { :ssl => { } } } + + it "does not set keypasswd on options" do + expect(request.options).not_to have_key :keypasswd + end + end + + context "when verify is false" do + let(:env) { { :ssl => { :verify => false } } } + + it "sets ssl_verifyhost to 0" do + expect(request.options[:ssl_verifyhost]).to eq(0) + end + + it "sets ssl_verifypeer to false" do + expect(request.options[:ssl_verifypeer]).to be_falsey + end + end + + context "when verify is true" do + let(:env) { { :ssl => { :verify => true } } } + + it "sets ssl_verifyhost to 2" do + expect(request.options[:ssl_verifyhost]).to eq(2) + end + + it "sets ssl_verifypeer to true" do + expect(request.options[:ssl_verifypeer]).to be_truthy + end + end + end + + describe "#parallel?" do + context "when parallel_manager" do + let(:env) { { :parallel_manager => true } } + + it "returns true" do + expect(adapter.method(:parallel?).call(env)).to be_truthy + end + end + + context "when no parallel_manager" do + let(:env) { { :parallel_manager => nil } } + + it "returns false" do + expect(adapter.method(:parallel?).call(env)).to be_falsey + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/dalli_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/dalli_spec.rb new file mode 100644 index 000000000..1ea2ce0af --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/dalli_spec.rb @@ -0,0 +1,41 @@ +if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("1.9.0") + require 'dalli' + require 'typhoeus/cache/dalli' + require 'spec_helper' + + describe Typhoeus::Cache::Dalli do + let(:dalli) { instance_double(Dalli::Client) } + let(:cache) { Typhoeus::Cache::Dalli.new(dalli) } + + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } + let(:response) { Typhoeus::Response.new(:response_code => 0, :return_code => 0, :mock => true) } + + describe "#set" do + it "sends the request to Dalli" do + expect(dalli).to receive(:set).with(request.cache_key, response, nil) + + cache.set(request, response) + end + end + + describe "#get" do + it "returns nil when the key is not in the cache" do + expect(dalli).to receive(:get).with(request.cache_key).and_return(nil) + + expect(cache.get(request)).to be_nil + end + + it "returns the cached response when the key is in cache" do + expect(dalli).to receive(:get).with(request.cache_key).and_return(response) + + result = cache.get(request) + expect(result).to_not be_nil + expect(result.response_code).to eq(response.response_code) + expect(result.return_code).to eq(response.return_code) + expect(result.headers).to eq(response.headers) + expect(result.body).to eq(response.body) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/redis_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/redis_spec.rb new file mode 100644 index 000000000..9ee5941c7 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/cache/redis_spec.rb @@ -0,0 +1,41 @@ +require 'redis' +require 'typhoeus/cache/redis' +require 'spec_helper' + +describe Typhoeus::Cache::Redis do + let(:redis) { instance_double(Redis) } + let(:cache) { Typhoeus::Cache::Redis.new(redis) } + + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } + let(:response) { Typhoeus::Response.new(:response_code => 0, :return_code => 0, :mock => true) } + let(:serialized_response) { Marshal.dump(response) } + + describe "#set" do + it "sends the serialized request to Redis" do + expect(redis).to receive(:set).with(request.cache_key, serialized_response) + expect(redis).to_not receive(:expire).with(request.cache_key, request.cache_ttl) + + cache.set(request, response) + end + end + + describe "#get" do + it "returns nil when the key is not in Redis" do + expect(redis).to receive(:get).with(request.cache_key).and_return(nil) + + expect(cache.get(request)).to be_nil + end + + it "returns the cached response when the key is in Redis" do + expect(redis).to receive(:get).with(request.cache_key).and_return(serialized_response) + + result = cache.get(request) + expect(result).to_not be_nil + expect(result.response_code).to eq(response.response_code) + expect(result.return_code).to eq(response.return_code) + expect(result.headers).to eq(response.headers) + expect(result.body).to eq(response.body) + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/config_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/config_spec.rb new file mode 100644 index 000000000..ac721c582 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/config_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Typhoeus::Config do + let(:config) { Typhoeus::Config } + + [:block_connection, :memoize, :verbose, :cache, :user_agent, :proxy].each do |name| + it "responds to #{name}" do + expect(config).to respond_to(name) + end + + it "responds to #{name}=" do + expect(config).to respond_to("#{name}=") + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/easy_factory_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/easy_factory_spec.rb new file mode 100644 index 000000000..cc1e9bc0b --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/easy_factory_spec.rb @@ -0,0 +1,143 @@ +require 'spec_helper' + +describe Typhoeus::EasyFactory do + let(:base_url) { "http://localhost:3001" } + let(:hydra) { Typhoeus::Hydra.new(:max_concurrency => 1) } + let(:options) { {} } + let(:request) { Typhoeus::Request.new(base_url, options) } + let(:easy_factory) { described_class.new(request, hydra) } + + describe "#get" do + context "when option[:cache_ttl]" do + let(:options) { {:cache_ttl => 1} } + + it "creates Ethon::Easy" do + expect(easy_factory.get).to be_a(Ethon::Easy) + end + end + + context "timeouts" do + it "sets nosignal to true by default" do + expect(easy_factory.easy).to receive(:http_request).with(anything(), anything(), hash_including(:nosignal => true)) + easy_factory.get + end + + context "when timeout is not a whole number and timeout_ms is not set" do + let(:options) { {:timeout => 0.1} } + it "ceils timeout and sets timeout_ms" do + expect(easy_factory.easy).to receive(:http_request).with(anything(), anything(), hash_including(:timeout_ms => 100, :timeout => 1)) + easy_factory.get + end + end + + context "when timeout is not a whole number and timeout_ms is set" do + let(:options) { {:timeout => 0.1, :timeout_ms => 123} } + it "ceils timeout and does not change timeout_ms" do + expect(easy_factory.easy).to receive(:http_request).with(anything(), anything(), hash_including(:timeout_ms => 123, :timeout => 1)) + easy_factory.get + end + end + + context "when connecttimeout is not a whole number and connecttimeout_ms is not set" do + let(:options) { {:connecttimeout => 0.1} } + it "ceils connecttimeout and sets connecttimeout_ms" do + expect(easy_factory.easy).to receive(:http_request).with(anything(), anything(), hash_including(:connecttimeout_ms => 100, :connecttimeout => 1)) + easy_factory.get + end + end + + context "when connecttimeout is not a whole number and connecttimeout_ms is set" do + let(:options) { {:connecttimeout => 0.1, :connecttimeout_ms => 123} } + it "ceils connecttimeout and does not change connecttimeout_ms" do + expect(easy_factory.easy).to receive(:http_request).with(anything(), anything(), hash_including(:connecttimeout_ms => 123, :connecttimeout => 1)) + easy_factory.get + end + end + + + end + + context "when invalid option" do + let(:options) { {:invalid => 1} } + + it "reraises" do + expect{ easy_factory.get }.to raise_error(Ethon::Errors::InvalidOption) + end + end + + context "when removed option" do + let(:options) { {:cache_timeout => 1} } + + it "reraises with help" do + expect{ easy_factory.get }.to raise_error( + Ethon::Errors::InvalidOption, /The option cache_timeout was removed/ + ) + end + end + + context "when changed option" do + let(:options) { {:proxy_auth_method => 1} } + + it "reraises with help" do + expect{ easy_factory.get }.to raise_error( + Ethon::Errors::InvalidOption, /Please try proxyauth instead of proxy_auth_method/ + ) + end + end + + context "when renamed option" do + let(:options) { {:connect_timeout => 1} } + + it "warns" do + expect(easy_factory).to receive(:warn).with( + "Deprecated option connect_timeout. Please use connecttimeout instead." + ) + easy_factory.get + end + + it "passes correct option" do + expect(easy_factory).to receive(:warn) + expect(easy_factory.easy).to receive(:connecttimeout=).with(1) + easy_factory.get + end + end + end + + describe "#set_callback" do + it "sets easy.on_progress callback when an on_progress callback is provided" do + request.on_progress { 1 } + expect(easy_factory.easy).to receive(:on_progress) + easy_factory.send(:set_callback) + end + + it "sets easy.on_complete callback" do + expect(easy_factory.easy).to receive(:on_complete) + easy_factory.send(:set_callback) + end + + it "finishes request" do + easy_factory.send(:set_callback) + expect(request).to receive(:finish) + easy_factory.easy.complete + end + + it "resets easy" do + easy_factory.send(:set_callback) + expect(easy_factory.easy).to receive(:reset) + easy_factory.easy.complete + end + + it "pushes easy back into the pool" do + easy_factory.send(:set_callback) + easy_factory.easy.complete + expect(Typhoeus::Pool.send(:easies)).to include(easy_factory.easy) + end + + it "adds next request" do + easy_factory.hydra.instance_variable_set(:@queued_requests, [request]) + expect(easy_factory.hydra).to receive(:add).with(request) + easy_factory.send(:set_callback) + easy_factory.easy.complete + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/errors/no_stub_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/errors/no_stub_spec.rb new file mode 100644 index 000000000..5815cead4 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/errors/no_stub_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Typhoeus::Errors::NoStub do + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url) } + let(:message) { "The connection is blocked and no stub defined: " } + + subject { Typhoeus::Errors::NoStub } + + it "displays the request url" do + expect { raise subject.new(request) }.to raise_error(subject, message + base_url) + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/expectation_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/expectation_spec.rb new file mode 100644 index 000000000..9dfb2b03d --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/expectation_spec.rb @@ -0,0 +1,280 @@ +require 'spec_helper' + +describe Typhoeus::Expectation do + let(:options) { {} } + let(:base_url) { "www.example.com" } + let(:expectation) { described_class.new(base_url, options) } + + describe ".new" do + it "sets base_url" do + expect(expectation.instance_variable_get(:@base_url)).to eq(base_url) + end + + it "sets options" do + expect(expectation.instance_variable_get(:@options)).to eq(options) + end + + it "initializes response_counter" do + expect(expectation.instance_variable_get(:@response_counter)).to eq(0) + end + end + + describe ".all" do + context "when @expectations nil" do + it "returns empty array" do + expect(Typhoeus::Expectation.all).to eq([]) + end + end + + context "when @expectations not nil" do + let(:expectations) { [1] } + + it "returns @expectations" do + Typhoeus::Expectation.instance_variable_set(:@expectations, expectations) + expect(Typhoeus::Expectation.all).to be(expectations) + end + end + end + + describe ".clear" do + let(:expectations) { double(:clear) } + + it "clears all" do + expect(expectations).to receive(:clear) + Typhoeus::Expectation.instance_variable_set(:@expectations, expectations) + Typhoeus::Expectation.clear + Typhoeus::Expectation.instance_variable_set(:@expectations, nil) + end + end + + describe ".response_for" do + let(:request) { Typhoeus::Request.new("") } + let(:stubbed_response) { Typhoeus::Response.new } + + it "finds a matching expectation and returns its next response" do + Typhoeus::Expectation.all << expectation + expect(expectation).to receive(:matches?).with(request).and_return(true) + expect(expectation).to receive(:response).with(request).and_return(stubbed_response) + + response = Typhoeus::Expectation.response_for(request) + + expect(response).to be(stubbed_response) + end + + it "returns nil if no matching expectation is found" do + response = Typhoeus::Expectation.response_for(request) + expect(response).to be(nil) + end + end + + describe "#stubbed_from" do + it "sets value" do + expectation.stubbed_from(:webmock) + expect(expectation.from).to eq(:webmock) + end + + it "returns self" do + expect(expectation.stubbed_from(:webmock)).to be(expectation) + end + end + + describe "#and_return" do + context "when value" do + it "adds to responses" do + expectation.and_return(1) + expect(expectation.responses).to eq([1]) + end + end + + context "when array" do + it "adds to responses" do + expectation.and_return([1, 2]) + expect(expectation.responses).to eq([1, 2]) + end + end + + context "when block" do + it "adds to responses" do + block = Proc.new {} + expectation.and_return(&block) + expect(expectation.responses).to eq([block]) + end + end + end + + describe "#responses" do + it "returns responses" do + expect(expectation.responses).to be_a(Array) + end + end + + describe "#response" do + let(:request) { Typhoeus::Request.new("") } + + before { expectation.instance_variable_set(:@responses, responses) } + + context "when one response" do + context "is pre-constructed" do + let(:responses) { [Typhoeus::Response.new] } + + it "returns response" do + expect(expectation.response(request)).to be(responses[0]) + end + end + + context "is lazily-constructed" do + def construct_response(request) + @request_from_response_construction = request + lazily_constructed_response + end + + let(:lazily_constructed_response) { Typhoeus::Response.new } + let(:responses) { [ Proc.new { |request| construct_response(request) } ] } + + it "returns response" do + expect(expectation.response(request)).to be(lazily_constructed_response) + expect(@request_from_response_construction).to be(request) + end + end + end + + context "when multiple responses" do + let(:responses) { [Typhoeus::Response.new, Typhoeus::Response.new, Typhoeus::Response.new] } + + it "returns one by one" do + 3.times do |i| + expect(expectation.response(request)).to be(responses[i]) + end + end + end + end + + describe "#matches?" do + let(:request) { double(:base_url => nil) } + + it "calls url_match?" do + expect(expectation).to receive(:url_match?) + expectation.matches?(request) + end + + it "calls options_match?" do + expect(expectation).to receive(:url_match?).and_return(true) + expect(expectation).to receive(:options_match?) + expectation.matches?(request) + end + end + + describe "#url_match?" do + let(:request_url) { "www.example.com" } + let(:request) { Typhoeus::Request.new(request_url) } + let(:url_match) { expectation.method(:url_match?).call(request.base_url) } + + context "when string" do + context "when match" do + it "returns true" do + expect(url_match).to be_truthy + end + end + + context "when no match" do + let(:base_url) { "no_match" } + + it "returns false" do + expect(url_match).to be_falsey + end + end + end + + context "when regexp" do + context "when match" do + let(:base_url) { /example/ } + + it "returns true" do + expect(url_match).to be_truthy + end + end + + context "when no match" do + let(:base_url) { /nomatch/ } + + it "returns false" do + expect(url_match).to be_falsey + end + + context "with nil request_url" do + let(:request_url) { nil } + + it "returns false" do + expect(url_match).to be_falsey + end + end + end + end + + context "when nil" do + let(:base_url) { nil } + + it "returns true" do + expect(url_match).to be_truthy + end + end + + context "when not string, regexp, nil" do + let(:base_url) { 1 } + + it "returns false" do + expect(url_match).to be_falsey + end + end + end + + describe "options_match?" do + let(:request_options) { {} } + let(:request) { Typhoeus::Request.new(nil, request_options) } + let(:options_match) { expectation.method(:options_match?).call(request) } + + context "when match" do + let(:options) { { :a => 1 } } + let(:request_options) { options } + + it "returns true" do + expect(options_match).to be_truthy + end + end + + context "when options are a subset from request_options" do + let(:options) { { :a => 1 } } + let(:request_options) { { :a => 1, :b => 2 } } + + it "returns true" do + expect(options_match).to be_truthy + end + end + + context "when options are nested" do + let(:options) { { :a => { :b => 1 } } } + let(:request_options) { options } + + it "returns true" do + expect(options_match).to be_truthy + end + end + + context "when options contains an array" do + let(:options) { { :a => [1, 2] } } + let(:request_options) { options } + + it "returns true" do + expect(options_match).to be_truthy + end + end + + context "when no match" do + let(:options) { { :a => 1 } } + + it "returns false" do + expect(options_match).to be_falsey + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/addable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/addable_spec.rb new file mode 100644 index 000000000..4cb8e1a1e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/addable_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Addable do + let(:hydra) { Typhoeus::Hydra.new() } + let(:request) { Typhoeus::Request.new("localhost:3001", {:method => :get}) } + + it "asks easy factory for an easy" do + multi = double + expect(Typhoeus::EasyFactory).to receive(:new).with(request, hydra).and_return(double(:get => 1)) + expect(hydra).to receive(:multi).and_return(multi) + expect(multi).to receive(:add).with(1) + hydra.add(request) + end + + it "adds easy to multi" do + multi = double + expect(Typhoeus::EasyFactory).to receive(:new).with(request, hydra).and_return(double(:get => 1)) + expect(hydra).to receive(:multi).and_return(multi) + expect(multi).to receive(:add).with(1) + hydra.add(request) + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/before_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/before_spec.rb new file mode 100644 index 000000000..e17e0438d --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/before_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Before do + let(:request) { Typhoeus::Request.new("") } + let(:hydra) { Typhoeus::Hydra.new } + let(:receive_counter) { double :mark => :twain } + + describe "#add" do + context "when before" do + context "when one" do + it "executes" do + Typhoeus.before { |r| receive_counter.mark } + expect(receive_counter).to receive(:mark) + hydra.add(request) + end + + context "when true" do + it "calls super" do + Typhoeus.before { true } + expect(Typhoeus::Expectation).to receive(:response_for) + hydra.add(request) + end + end + + context "when falsy" do + context "when queue requests" do + let(:queued_request) { Typhoeus::Request.new("") } + + before { hydra.queue(queued_request) } + + it "dequeues" do + Typhoeus.before { false } + hydra.add(request) + expect(hydra.queued_requests).to be_empty + end + end + + context "when false" do + it "doesn't call super" do + Typhoeus.before { false } + expect(Typhoeus::Expectation).to receive(:response_for).never + hydra.add(request) + end + end + + context "when response" do + it "doesn't call super" do + Typhoeus.before { Typhoeus::Response.new } + expect(Typhoeus::Expectation).to receive(:response_for).never + hydra.add(request) + end + end + end + end + + context "when multi" do + context "when all true" do + before { 3.times { Typhoeus.before { |r| receive_counter.mark } } } + + it "calls super" do + expect(Typhoeus::Expectation).to receive(:response_for) + hydra.add(request) + end + + it "executes all" do + expect(receive_counter).to receive(:mark).exactly(3).times + hydra.add(request) + end + end + + context "when middle false" do + before do + Typhoeus.before { |r| receive_counter.mark } + Typhoeus.before { |r| receive_counter.mark; nil } + Typhoeus.before { |r| receive_counter.mark } + end + + it "doesn't call super" do + expect(Typhoeus::Expectation).to receive(:response_for).never + hydra.add(request) + end + + it "executes only two" do + expect(receive_counter).to receive(:mark).exactly(2).times + hydra.add(request) + end + end + end + end + + context "when no before" do + it "calls super" do + expect(Typhoeus::Expectation).to receive(:response_for) + hydra.add(request) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/block_connection_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/block_connection_spec.rb new file mode 100644 index 000000000..df3e94546 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/block_connection_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::BlockConnection do + let(:base_url) { "localhost:3001" } + let(:hydra) { Typhoeus::Hydra.new() } + let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } + + describe "add" do + context "when block_connection activated" do + before { Typhoeus::Config.block_connection = true } + after { Typhoeus::Config.block_connection = false } + + it "raises" do + expect{ hydra.add(request) }.to raise_error(Typhoeus::Errors::NoStub) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/cacheable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/cacheable_spec.rb new file mode 100644 index 000000000..6e2f0ab69 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/cacheable_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Cacheable do + let(:base_url) { "localhost:3001" } + let(:hydra) { Typhoeus::Hydra.new() } + let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } + let(:response) { Typhoeus::Response.new } + let(:cache) { MemoryCache.new } + + describe "add" do + context "when cache activated" do + before { Typhoeus::Config.cache = cache } + after { Typhoeus::Config.cache = false } + + context "when request new" do + it "sets no response" do + hydra.add(request) + expect(request.response).to be_nil + end + + it "doesn't call complete" do + expect(request).to receive(:complete).never + hydra.add(request) + end + end + + context "when request in memory" do + before { cache.memory[request] = response } + + it "returns response with cached status" do + hydra.add(request) + expect(response.cached?).to be_truthy + end + + context "when no queued requests" do + it "finishes request" do + expect(request).to receive(:finish).with(response) + hydra.add(request) + expect(response.cached?).to be_truthy + end + end + + context "when queued requests" do + let(:queued_request) { Typhoeus::Request.new(base_url, {:method => :get}) } + + before { cache.memory[queued_request] = response } + + it "finishes both requests" do + hydra.queue(queued_request) + expect(request).to receive(:finish).with(response) + expect(queued_request).to receive(:finish).with(response) + hydra.add(request) + end + end + end + + context "when cache is specified on a request" do + before { Typhoeus::Config.cache = false } + + context "when cache is false" do + let(:non_cached_request) { Typhoeus::Request.new(base_url, {:method => :get, :cache => false}) } + + it "initiates an HTTP call" do + expect(Typhoeus::EasyFactory).to receive(:new).with(non_cached_request, hydra).and_call_original + + hydra.add(non_cached_request) + end + end + + context "when cache is defined" do + let(:cached_request) { Typhoeus::Request.new(base_url, {:method => :get, :cache => cache}) } + + before { cache.memory[cached_request] = response } + + it "uses the cache instead of making a new request" do + expect(Typhoeus::EasyFactory).not_to receive(:new) + + hydra.add(cached_request) + + expect(cached_request.response).to be_cached + expect(cached_request.response).to eq(response) + end + end + end + + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/memoizable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/memoizable_spec.rb new file mode 100644 index 000000000..c04f2998a --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/memoizable_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Memoizable do + let(:base_url) { "localhost:3001" } + let(:hydra) { Typhoeus::Hydra.new() } + let(:request) { Typhoeus::Request.new(base_url) } + + describe "add" do + context "when memoization activated" do + before { Typhoeus::Config.memoize = true } + + context "when request new" do + it "sets no response" do + hydra.add(request) + expect(request.response).to be_nil + end + + it "doesn't call complete" do + expect(request).to receive(:complete).never + hydra.add(request) + end + end + + context "when request in memory" do + let(:response) { Typhoeus::Response.new } + before { hydra.memory[request] = response } + + it "finishes request" do + expect(request).to receive(:finish).with(response, true) + hydra.add(request) + end + + context "when queued request" do + let(:queued_request) { Typhoeus::Request.new(base_url) } + + it "dequeues" do + hydra.queue(queued_request) + expect(request).to receive(:finish).with(response, true) + expect(queued_request).to receive(:finish).with(response, true) + hydra.add(request) + end + end + end + end + end + + describe "#run" do + it "clears memory before starting" do + expect(hydra.memory).to receive(:clear) + hydra.run + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/queueable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/queueable_spec.rb new file mode 100644 index 000000000..d9fc87ade --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/queueable_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Queueable do + let(:base_url) { "localhost:3001" } + let(:options) { {} } + let(:hydra) { Typhoeus::Hydra.new(options) } + + describe "#queue" do + let(:request) { Typhoeus::Request.new("") } + + it "accepts requests" do + hydra.queue(request) + end + + it "sets hydra on request" do + hydra.queue(request) + expect(request.hydra).to eq(hydra) + end + + it "adds to queued requests" do + hydra.queue(request) + expect(hydra.queued_requests).to include(request) + end + + it "adds to front of queued requests" do + hydra.queue_front(request) + expect(hydra.queued_requests.first).to be(request) + end + end + + describe "#abort" do + before { hydra.queued_requests << 1 } + + it "clears queue" do + hydra.abort + expect(hydra.queued_requests).to be_empty + end + end + + describe "#dequeue_many" do + before do + requests.each { |r| hydra.queue r } + end + + context "when no request queued" do + let(:requests) { [] } + + it "does nothing" do + expect(hydra).to_not receive(:add) + hydra.dequeue_many + end + end + + context "when request queued" do + let(:first) { Typhoeus::Request.new("localhost:3001/first") } + let(:requests) { [first] } + + it "adds request from queue to multi" do + expect(hydra).to receive(:add).with(first) + hydra.dequeue_many + end + end + + context "when three request queued" do + let(:first) { Typhoeus::Request.new("localhost:3001/first") } + let(:second) { Typhoeus::Request.new("localhost:3001/second") } + let(:third) { Typhoeus::Request.new("localhost:3001/third") } + let(:requests) { [first, second, third] } + + it "adds requests from queue to multi" do + expect(hydra).to receive(:add).with(first) + expect(hydra).to receive(:add).with(second) + expect(hydra).to receive(:add).with(third) + hydra.dequeue_many + end + + context "when max_concurrency is two" do + let(:options) { {:max_concurrency => 2} } + it "adds requests from queue to multi" do + expect(hydra).to receive(:add).with(first) + expect(hydra).to receive(:add).with(second) + expect(hydra).to_not receive(:add).with(third) + hydra.dequeue_many + end + end + + context "when max_concurrency is a string" do + let(:options) { {:max_concurrency => "2"} } + it "adds requests from queue to multi" do + expect(hydra).to receive(:add).with(first) + expect(hydra).to receive(:add).with(second) + expect(hydra).to_not receive(:add).with(third) + hydra.dequeue_many + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/runnable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/runnable_spec.rb new file mode 100644 index 000000000..1e0237e23 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/runnable_spec.rb @@ -0,0 +1,137 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Runnable do + let(:base_url) { "localhost:3001" } + let(:options) { {} } + let(:hydra) { Typhoeus::Hydra.new(options) } + let(:receive_counter) { double :mark => :twain } + + describe "#run" do + let(:requests) { [] } + + before do + requests.each { |r| hydra.queue r } + end + + it "runs multi#dequeue_many" do + expect(hydra).to receive(:dequeue_many) + hydra.run + end + + it "runs multi#perform" do + expect(hydra.multi).to receive(:perform) + hydra.run + end + + context "when request queued" do + let(:first) { Typhoeus::Request.new("localhost:3001/first") } + let(:requests) { [first] } + + it "sends" do + hydra.run + expect(first.response).to be + end + end + + context "when three request queued" do + let(:first) { Typhoeus::Request.new("localhost:3001/first") } + let(:second) { Typhoeus::Request.new("localhost:3001/second") } + let(:third) { Typhoeus::Request.new("localhost:3001/third") } + let(:requests) { [first, second, third] } + + it "sends first" do + hydra.run + expect(first.response).to be + end + + it "sends second" do + hydra.run + expect(second.response).to be + end + + it "sends third" do + hydra.run + expect(third.response).to be + end + + it "sends first first" do + first.on_complete do + expect(second.response).to be_nil + expect(third.response).to be_nil + end + end + + it "sends second second" do + first.on_complete do + expect(first.response).to be + expect(third.response).to be_nil + end + end + + it "sends thirds last" do + first.on_complete do + expect(second.response).to be + expect(third.response).to be + end + end + end + + context "when really queued request" do + let(:options) { {:max_concurrency => 1} } + let(:first) { Typhoeus::Request.new("localhost:3001/first") } + let(:second) { Typhoeus::Request.new("localhost:3001/second") } + let(:third) { Typhoeus::Request.new("localhost:3001/third") } + let(:requests) { [first, second, third] } + + it "sends first" do + hydra.run + expect(first.response).to be + end + + it "sends second" do + hydra.run + expect(second.response).to be + end + + it "sends third" do + hydra.run + expect(third.response).to be + end + end + + context "when request queued in callback" do + let(:first) do + Typhoeus::Request.new("localhost:3001/first").tap do |r| + r.on_complete{ hydra.queue(second) } + end + end + let(:second) { Typhoeus::Request.new("localhost:3001/second") } + let(:requests) { [first] } + + before { Typhoeus.on_complete { |r| receive_counter.mark } } + after { Typhoeus.on_complete.clear; Typhoeus.before.clear } + + context "when real request" do + context "when max_concurrency default" do + let(:options) { {} } + + it "calls on_complete callback once for every response" do + expect(receive_counter).to receive(:mark).exactly(2).times + hydra.run + end + end + end + + context "when no real request" do + context "when before hook returns and finishes response" do + before { Typhoeus.before{ |request| request.finish(Typhoeus::Response.new) } } + + it "simulates real multi run and adds and finishes both requests" do + expect(receive_counter).to receive(:mark).exactly(2).times + hydra.run + end + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/stubbable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/stubbable_spec.rb new file mode 100644 index 000000000..6b64cc018 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra/stubbable_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe Typhoeus::Hydra::Stubbable do + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url) } + let(:response) { Typhoeus::Response.new } + let(:hydra) { Typhoeus::Hydra.new } + + before { Typhoeus.stub(base_url).and_return(response) } + + describe "#add" do + it "checks expectations" do + hydra.add(request) + end + + context "when expectation found" do + it "calls on_headers callbacks" do + canary = :not_called + request.on_headers do + canary = :called + end + hydra.add(request) + hydra.run + expect(canary).to eq(:called) + end + + it "calls on_body callbacks" do + canary = :not_called + request.on_body do + canary = :called + end + hydra.add(request) + hydra.run + expect(canary).to eq(:called) + end + + it "finishes response" do + expect(request).to receive(:finish) + hydra.add(request) + end + + it "is a mock" do + hydra.add(request) + expect(request.response.mock).to be(true) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra_spec.rb new file mode 100644 index 000000000..a8a35aa15 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/hydra_spec.rb @@ -0,0 +1,22 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Typhoeus::Hydra do + let(:base_url) { "localhost:3001" } + let(:options) { {} } + let(:hydra) { Typhoeus::Hydra.new(options) } + + describe "#new" do + let(:options) { {:pipeling => true} } + + it "passes options to multi" do + expect(Ethon::Multi).to receive(:new).with(options) + hydra + end + end + + describe "#hydra" do + it "returns a hydra" do + expect(Typhoeus::Hydra.hydra).to be_a(Typhoeus::Hydra) + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/pool_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/pool_spec.rb new file mode 100644 index 000000000..b04f433e1 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/pool_spec.rb @@ -0,0 +1,137 @@ +require 'spec_helper' + +describe Typhoeus::Pool do + let(:easy) { Ethon::Easy.new } + after { Typhoeus::Pool.clear } + + describe "#easies" do + it "returns array" do + expect(Typhoeus::Pool.send(:easies)).to be_a(Array) + end + end + + describe "#release" do + it "resets easy" do + expect(easy).to receive(:reset) + Typhoeus::Pool.release(easy) + end + + it "flush cookies to disk" do + expect(easy).to receive(:cookielist=).with('flush') + expect(easy).to receive(:reset) + expect(easy).to receive(:cookielist=).with('all') + Typhoeus::Pool.release(easy) + end + + it "writes cookies to disk" do + tempfile1 = Tempfile.new('cookies') + tempfile2 = Tempfile.new('cookies') + + easy.cookiejar = tempfile1.path + easy.url = "localhost:3001/cookies-test" + easy.perform + + Typhoeus::Pool.release(easy) + + expect(File.zero?(tempfile1.path)).to be(false) + expect(File.read(tempfile1.path)).to match(/\s+foo\s+bar$/) + expect(File.read(tempfile1.path)).to match(/\s+bar\s+foo$/) + + # do it again - and check if tempfile1 wasn't change + easy.cookiejar = tempfile2.path + easy.url = "localhost:3001/cookies-test2" + easy.perform + + Typhoeus::Pool.release(easy) + + # tempfile 1 + expect(File.zero?(tempfile1.path)).to be(false) + expect(File.read(tempfile1.path)).to match(/\s+foo\s+bar$/) + expect(File.read(tempfile1.path)).to match(/\s+bar\s+foo$/) + + # tempfile2 + expect(File.zero?(tempfile2.path)).to be(false) + expect(File.read(tempfile2.path)).to match(/\s+foo2\s+bar$/) + expect(File.read(tempfile2.path)).to match(/\s+bar2\s+foo$/) + end + + it "puts easy back into pool" do + Typhoeus::Pool.release(easy) + expect(Typhoeus::Pool.send(:easies)).to include(easy) + end + + context "when threaded access" do + it "releases correct number of easies" do + (0..9).map do |n| + Thread.new do + Typhoeus::Pool.release(Ethon::Easy.new) + end + end.map(&:join) + expect(Typhoeus::Pool.send(:easies).size).to eq(10) + end + end + end + + describe "#get" do + context "when easy in pool" do + before { Typhoeus::Pool.send(:easies) << easy } + + it "takes" do + expect(Typhoeus::Pool.get).to eq(easy) + end + end + + context "when no easy in pool" do + it "creates" do + expect(Typhoeus::Pool.get).to be_a(Ethon::Easy) + end + + context "when threaded access" do + it "creates correct number of easies" do + queue = Queue.new + (0..9).map do |n| + Thread.new do + queue.enq(Typhoeus::Pool.get) + end + end.map(&:join) + + array = Array.new(queue.size) { queue.pop } + expect(array.uniq.size).to eq(10) + end + end + end + + context "when forked" do + before do + allow(Process).to receive(:pid).and_return(1) + Typhoeus::Pool.send(:easies) << easy + allow(Process).to receive(:pid).and_return(2) + end + + after do + allow(Process).to receive(:pid).and_call_original + Typhoeus::Pool.instance_variable_set(:@pid, Process.pid) + end + + it "creates" do + expect(Typhoeus::Pool.get).to_not eq(easy) + end + end + end + + describe "#with" do + it "is re-entrant" do + array = [] + Typhoeus::Pool.with_easy do |e1| + array << e1 + Typhoeus::Pool.with_easy do |e2| + array << e2 + Typhoeus::Pool.with_easy do |e3| + array << e3 + end + end + end + expect(array.uniq.size).to eq(3) + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/actions_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/actions_spec.rb new file mode 100644 index 000000000..03493e10f --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/actions_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe Typhoeus::Request::Actions do + [:get, :post, :put, :delete, :head, :patch, :options].each do |name| + describe ".#{name}" do + let(:response) { Typhoeus::Request.method(name).call("http://localhost:3001") } + + it "returns ok" do + expect(response.return_code).to eq(:ok) + end + + unless name == :head + it "makes #{name.to_s.upcase} Request" do + expect(response.response_body).to include("\"REQUEST_METHOD\":\"#{name.to_s.upcase}\"") + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/before_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/before_spec.rb new file mode 100644 index 000000000..ed39b0c9e --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/before_spec.rb @@ -0,0 +1,93 @@ +require 'spec_helper' + +describe Typhoeus::Request::Before do + let(:request) { Typhoeus::Request.new("") } + let(:receive_counter) { double :mark => :twain } + + describe "#queue" do + context "when before" do + context "when one" do + it "executes" do + Typhoeus.before { |r| receive_counter.mark } + expect(receive_counter).to receive(:mark) + request.run + end + + context "when true" do + it "calls super" do + Typhoeus.before { true } + expect(Typhoeus::Expectation).to receive(:response_for) + request.run + end + end + + context "when false" do + it "doesn't call super" do + Typhoeus.before { false } + expect(Typhoeus::Expectation).to receive(:response_for).never + request.run + end + + it "returns response" do + Typhoeus.before { |r| r.response = 1; false } + expect(request.run).to be(1) + end + end + + context "when a response" do + it "doesn't call super" do + Typhoeus.before { Typhoeus::Response.new } + expect(Typhoeus::Expectation).to receive(:response_for).never + request.run + end + + it "returns response" do + Typhoeus.before { |r| r.response = Typhoeus::Response.new } + expect(request.run).to be_a(Typhoeus::Response) + end + end + end + + context "when multi" do + context "when all true" do + before { 3.times { Typhoeus.before { |r| receive_counter.mark } } } + + it "calls super" do + expect(Typhoeus::Expectation).to receive(:response_for) + request.run + end + + it "executes all" do + expect(receive_counter).to receive(:mark).exactly(3) + request.run + end + end + + context "when middle false" do + before do + Typhoeus.before { |r| receive_counter.mark } + Typhoeus.before { |r| receive_counter.mark; nil } + Typhoeus.before { |r| receive_counter.mark } + end + + it "doesn't call super" do + expect(Typhoeus::Expectation).to receive(:response_for).never + request.run + end + + it "executes only two" do + expect(receive_counter).to receive(:mark).exactly(2).times + request.run + end + end + end + end + + context "when no before" do + it "calls super" do + expect(Typhoeus::Expectation).to receive(:response_for) + request.run + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/block_connection_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/block_connection_spec.rb new file mode 100644 index 000000000..2ddacdcae --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/block_connection_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +describe Typhoeus::Request::BlockConnection do + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } + + describe "run" do + context "when blocked" do + before { request.block_connection = true } + + it "raises" do + expect{ request.run }.to raise_error(Typhoeus::Errors::NoStub) + end + end + + context "when not blocked" do + before { request.block_connection = false } + + it "doesn't raise" do + expect{ request.run }.to_not raise_error + end + end + end + + describe "#blocked?" do + context "when local block_connection" do + context "when true" do + before { request.block_connection = true } + + it "returns true" do + expect(request.blocked?).to be_truthy + end + end + + context "when false" do + before { request.block_connection = false } + + it "returns false" do + expect(request.blocked?).to be_falsey + end + end + end + + context "when global block_connection" do + context "when true" do + before { Typhoeus::Config.block_connection = true } + after { Typhoeus::Config.block_connection = false } + + it "returns true" do + expect(request.blocked?).to be_truthy + end + end + + context "when false" do + before { Typhoeus::Config.block_connection = false } + + it "returns false" do + expect(request.blocked?).to be_falsey + end + end + end + + context "when global and local block_connection" do + before do + Typhoeus::Config.block_connection = true + request.block_connection = false + end + after { Typhoeus::Config.block_connection = false } + + it "takes local" do + expect(request.blocked?).to be_falsey + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/cacheable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/cacheable_spec.rb new file mode 100644 index 000000000..bffa3e4d4 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/cacheable_spec.rb @@ -0,0 +1,94 @@ +require 'spec_helper' + +describe Typhoeus::Request::Cacheable do + let(:cache) { MemoryCache.new } + let(:options) { {} } + let(:request) { Typhoeus::Request.new("http://localhost:3001", options) } + let(:response) { Typhoeus::Response.new } + + before { Typhoeus::Config.cache = cache } + after { Typhoeus::Config.cache = false } + + describe "#response=" do + context "when cache activated" do + context "when request new" do + it "caches response" do + request.response = response + expect(cache.memory[request]).to be + end + + it "doesn't set cached on response" do + request.response = response + expect(request.response.cached?).to be_falsey + end + end + + context "when request in memory" do + before { cache.memory[request] = response } + + it "finishes request" do + expect(request).to receive(:finish).with(response) + request.run + end + + it "sets cached to true for response" do + request.run + expect(request.response.cached?).to be_truthy + end + end + end + end + + describe "#run" do + context "when cache activated" do + context "when request new" do + it "fetches response" do + expect(request.response).to_not be(response) + end + end + + context "when request in memory" do + before { cache.memory[request] = response } + + it "finishes request" do + expect(request).to receive(:finish).with(response) + request.run + end + end + + context "when cache is specified on a request" do + before { Typhoeus::Config.cache = false } + + context "when cache is false" do + let(:options) { { :cache => false } } + + it "finishes request" do + expect(request.response).to_not be(response) + request.run + end + end + + context "when cache is defined" do + let(:options) { { :cache => cache } } + + before { cache.memory[request] = response } + + it "finishes request" do + expect(request).to receive(:finish).with(response) + request.run + end + end + end + end + end + + describe "#cache_ttl" do + context "when option[:cache_ttl]" do + let(:options) { {:cache_ttl => 1} } + + it "returns" do + expect(request.cache_ttl).to be(1) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/callbacks_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/callbacks_spec.rb new file mode 100644 index 000000000..9b30e74b0 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/callbacks_spec.rb @@ -0,0 +1,91 @@ +require 'spec_helper' + +describe Typhoeus::Request::Callbacks do + let(:request) { Typhoeus::Request.new("fubar") } + + [:on_complete, :on_success, :on_failure, :on_progress].each do |callback| + describe "##{callback}" do + it "responds" do + expect(request).to respond_to(callback) + end + + context "when no block given" do + it "returns @#{callback}" do + expect(request.method(callback).call).to eq([]) + end + end + + context "when block given" do + it "stores" do + request.method(callback).call { p 1 } + expect(request.instance_variable_get("@#{callback}").size).to eq(1) + end + end + + context "when multiple blocks given" do + it "stores" do + request.method(callback).call { p 1 } + request.method(callback).call { p 2 } + expect(request.instance_variable_get("@#{callback}").size).to eq(2) + end + end + end + end + + describe "#execute_callbacks" do + [:on_complete, :on_success, :on_failure, :on_progress].each do |callback| + context "when #{callback}" do + context "when local callback" do + before do + code = if callback == :on_failure + 500 + else + 200 + end + request.response = Typhoeus::Response.new(:mock => true, :response_code => code) + request.method(callback).call {|r| expect(r).to be_a(Typhoeus::Response) } + end + + it "executes blocks and passes response" do + request.execute_callbacks + end + + it "sets handled_response" do + request.method(callback).call { 1 } + request.execute_callbacks + expect(request.response.handled_response).to be(1) + end + end + + context "when global callback" do + before do + request.response = Typhoeus::Response.new + Typhoeus.method(callback).call {|r| expect(r).to be_a(Typhoeus::Response) } + end + + it "executes blocks and passes response" do + request.execute_callbacks + end + end + + context "when global and local callbacks" do + before do + request.response = Typhoeus::Response.new + Typhoeus.method(callback).call {|r| r.instance_variable_set(:@fu, 1) } + request.method(callback).call {|r| expect(r.instance_variable_get(:@fu)).to eq(1) } + end + + it "runs global first" do + request.execute_callbacks + end + end + end + end + + context "when local on_complete and gobal on_success" do + it "runs all global callbacks first" do + skip + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/marshal_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/marshal_spec.rb new file mode 100644 index 000000000..6ab922a57 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/marshal_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe Typhoeus::Request::Marshal do + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url) } + + describe "#marshal_dump" do + %w(on_complete on_success on_failure on_progress).each do |name| + context "when #{name} handler" do + before { request.instance_variable_set("@#{name}", Proc.new{}) } + + it "doesn't include @#{name}" do + expect(request.send(:marshal_dump).map(&:first)).to_not include("@#{name}") + end + + it "doesn't raise when dumped" do + expect { Marshal.dump(request) }.to_not raise_error + end + + context "when loading" do + let(:loaded) { Marshal.load(Marshal.dump(request)) } + + it "includes base_url" do + expect(loaded.base_url).to eq(request.base_url) + end + + it "doesn't include #{name}" do + expect(loaded.instance_variables).to_not include("@#{name}") + end + end + end + end + + context 'when run through hydra' do + let(:options) { {} } + let(:hydra) { Typhoeus::Hydra.new(options) } + + before(:each) do + hydra.queue(request) + hydra.run + end + + it "doesn't include @hydra" do + expect(request.send(:marshal_dump).map(&:first)).to_not include("@hydra") + end + + context 'when loading' do + let(:loaded) { Marshal.load(Marshal.dump(request)) } + + it "includes base_url" do + expect(loaded.base_url).to eq(request.base_url) + end + + it "doesn't include #{name}" do + expect(loaded.instance_variables).to_not include("@hydra") + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/memoizable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/memoizable_spec.rb new file mode 100644 index 000000000..1bb7ebcab --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/memoizable_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Typhoeus::Request::Memoizable do + let(:options) { {} } + let(:request) { Typhoeus::Request.new("fu", options) } + let(:response) { Typhoeus::Response.new } + let(:hydra) { Typhoeus::Hydra.new } + + describe "#response=" do + context "when memoization activated" do + before { Typhoeus::Config.memoize = true } + after { Typhoeus::Config.memoize = false } + + context "when GET request" do + let(:options) { {:method => :get} } + before { request.hydra = hydra } + + it "stores response in memory" do + request.response = response + expect(hydra.memory[request]).to be + end + end + + context "when no GET request" do + let(:options) { {:method => :post} } + + it "doesn't store response in memory" do + request.response = response + expect(hydra.memory[request]).to be_nil + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/operations_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/operations_spec.rb new file mode 100644 index 000000000..79f6be0ea --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/operations_spec.rb @@ -0,0 +1,101 @@ +require 'spec_helper' + +describe Typhoeus::Request::Operations do + let(:base_url) { "localhost:3001" } + let(:options) { {} } + let(:request) { Typhoeus::Request.new(base_url, options) } + + describe "#run" do + let(:easy) { Ethon::Easy.new } + before { expect(Typhoeus::Pool).to receive(:get).and_return(easy) } + + it "grabs an easy" do + request.run + end + + it "generates settings" do + expect(easy).to receive(:http_request) + request.run + end + + it "performs" do + expect(easy).to receive(:perform) + request.run + end + + it "sets response" do + request.run + expect(request.response).to be + end + + it "releases easy" do + expect(Typhoeus::Pool).to receive(:release) + request.run + end + + it "calls on_body" do + on_body_called = false + request.on_body { |body, response| on_body_called = true } + request.run + expect(on_body_called).to be_truthy + expect(request.response.body).to satisfy { |v| v.nil? || v == '' } + end + + it "makes response headers available to on_body" do + headers = nil + request.on_body { |body, response| headers = response.headers } + request.run + expect(headers).to be + expect(headers).to eq(request.response.headers) + end + + it "calls on_headers and on_body" do + headers = nil + request.on_headers { |response| headers = response.headers } + request.on_body { |body, response| expect(headers).not_to be_nil ; expect(response.headers).to eq(headers) } + request.on_complete { |response| expect(response).not_to be_nil ; expect(response.headers).to eq(headers) ; expect(response.body).to be_empty } + request.run + end + + it "calls on_headers and on_complete" do + headers = nil + request.on_headers { |response| headers = response.headers } + request.on_complete { |response| expect(response).not_to be_nil ; expect(response.headers).to eq(headers) ; expect(response.body).not_to be_empty } + request.run + end + + it "calls on_complete" do + callback = double(:call) + expect(callback).to receive(:call) + request.instance_variable_set(:@on_complete, [callback]) + request.run + end + + it "returns a response" do + expect(request.run).to be_a(Typhoeus::Response) + end + end + + describe "#finish" do + let(:response) { Typhoeus::Response.new } + + it "assigns response" do + request.finish(response) + expect(request.response).to be(response) + end + + it "assigns request to response" do + request.finish(response) + expect(request.response.request).to be(request) + end + + it "executes callbacks" do + expect(request).to receive(:execute_callbacks) + request.finish(response) + end + + it "returns response" do + expect(request.finish(response)).to be(response) + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/responseable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/responseable_spec.rb new file mode 100644 index 000000000..01087bc83 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/responseable_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Typhoeus::Request::Responseable do + let(:request) { Typhoeus::Request.new("base_url", {}) } + let(:response) { Typhoeus::Response.new } + + describe "#response=" do + it "stores response" do + request.response = response + expect(request.response).to eq(response) + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/stubbable_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/stubbable_spec.rb new file mode 100644 index 000000000..4651d5fb9 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request/stubbable_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe Typhoeus::Request::Stubbable do + let(:base_url) { "localhost:3001" } + let(:request) { Typhoeus::Request.new(base_url) } + let(:response) { Typhoeus::Response.new } + + before { Typhoeus.stub(base_url).and_return(response) } + + describe "#run" do + it "checks expectations" do + request.run + end + + context "when expectation found" do + it "calls on_headers callbacks" do + canary = :not_called + request.on_headers do + canary = :called + end + request.run + expect(canary).to eq(:called) + end + + it "calls on_body callbacks" do + canary = :not_called + request.on_body do + canary = :called + end + request.run + expect(canary).to eq(:called) + end + + it "finishes request" do + expect(request).to receive(:finish) + request.run + end + + it "sets mock on response" do + request.run + expect(request.response.mock).to be(true) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request_spec.rb new file mode 100644 index 000000000..cabcb4c80 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/request_spec.rb @@ -0,0 +1,232 @@ +require 'spec_helper' + +describe Typhoeus::Request do + let(:base_url) { "localhost:3001" } + let(:options) { {:verbose => true, :headers => { 'User-Agent' => "Fubar", 'Expect' => "" }, :maxredirs => 50} } + let(:request) { Typhoeus::Request.new(base_url, options) } + + describe ".url" do + context "when no parameters" do + it "returns base_url" do + expect(request.url).to eq(request.base_url) + end + end + + context "when parameters" do + let(:options) { {:params => {:a => 1}} } + + it "returns full url" do + expect(request.url).to eq("#{request.base_url}?a=1") + end + end + + it "pushes an easy back into the pool" do + easy = double.as_null_object + allow(Typhoeus::Pool).to receive(:get).and_return(easy) + expect(Typhoeus::Pool).to receive(:release).with(easy) + request.url + end + end + + describe ".new" do + it "stores base_url" do + expect(request.base_url).to eq(base_url) + end + + it "stores options" do + expect(request.options).to eq(options) + end + + it "stores original options" do + expect(request.original_options).to eq(options) + expect(request.original_options).to_not be(request.options) + end + + it "sets defaults" do + expect(request.options[:headers]['User-Agent']).to be + end + end + + describe "set_defaults" do + context "when header with user agent" do + let(:options) { {:headers => {'User-Agent' => "Custom"} } } + + it "doesn't modify user agent" do + expect(request.options[:headers]['User-Agent']).to eq("Custom") + end + end + + context "when header without user agent" do + let(:options) { {:headers => {} } } + + it "add user agent" do + agent = request.options[:headers]['User-Agent'] + expect(agent).to eq(Typhoeus::USER_AGENT) + end + end + + context "when Config.user_agent set" do + before { Typhoeus.configure { |config| config.user_agent = "Default" } } + after { Typhoeus.configure { |config| config.user_agent = nil } } + + context "with headers" do + let(:options) { {:headers => { "User-Agent" => "Fubar" } } } + + it "uses the request options' user agent" do + expect(request.options[:headers]["User-Agent"]).to eq("Fubar") + end + end + + context "without headers" do + let(:options) { {:headers => {} } } + + it "uses the global options' user agent" do + expect(request.options[:headers]["User-Agent"]).to eq("Default") + end + end + end + + context "when Config.verbose set" do + before { Typhoeus.configure { |config| config.verbose = true} } + after { Typhoeus.configure { |config| config.verbose = false} } + + it "respects" do + expect(request.options[:verbose]).to be_truthy + end + end + + context "when maxredirs" do + context "when not set" do + it "defaults to 50" do + expect(request.options[:maxredirs]).to be(50) + end + end + + context "when set" do + let(:options) { {:maxredirs => 1} } + + it "respects" do + expect(request.options[:maxredirs]).to be(1) + end + end + end + + context "when Config.proxy set" do + before { Typhoeus.configure { |config| config.proxy = "http://proxy.internal" } } + after { Typhoeus.configure { |config| config.proxy = nil } } + + it "respects" do + expect(request.options[:proxy]).to eq("http://proxy.internal") + end + + context "when option proxy set" do + let(:options) { {:proxy => nil} } + + it "does not override" do + expect(request.options[:proxy]).to be_nil + end + end + end + end + + describe "#eql?" do + context "when another class" do + let(:other) { "" } + + it "returns false" do + expect(request).to_not eql other + end + end + + context "when same class" do + let(:other) { Typhoeus::Request.new("base_url", options) } + + context "when other base_url" do + it "returns false" do + expect(request).to_not eql other + end + end + + context "when same base_url and other options" do + let(:other) { Typhoeus::Request.new(base_url, {}) } + + it "returns false" do + expect(request).to_not eql other + end + end + + + context "when same base_url and options" do + context "when same order" do + let(:other) { Typhoeus::Request.new(base_url, options) } + + it "returns true" do + expect(request).to eql other + end + end + + context "when different order" do + let(:other_options) { + {:headers => { 'User-Agent' => "Fubar", 'Expect' => ""}, :verbose => true } + } + let(:other) { Typhoeus::Request.new(base_url, other_options)} + + it "returns true" do + expect(request).to eql other + end + end + end + end + end + + describe "#hash" do + context "when request.eql?(other)" do + context "when different order" do + let(:other_options) { + {:headers => { 'User-Agent' => "Fubar", 'Expect' => "" }, :verbose => true } + } + let(:other) { Typhoeus::Request.new(base_url, other_options)} + + it "has same hashes" do + expect(request.hash).to eq(other.hash) + end + end + + context "when same order" do + let(:other) { Typhoeus::Request.new(base_url, options) } + + it "has same hashes" do + expect(request.hash).to eq(other.hash) + end + end + + context "when hashes with different orders are contained in arrays" do + let(:request) { Typhoeus::Request.new(base_url, :params => [{:b => 2, :a => 1}]) } + let(:other) { Typhoeus::Request.new(base_url, :params => [{:a => 1, :b => 2}]) } + it "has different hashes" do + expect(request.hash).to eq(other.hash) + end + end + end + + context "when not request.eql?(other)" do + let(:request) { Typhoeus::Request.new(base_url, :params => {:foo => 'bar'}) } + let(:other) { Typhoeus::Request.new(base_url, :params => {:foo => 'baz'}) } + + it "has different hashes" do + expect(request.hash).to_not eq(other.hash) + end + end + end + + describe "#encoded_body" do + let(:request) { + Typhoeus::Request.new("www.example.com",:body => {:a => 1}) + } + + it "returns encoded body" do + expect(request.encoded_body).to eq("a=1") + end + end + +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/header_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/header_spec.rb new file mode 100644 index 000000000..922d99ebf --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/header_spec.rb @@ -0,0 +1,147 @@ +require 'spec_helper' + +describe Typhoeus::Response::Header do + let(:raw) { nil } + let(:header) { Typhoeus::Response::Header.new(raw) } + + describe ".new" do + context "when string" do + let(:raw) { 'Date: Fri, 29 Jun 2012 10:09:23 GMT' } + + it "sets Date" do + expect(header['Date']).to eq('Fri, 29 Jun 2012 10:09:23 GMT') + end + + it "provides case insensitive access" do + expect(header['DaTe']).to eq('Fri, 29 Jun 2012 10:09:23 GMT') + end + + it "provides symbol access" do + expect(header[:date]).to eq('Fri, 29 Jun 2012 10:09:23 GMT') + end + end + + context "when hash" do + let(:raw) { { 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT' } } + + it "sets Date" do + expect(header['Date']).to eq(raw['Date']) + end + + it "provides case insensitive access" do + expect(header['DaTe']).to eq(raw['Date']) + end + end + end + + describe "#parse" do + context "when no header" do + it "returns nil" do + expect(header).to be_empty + end + end + + context "when header" do + let(:raw) do + 'HTTP/1.1 200 OK + Set-Cookie: NID=61=LblqYgUOu; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly + Date: Fri, 29 Jun 2012 10:09:23 GMT + Expires: -1 + Cache-Control: private, max-age=0 + Content-Type: text/html; charset=ISO-8859-1 + Set-Cookie: PREF=ID=77e93yv0hPtejLou; expires=Sun, 29-Jun-2014 10:09:23 GMT; path=/; domain=.google.de + Set-Cookie: NID=61=LblqYgh5Ou; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly + P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." + Server: gws + X-XSS-Protection: 1; mode=block + X-Frame-Options: SAMEORIGIN + Transfer-Encoding: chunked'.gsub(/^\s{8}/, '') + end + + it "sets raw" do + expect(header.send(:raw)).to eq(raw) + end + + it "sets Set-Cookie" do + expect(header['set-cookie'].size).to eq(3) + end + + it "provides case insensitive access" do + expect(header['Set-CooKie'].size).to eq(3) + end + + [ + 'NID=61=LblqYgUOu; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly', + 'PREF=ID=77e93yv0hPtejLou; expires=Sun, 29-Jun-2014 10:09:23 GMT; path=/; domain=.google.de', + 'NID=61=LblqYgh5Ou; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly' + ].each_with_index do |cookie, i| + it "sets Cookie##{i}" do + expect(header['set-cookie']).to include(cookie) + end + end + + { + 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT', 'Expires' => '-1', + 'Cache-Control' => 'private, max-age=0', + 'Content-Type' => 'text/html; charset=ISO-8859-1', + 'P3P' => 'CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."', + 'Server' => 'gws', 'X-XSS-Protection' => '1; mode=block', + 'X-Frame-Options' => 'SAMEORIGIN', 'Transfer-Encoding' => 'chunked' + }.each do |name, value| + it "sets #{name}" do + expect(header[name.downcase]).to eq(value) + end + end + + context 'includes a multi-line header' do + let(:raw) do + 'HTTP/1.1 200 OK + Date: Fri, 29 Jun 2012 10:09:23 GMT + Content-Security-Policy: default-src "self"; + img-src * data: "self"; + upgrade-insecure-requests;'.gsub(/^\s{10}/, '') + end + + it "joins header parts" do + expect(header).to eq({ + 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT', + 'Content-Security-Policy' => 'default-src "self"; img-src * data: "self"; upgrade-insecure-requests;' + }) + end + end + + context 'includes line with only whitespace' do + let(:raw) do + 'HTTP/1.1 200 OK + Date: Fri, 29 Jun 2012 10:09:23 GMT + + '.gsub(/^\s{10}/, '') + end + + it 'ignores it' do + expect(header).to eq({ 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT' }) + end + end + + context 'with broken headers' do + let(:raw) do + 'HTTP/1.1 200 OK + Date: + Content-Type + '.gsub(/^\s{10}/, '') + end + + it 'returns empty string for invalid headers' do + expect(header.to_hash).to include({ 'Date' => '', 'Content-Type' => '' }) + end + end + end + end + + it "can be Marshal'd" do + header = Typhoeus::Response::Header.new("Foo: Bar") + expect { + Marshal.dump(header) + }.not_to raise_error + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/informations_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/informations_spec.rb new file mode 100644 index 000000000..896931af0 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/informations_spec.rb @@ -0,0 +1,283 @@ +require 'spec_helper' + +describe Typhoeus::Response::Informations do + let(:options) { {} } + let(:response) { Typhoeus::Response.new(options) } + + describe "#return_code" do + let(:options) { { :return_code => :ok } } + + it "returns return_code from options" do + expect(response.return_code).to be(:ok) + end + end + + describe "#debug_info" do + let(:options) { { :debug_info => Ethon::Easy::DebugInfo.new } } + + it "returns debug_info from options" do + expect(response.debug_info).to be_a(Ethon::Easy::DebugInfo) + end + end + + describe "#return_message" do + let(:options) { { :return_code => :couldnt_connect } } + + it "returns a message" do + expect(response.return_message).to eq("Couldn't connect to server") + end + + describe "with nil return_code" do + let(:options) { { :return_code => nil } } + + it "returns nil" do + expect(response.return_message).to be_nil + end + end + end + + describe "#response_body" do + context "when response_body" do + let(:options) { { :response_body => "body" } } + + it "returns response_body from options" do + expect(response.response_body).to eq("body") + end + end + + context "when body" do + let(:options) { { :body => "body" } } + + it "returns body from options" do + expect(response.body).to eq("body") + end + end + end + + describe "#response_headers" do + let(:options) { { :response_headers => "Length: 1" } } + + context "when no mock" do + it "returns response_headers from options" do + expect(response.response_headers).to eq("Length: 1") + end + end + + context "when mock" do + context "when no response_headers" do + context "when headers" do + let(:options) { { :mock => true, :headers => {"Length" => 1, "Content-Type" => "text/plain" } } } + + it "constructs response_headers" do + expect(response.response_headers).to include("Length: 1") + expect(response.response_headers).to include("Content-Type: text/plain") + expect(response.response_headers).to include("\r\n") + end + end + + context "when multiple values for a header" do + let(:options) { { :mock => true, :headers => {"Length" => 1, "Content-Type" => "text/plain", "set-cookie" => ["cookieone=one","cookietwo=two"] } } } + + it "constructs response_headers" do + expect(response.response_headers).to include("Length: 1") + expect(response.response_headers).to include("Content-Type: text/plain") + expect(response.response_headers).to include("set-cookie: cookieone=one,cookietwo=two") + expect(response.response_headers).to include("\r\n") + end + end + end + end + end + + describe "#response_code" do + context "when response_code" do + let(:options) { { :response_code => "200" } } + + it "returns response_code from options" do + expect(response.response_code).to eq(200) + end + end + + context "when code" do + let(:options) { { :code => "200" } } + + it "returns code from options" do + expect(response.code).to eq(200) + end + end + end + + describe "#httpauth_avail" do + let(:options) { { :httpauth_avail => "code" } } + + it "returns httpauth_avail from options" do + expect(response.httpauth_avail).to eq("code") + end + end + + describe "#total_time" do + let(:options) { { :total_time => 1 } } + + it "returns total_time from options" do + expect(response.total_time).to eq(1) + end + end + + describe "#starttransfer_time" do + let(:options) { { :starttransfer_time => 1 } } + + it "returns starttransfer_time from options" do + expect(response.starttransfer_time).to eq(1) + end + end + + describe "#appconnect_time" do + let(:options) { { :appconnect_time => 1 } } + + it "returns appconnect_time from options" do + expect(response.appconnect_time).to eq(1) + end + end + + describe "#pretransfer_time" do + let(:options) { { :pretransfer_time => 1 } } + + it "returns pretransfer_time from options" do + expect(response.pretransfer_time).to eq(1) + end + end + + describe "#connect_time" do + let(:options) { { :connect_time => 1 } } + + it "returns connect_time from options" do + expect(response.connect_time).to eq(1) + end + end + + describe "#namelookup_time" do + let(:options) { { :namelookup_time => 1 } } + + it "returns namelookup_time from options" do + expect(response.namelookup_time).to eq(1) + end + end + + describe "#redirect_time" do + let(:options) { { :redirect_time => 1 } } + + it "returns redirect_time from options" do + expect(response.redirect_time).to eq(1) + end + end + + describe "#effective_url" do + let(:options) { { :effective_url => "http://www.example.com" } } + + it "returns effective_url from options" do + expect(response.effective_url).to eq("http://www.example.com") + end + end + + describe "#primary_ip" do + let(:options) { { :primary_ip => "127.0.0.1" } } + + it "returns primary_ip from options" do + expect(response.primary_ip).to eq("127.0.0.1") + end + end + + describe "#redirect_count" do + let(:options) { { :redirect_count => 2 } } + + it "returns redirect_count from options" do + expect(response.redirect_count).to eq(2) + end + end + + describe "#request_size" do + let(:options) { { :request_size => 2 } } + + it "returns request_size from options" do + expect(response.request_size).to eq(2) + end + end + + describe "#headers" do + context "when no response_headers" do + it "returns nil" do + expect(response.headers).to be_nil + end + end + + context "when response_headers" do + let(:options) { {:response_headers => "Expire: -1\nServer: gws"} } + + it "returns nonempty headers" do + expect(response.headers).to_not be_empty + end + + it "has Expire" do + expect(response.headers['expire']).to eq('-1') + end + + it "has Server" do + expect(response.headers['server']).to eq('gws') + end + end + + context "when multiple headers" do + let(:options) { {:response_headers => "Server: A\r\n\r\nServer: B"} } + + it "returns the last" do + expect(response.headers['server']).to eq("B") + end + end + + context "when mock" do + context "when headers" do + let(:options) { {:mock => true, :headers => {"Length" => "1"}} } + + it "returns Typhoeus::Response::Header" do + expect(response.headers).to be_a(Typhoeus::Response::Header) + end + + it "returns headers" do + expect(response.headers.to_hash).to include("Length" => "1") + end + end + end + + context "when requesting" do + let(:response) { Typhoeus.get("localhost:3001") } + + it "returns headers" do + expect(response.headers).to_not be_empty + end + end + end + + describe "#redirections" do + context "when no response_headers" do + it "returns empty array" do + expect(response.redirections).to be_empty + end + end + + context "when headers" do + let(:options) { {:response_headers => "Expire: -1\nServer: gws"} } + + it "returns empty array" do + expect(response.redirections).to be_empty + end + end + + context "when multiple headers" do + let(:options) { {:response_headers => "Server: A\r\n\r\nServer: B"} } + + it "returns response from all but last headers" do + expect(response.redirections.size).to eq(1) + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/status_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/status_spec.rb new file mode 100644 index 000000000..64ba1e0d9 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response/status_spec.rb @@ -0,0 +1,256 @@ +require 'spec_helper' + +describe Typhoeus::Response::Status do + let(:response) { Typhoeus::Response.new(options) } + let(:options) { {} } + + describe "timed_out?" do + context "when return code is operation_timedout" do + let(:options) { {:return_code => :operation_timedout} } + + it "return true" do + expect(response).to be_timed_out + end + end + end + + describe "#status_message" do + context "when no header" do + it "returns nil" do + expect(response.status_message).to be_nil + end + end + + context "when header" do + context "when no message" do + let(:options) { {:response_headers => "HTTP/1.1 200\r\n"} } + + it "returns nil" do + expect(response.status_message).to be_nil + end + end + + context "when messsage" do + let(:options) { {:response_headers => "HTTP/1.1 200 message\r\n"} } + + it "returns message" do + expect(response.status_message).to eq("message") + end + end + end + end + + describe "#http_version" do + context "when no header" do + it "returns nil" do + expect(response.http_version).to be_nil + end + end + + context "when header" do + context "when no http version" do + let(:options) { {:response_headers => "HTTP OK"} } + + it "returns nil" do + expect(response.http_version).to be_nil + end + end + + context "when invalid http_version" do + let(:options) { {:response_headers => "HTTP foo/bar OK"} } + + it "returns nil" do + expect(response.http_version).to be_nil + end + end + + context "when valid http_version" do + let(:options) { {:response_headers => "HTTP/1.1 OK"} } + + it "returns http_version" do + expect(response.http_version).to eq("1.1") + end + end + end + end + + describe "#success?" do + context "when response code 200-299" do + let(:options) { {:return_code => return_code, :response_code => 201} } + + context "when mock" do + before { response.mock = true } + + context "when return_code :ok" do + let(:return_code) { :ok } + + it "returns true" do + expect(response.success?).to be_truthy + end + end + + context "when return_code nil" do + let(:return_code) { nil } + + it "returns true" do + expect(response.success?).to be_truthy + end + end + end + + context "when no mock" do + before { response.mock = nil } + + context "when return_code :ok" do + let(:return_code) { :ok } + + it "returns true" do + expect(response.success?).to be_truthy + end + end + + context "when return_code nil" do + let(:return_code) { nil } + + it "returns false" do + expect(response.success?).to be_falsey + end + end + end + end + + context "when response code is not 200-299" do + let(:options) { {:return_code => :ok, :response_code => 500} } + + it "returns false" do + expect(response.success?).to be_falsey + end + end + end + + describe "#failure?" do + context "when response code between 300-526 and 100-300" do + let(:options) { {:return_code => return_code, :response_code => 300} } + + context "when mock" do + before { response.mock = true } + + context "when return_code :internal_server_error" do + let(:return_code) { :internal_server_error } + + it "returns true" do + expect(response.failure?).to be_truthy + end + end + + context "when return_code nil" do + let(:return_code) { nil } + + it "returns true" do + expect(response.failure?).to be_truthy + end + end + end + + context "when no mock" do + before { response.mock = nil } + + context "when return_code :internal_server_error" do + let(:return_code) { :internal_server_error } + + it "returns true" do + expect(response.failure?).to be_truthy + end + end + + context "when return_code nil" do + let(:return_code) { nil } + + it "returns false" do + expect(response.failure?).to be_falsey + end + end + end + end + + context "when response code is not 300-526" do + let(:options) { {:return_code => :ok, :response_code => 200} } + + it "returns false" do + expect(response.failure?).to be_falsey + end + end + end + + describe "#modified?" do + context "when response code 304" do + let(:options) { {:return_code => :ok, :response_code => 304} } + + context "when mock" do + before { response.mock = true } + + context "when return_code :ok" do + let(:return_code) { :ok } + + it "returns false" do + expect(response.modified?).to be_falsey + end + end + + context "when return_code nil" do + let(:return_code) { nil } + + it "returns false" do + expect(response.modified?).to be_falsey + end + end + end + + context "when no mock" do + before { response.mock = nil } + + context "when return_code :ok" do + let(:return_code) { :ok } + + it "returns false" do + expect(response.modified?).to be_falsey + end + end + + context "when return_code nil" do + let(:return_code) { nil } + + it "returns true" do + expect(response.modified?).to be_falsey + end + end + end + end + + context "when response code is not 304" do + let(:options) { {:return_code => :ok, :response_code => 500} } + + it "returns true" do + expect(response.modified?).to be_truthy + end + end + end + + describe "#first_header_line" do + context "when multiple header" do + let(:options) { {:response_headers => "1\r\n\r\n2\r\nbla"} } + + it "returns first line of last block" do + expect(response.method(:first_header_line).call).to eq("2") + end + end + + context "when single header" do + let(:options) { {:response_headers => "1"} } + + it "returns first line" do + expect(response.method(:first_header_line).call).to eq("1") + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response_spec.rb new file mode 100644 index 000000000..02512f4ea --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus/response_spec.rb @@ -0,0 +1,100 @@ +require 'spec_helper' + +describe Typhoeus::Response do + let(:response) { Typhoeus::Response.new(options) } + let(:options) { {} } + + describe ".new" do + context "when options" do + context "when return_code" do + let(:options) { {:return_code => 2} } + + it "stores" do + expect(response.options[:return_code]).to be(2) + end + end + + context "when headers" do + let(:options) { {:headers => {'A' => 'B'}} } + + it "stores unmodified" do + expect(response.options[:headers]).to be(options[:headers]) + end + + it "sets @headers to a Typhoeus::Response::Header" do + expect(response.instance_variable_get(:@headers)).to be_a(Typhoeus::Response::Header) + end + + it "has key" do + expect(response.headers['A']).to eq('B') + end + end + end + end + + describe "#mock" do + context "when @mock" do + before { response.mock = true } + + it "returns @mock" do + expect(response.mock).to be_truthy + end + end + + context "when options[:mock]" do + let(:options) { {:mock => true} } + + it "returns options[:mock]" do + expect(response.mock).to be_truthy + end + end + + context "when @mock and options[:mock]" do + let(:options) { {:mock => 1} } + before { response.mock = 2 } + + it "returns @mock" do + expect(response.mock).to be(2) + end + end + end + + describe "#handled_response" do + let(:handled_response) { Typhoeus::Response.new } + + context "when @handled_response" do + before { response.handled_response = handled_response } + + it "returns @handled_response" do + expect(response.handled_response).to be(handled_response) + end + end + + context "when @handled_response is nil" do + before { response.handled_response = nil } + + it "returns response" do + expect(response.handled_response).to be(response) + end + end + end + + describe "#cached" do + context "when @cached" do + before { response.cached = true } + + it "returns cached status" do + expect(response.cached?).to be_truthy + end + end + + context "when @cached is nil" do + before { response.cached = nil } + + it "returns false" do + expect(response.cached?).to be_falsey + end + end + + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/spec/typhoeus_spec.rb b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus_spec.rb new file mode 100644 index 000000000..6432c8d83 --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/spec/typhoeus_spec.rb @@ -0,0 +1,105 @@ +require 'spec_helper' + +describe Typhoeus do + before(:each) do + Typhoeus.configure { |config| config.verbose = false; config.block_connection = false } + end + + describe ".configure" do + it "yields config" do + Typhoeus.configure do |config| + expect(config).to be_a(Typhoeus::Config) + end + end + + it "sets values config" do + Typhoeus::Config.verbose = true + expect(Typhoeus::Config.verbose).to be_truthy + end + end + + describe ".stub" do + let(:base_url) { "www.example.com" } + + shared_examples "lazy response construction" do + it "calls the block to construct a response when a request matches the stub" do + expected_response = Typhoeus::Response.new + Typhoeus.stub(base_url) do |request| + expected_response + end + + response = Typhoeus.get(base_url) + + expect(response).to be(expected_response) + end + end + + context "when no similar expectation exists" do + include_examples "lazy response construction" + + it "returns expectation" do + expect(Typhoeus.stub(base_url)).to be_a(Typhoeus::Expectation) + end + + it "adds expectation" do + Typhoeus.stub(:get, "") + expect(Typhoeus::Expectation.all.size).to eq(1) + end + end + + context "when similar expectation exists" do + include_examples "lazy response construction" + + let(:expectation) { Typhoeus::Expectation.new(base_url) } + before { Typhoeus::Expectation.all << expectation } + + it "returns expectation" do + expect(Typhoeus.stub(base_url)).to be_a(Typhoeus::Expectation) + end + + it "doesn't add expectation" do + Typhoeus.stub(base_url) + expect(Typhoeus::Expectation.all.size).to eq(1) + end + end + end + + describe ".before" do + it "adds callback" do + Typhoeus.before { true } + expect(Typhoeus.before.size).to eq(1) + end + end + + describe ".with_connection" do + it "executes block with block connection is false" do + Typhoeus.with_connection { expect(Typhoeus::Config.block_connection).to be(false) } + end + + it "sets block connection back to previous value" do + Typhoeus::Config.block_connection = true + Typhoeus.with_connection {} + expect(Typhoeus::Config.block_connection).to be(true) + end + + it "returns result of block" do + expect(Typhoeus.with_connection { "123" }).to eq("123") + end + end + + [:get, :post, :put, :delete, :head, :patch, :options].each do |name| + describe ".#{name}" do + let(:response) { Typhoeus::Request.method(name).call("http://localhost:3001") } + + it "returns ok" do + expect(response.return_code).to eq(:ok) + end + + unless name == :head + it "makes #{name.to_s.upcase} requests" do + expect(response.response_body).to include("\"REQUEST_METHOD\":\"#{name.to_s.upcase}\"") + end + end + end + end +end diff --git a/fluentd/vendored_gem_src/typhoeus/typhoeus.gemspec b/fluentd/vendored_gem_src/typhoeus/typhoeus.gemspec new file mode 100644 index 000000000..39bcc7a6a --- /dev/null +++ b/fluentd/vendored_gem_src/typhoeus/typhoeus.gemspec @@ -0,0 +1,25 @@ +# encoding: utf-8 +lib = File.expand_path('../lib/', __FILE__) +$:.unshift lib unless $:.include?(lib) + +require 'typhoeus/version' + +Gem::Specification.new do |s| + s.name = "typhoeus" + s.version = Typhoeus::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["David Balatero", "Paul Dix", "Hans Hasselberg"] + s.email = ["hans.hasselberg@gmail.com"] + s.homepage = "https://github.com/typhoeus/typhoeus" + s.summary = "Parallel HTTP library on top of libcurl multi." + s.description = %q{Like a modern code version of the mythical beast with 100 serpent heads, Typhoeus runs HTTP requests in parallel while cleanly encapsulating handling logic.} + + s.required_rubygems_version = ">= 1.3.6" + s.license = 'MIT' + + s.add_dependency('ethon', [">= 0.9.0"]) + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- spec/*`.split("\n") + s.require_path = 'lib' +end diff --git a/hack/update-fluentd-vendor-gems.sh b/hack/update-fluentd-vendor-gems.sh index e82f5ece1..b65478a46 100755 --- a/hack/update-fluentd-vendor-gems.sh +++ b/hack/update-fluentd-vendor-gems.sh @@ -4,7 +4,7 @@ # - unpack the gems into the fluentd/vendor directory set -euo pipefail - +BUNDLE_TASK=${BUNDLE_TASK:-install} basedir=$( dirname $0 ) if [ -z "$basedir" ] ; then pushd .. > /dev/null @@ -30,7 +30,7 @@ export FLUENTD_VERSION # update Gemfile.lock by installing Gemfile echo updating Gemfile.lock pushd $fluentddir - bundle update + bundle $BUNDLE_TASK popd if [ -n "${CLOBBER_VENDOR:-}" ] ; then