fluid_cli 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +1 -0
- data/dev.yml +5 -0
- data/exe/fluid +24 -0
- data/lib/fluid_cli/api.rb +135 -0
- data/lib/fluid_cli/assets/post_auth_page/index.html.erb +34 -0
- data/lib/fluid_cli/assets/post_auth_page/style.css +58 -0
- data/lib/fluid_cli/command.rb +55 -0
- data/lib/fluid_cli/commands/help.rb +21 -0
- data/lib/fluid_cli/commands/login.rb +30 -0
- data/lib/fluid_cli/commands/logout.rb +38 -0
- data/lib/fluid_cli/commands/switch.rb +23 -0
- data/lib/fluid_cli/commands/theme/common/company_helper.rb +15 -0
- data/lib/fluid_cli/commands/theme/common/root_helper.rb +95 -0
- data/lib/fluid_cli/commands/theme/dev.rb +61 -0
- data/lib/fluid_cli/commands/theme/help.rb +21 -0
- data/lib/fluid_cli/commands/theme/init.rb +46 -0
- data/lib/fluid_cli/commands/theme/pull.rb +68 -0
- data/lib/fluid_cli/commands/theme/push.rb +132 -0
- data/lib/fluid_cli/commands/theme.rb +23 -0
- data/lib/fluid_cli/commands/whoami.rb +23 -0
- data/lib/fluid_cli/commands.rb +19 -0
- data/lib/fluid_cli/company_switcher.rb +69 -0
- data/lib/fluid_cli/context.rb +691 -0
- data/lib/fluid_cli/db.rb +114 -0
- data/lib/fluid_cli/entry_point.rb +10 -0
- data/lib/fluid_cli/environment.rb +32 -0
- data/lib/fluid_cli/file_system_listener.rb +29 -0
- data/lib/fluid_cli/form.rb +42 -0
- data/lib/fluid_cli/git.rb +319 -0
- data/lib/fluid_cli/http_request.rb +54 -0
- data/lib/fluid_cli/identity_auth/servlet.rb +39 -0
- data/lib/fluid_cli/identity_auth.rb +126 -0
- data/lib/fluid_cli/options.rb +38 -0
- data/lib/fluid_cli/theme/dev_server/certificate_manager.rb +79 -0
- data/lib/fluid_cli/theme/dev_server/errors.rb +9 -0
- data/lib/fluid_cli/theme/dev_server/header_hash.rb +98 -0
- data/lib/fluid_cli/theme/dev_server/hooks/file_change_hook.rb +39 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/hot-reload-no-script.html +27 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/hot_reload.js +28 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/sse_client.js +43 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/theme.js +16 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/script_injector.rb +54 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload.rb +75 -0
- data/lib/fluid_cli/theme/dev_server/local_assets.rb +92 -0
- data/lib/fluid_cli/theme/dev_server/proxy.rb +235 -0
- data/lib/fluid_cli/theme/dev_server/proxy_param_builder.rb +82 -0
- data/lib/fluid_cli/theme/dev_server/reload_mode.rb +34 -0
- data/lib/fluid_cli/theme/dev_server/sse.rb +75 -0
- data/lib/fluid_cli/theme/dev_server/watcher.rb +57 -0
- data/lib/fluid_cli/theme/dev_server/web_server.rb +140 -0
- data/lib/fluid_cli/theme/dev_server.rb +289 -0
- data/lib/fluid_cli/theme/development_theme.rb +101 -0
- data/lib/fluid_cli/theme/file.rb +105 -0
- data/lib/fluid_cli/theme/forms/select.rb +33 -0
- data/lib/fluid_cli/theme/mime_type.rb +34 -0
- data/lib/fluid_cli/theme/presenters/theme_presenter.rb +49 -0
- data/lib/fluid_cli/theme/presenters/themes_presenter.rb +31 -0
- data/lib/fluid_cli/theme/root.rb +62 -0
- data/lib/fluid_cli/theme/syncer/checksums.rb +66 -0
- data/lib/fluid_cli/theme/syncer/downloader.rb +54 -0
- data/lib/fluid_cli/theme/syncer/error_reporter.rb +45 -0
- data/lib/fluid_cli/theme/syncer/merger.rb +53 -0
- data/lib/fluid_cli/theme/syncer/operation.rb +58 -0
- data/lib/fluid_cli/theme/syncer/standard_reporter.rb +32 -0
- data/lib/fluid_cli/theme/syncer/unsupported_script_warning.rb +90 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/apply_to_all.rb +41 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/apply_to_all_form.rb +37 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/base_strategy_form.rb +64 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/select_delete_strategy.rb +29 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/select_update_strategy.rb +30 -0
- data/lib/fluid_cli/theme/syncer/uploader/json_delete_handler.rb +49 -0
- data/lib/fluid_cli/theme/syncer/uploader/json_update_handler.rb +71 -0
- data/lib/fluid_cli/theme/syncer/uploader.rb +105 -0
- data/lib/fluid_cli/theme/syncer.rb +412 -0
- data/lib/fluid_cli/theme/theme.rb +186 -0
- data/lib/fluid_cli/theme/ui/sync_progress_bar.rb +22 -0
- data/lib/fluid_cli/thread_pool/job.rb +35 -0
- data/lib/fluid_cli/thread_pool.rb +49 -0
- data/lib/fluid_cli/version.rb +3 -0
- data/lib/fluid_cli.rb +59 -0
- data/vendor/deps/base64/.document +5 -0
- data/vendor/deps/base64/.gitignore +9 -0
- data/vendor/deps/base64/BSDL +22 -0
- data/vendor/deps/base64/COPYING +56 -0
- data/vendor/deps/base64/Gemfile +9 -0
- data/vendor/deps/base64/LEGAL +60 -0
- data/vendor/deps/base64/README.md +48 -0
- data/vendor/deps/base64/Rakefile +31 -0
- data/vendor/deps/base64/base64.gemspec +28 -0
- data/vendor/deps/base64/bin/console +14 -0
- data/vendor/deps/base64/bin/setup +8 -0
- data/vendor/deps/base64/lib/base64.rb +382 -0
- data/vendor/deps/base64/sig/base64.rbs +358 -0
- data/vendor/deps/base64/test/base64/test_base64.rb +115 -0
- data/vendor/deps/base64/test_sig/test_base64.rb +44 -0
- data/vendor/deps/cli-kit/REVISION +1 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/definition.rb +286 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/evaluation.rb +215 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/parser/node.rb +128 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/parser.rb +125 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/tokenizer.rb +130 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args.rb +16 -0
- data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +30 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_help.rb +268 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +150 -0
- data/vendor/deps/cli-kit/lib/cli/kit/config.rb +137 -0
- data/vendor/deps/cli-kit/lib/cli/kit/core_ext.rb +28 -0
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +166 -0
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +92 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +91 -0
- data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +92 -0
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +94 -0
- data/vendor/deps/cli-kit/lib/cli/kit/opts.rb +248 -0
- data/vendor/deps/cli-kit/lib/cli/kit/parse_args.rb +55 -0
- data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +66 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +260 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support.rb +11 -0
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +290 -0
- data/vendor/deps/cli-kit/lib/cli/kit/util.rb +118 -0
- data/vendor/deps/cli-kit/lib/cli/kit/version.rb +7 -0
- data/vendor/deps/cli-kit/lib/cli/kit.rb +139 -0
- data/vendor/deps/cli-ui/REVISION +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +218 -0
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +101 -0
- data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +219 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +67 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +179 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +152 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +127 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +286 -0
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +92 -0
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +63 -0
- data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +64 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +132 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress_reporter.rb +209 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +583 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +36 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +381 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +48 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +602 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +399 -0
- data/vendor/deps/cli-ui/lib/cli/ui/table.rb +83 -0
- data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +55 -0
- data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +106 -0
- data/vendor/deps/cli-ui/lib/cli/ui/version.rb +8 -0
- data/vendor/deps/cli-ui/lib/cli/ui/widgets/base.rb +46 -0
- data/vendor/deps/cli-ui/lib/cli/ui/widgets/status.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +89 -0
- data/vendor/deps/cli-ui/lib/cli/ui/work_queue.rb +142 -0
- data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +61 -0
- data/vendor/deps/cli-ui/lib/cli/ui.rb +359 -0
- data/vendor/deps/cli-ui/vendor/reentrant_mutex.rb +78 -0
- data/vendor/deps/debug/CONTRIBUTING.md +573 -0
- data/vendor/deps/debug/Gemfile +10 -0
- data/vendor/deps/debug/LICENSE.txt +22 -0
- data/vendor/deps/debug/README.md +996 -0
- data/vendor/deps/debug/Rakefile +57 -0
- data/vendor/deps/debug/TODO.md +23 -0
- data/vendor/deps/debug/debug.gemspec +33 -0
- data/vendor/deps/debug/exe/rdbg +53 -0
- data/vendor/deps/debug/ext/debug/Makefile +273 -0
- data/vendor/deps/debug/ext/debug/debug.c +228 -0
- data/vendor/deps/debug/ext/debug/debug_version.h +1 -0
- data/vendor/deps/debug/ext/debug/extconf.rb +27 -0
- data/vendor/deps/debug/ext/debug/iseq_collector.c +93 -0
- data/vendor/deps/debug/lib/debug/abbrev_command.rb +77 -0
- data/vendor/deps/debug/lib/debug/breakpoint.rb +556 -0
- data/vendor/deps/debug/lib/debug/client.rb +263 -0
- data/vendor/deps/debug/lib/debug/color.rb +123 -0
- data/vendor/deps/debug/lib/debug/config.rb +592 -0
- data/vendor/deps/debug/lib/debug/console.rb +224 -0
- data/vendor/deps/debug/lib/debug/dap_custom/traceInspector.rb +336 -0
- data/vendor/deps/debug/lib/debug/debug.bundle +0 -0
- data/vendor/deps/debug/lib/debug/frame_info.rb +190 -0
- data/vendor/deps/debug/lib/debug/irb_integration.rb +37 -0
- data/vendor/deps/debug/lib/debug/local.rb +115 -0
- data/vendor/deps/debug/lib/debug/open.rb +13 -0
- data/vendor/deps/debug/lib/debug/open_nonstop.rb +15 -0
- data/vendor/deps/debug/lib/debug/prelude.rb +50 -0
- data/vendor/deps/debug/lib/debug/server.rb +534 -0
- data/vendor/deps/debug/lib/debug/server_cdp.rb +1348 -0
- data/vendor/deps/debug/lib/debug/server_dap.rb +1108 -0
- data/vendor/deps/debug/lib/debug/session.rb +2667 -0
- data/vendor/deps/debug/lib/debug/source_repository.rb +150 -0
- data/vendor/deps/debug/lib/debug/start.rb +5 -0
- data/vendor/deps/debug/lib/debug/thread_client.rb +1457 -0
- data/vendor/deps/debug/lib/debug/tracer.rb +241 -0
- data/vendor/deps/debug/lib/debug/version.rb +5 -0
- data/vendor/deps/debug/lib/debug.rb +9 -0
- data/vendor/deps/debug/misc/README.md.erb +660 -0
- data/vendor/deps/listen/.github/release-drafter.yml +17 -0
- data/vendor/deps/listen/.github/workflows/development.yml +67 -0
- data/vendor/deps/listen/.github/workflows/push.yml +12 -0
- data/vendor/deps/listen/.gitignore +28 -0
- data/vendor/deps/listen/.rspec +3 -0
- data/vendor/deps/listen/.rubocop.yml +283 -0
- data/vendor/deps/listen/.yardopts +11 -0
- data/vendor/deps/listen/CHANGELOG.md +1 -0
- data/vendor/deps/listen/CONTRIBUTING.md +45 -0
- data/vendor/deps/listen/Gemfile +33 -0
- data/vendor/deps/listen/Guardfile +26 -0
- data/vendor/deps/listen/LICENSE.txt +22 -0
- data/vendor/deps/listen/README.md +490 -0
- data/vendor/deps/listen/Rakefile +154 -0
- data/vendor/deps/listen/bin/listen +11 -0
- data/vendor/deps/listen/lib/listen/adapter/base.rb +129 -0
- data/vendor/deps/listen/lib/listen/adapter/bsd.rb +104 -0
- data/vendor/deps/listen/lib/listen/adapter/config.rb +31 -0
- data/vendor/deps/listen/lib/listen/adapter/darwin.rb +77 -0
- data/vendor/deps/listen/lib/listen/adapter/linux.rb +108 -0
- data/vendor/deps/listen/lib/listen/adapter/polling.rb +40 -0
- data/vendor/deps/listen/lib/listen/adapter/windows.rb +96 -0
- data/vendor/deps/listen/lib/listen/adapter.rb +43 -0
- data/vendor/deps/listen/lib/listen/backend.rb +40 -0
- data/vendor/deps/listen/lib/listen/change.rb +69 -0
- data/vendor/deps/listen/lib/listen/cli.rb +65 -0
- data/vendor/deps/listen/lib/listen/directory.rb +93 -0
- data/vendor/deps/listen/lib/listen/error.rb +11 -0
- data/vendor/deps/listen/lib/listen/event/config.rb +39 -0
- data/vendor/deps/listen/lib/listen/event/loop.rb +92 -0
- data/vendor/deps/listen/lib/listen/event/processor.rb +128 -0
- data/vendor/deps/listen/lib/listen/event/queue.rb +52 -0
- data/vendor/deps/listen/lib/listen/file.rb +95 -0
- data/vendor/deps/listen/lib/listen/fsm.rb +131 -0
- data/vendor/deps/listen/lib/listen/listener/config.rb +41 -0
- data/vendor/deps/listen/lib/listen/listener.rb +136 -0
- data/vendor/deps/listen/lib/listen/logger.rb +65 -0
- data/vendor/deps/listen/lib/listen/monotonic_time.rb +27 -0
- data/vendor/deps/listen/lib/listen/options.rb +24 -0
- data/vendor/deps/listen/lib/listen/queue_optimizer.rb +129 -0
- data/vendor/deps/listen/lib/listen/record/entry.rb +66 -0
- data/vendor/deps/listen/lib/listen/record/symlink_detector.rb +47 -0
- data/vendor/deps/listen/lib/listen/record.rb +122 -0
- data/vendor/deps/listen/lib/listen/silencer/controller.rb +50 -0
- data/vendor/deps/listen/lib/listen/silencer.rb +106 -0
- data/vendor/deps/listen/lib/listen/thread.rb +54 -0
- data/vendor/deps/listen/lib/listen/version.rb +5 -0
- data/vendor/deps/listen/lib/listen.rb +47 -0
- data/vendor/deps/listen/listen.gemspec +40 -0
- data/vendor/deps/listen/spec/acceptance/listen_spec.rb +320 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/base_spec.rb +101 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/bsd_spec.rb +13 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/config_spec.rb +122 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/darwin_spec.rb +82 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/linux_spec.rb +199 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/polling_spec.rb +83 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/windows_spec.rb +13 -0
- data/vendor/deps/listen/spec/lib/listen/adapter_spec.rb +69 -0
- data/vendor/deps/listen/spec/lib/listen/backend_spec.rb +82 -0
- data/vendor/deps/listen/spec/lib/listen/change_spec.rb +102 -0
- data/vendor/deps/listen/spec/lib/listen/cli_spec.rb +116 -0
- data/vendor/deps/listen/spec/lib/listen/directory_spec.rb +284 -0
- data/vendor/deps/listen/spec/lib/listen/event/config_spec.rb +33 -0
- data/vendor/deps/listen/spec/lib/listen/event/loop_spec.rb +118 -0
- data/vendor/deps/listen/spec/lib/listen/event/processor_spec.rb +250 -0
- data/vendor/deps/listen/spec/lib/listen/event/queue_spec.rb +118 -0
- data/vendor/deps/listen/spec/lib/listen/file_spec.rb +254 -0
- data/vendor/deps/listen/spec/lib/listen/fsm_spec.rb +147 -0
- data/vendor/deps/listen/spec/lib/listen/listener/config_spec.rb +29 -0
- data/vendor/deps/listen/spec/lib/listen/listener_spec.rb +321 -0
- data/vendor/deps/listen/spec/lib/listen/logger_spec.rb +212 -0
- data/vendor/deps/listen/spec/lib/listen/monotonic_time_spec.rb +58 -0
- data/vendor/deps/listen/spec/lib/listen/queue_optimizer_spec.rb +111 -0
- data/vendor/deps/listen/spec/lib/listen/record_spec.rb +424 -0
- data/vendor/deps/listen/spec/lib/listen/silencer/controller_spec.rb +97 -0
- data/vendor/deps/listen/spec/lib/listen/silencer_spec.rb +109 -0
- data/vendor/deps/listen/spec/lib/listen/thread_spec.rb +133 -0
- data/vendor/deps/listen/spec/lib/listen_spec.rb +25 -0
- data/vendor/deps/listen/spec/spec_helper.rb +49 -0
- data/vendor/deps/listen/spec/support/acceptance_helper.rb +260 -0
- data/vendor/deps/listen/spec/support/fixtures_helper.rb +32 -0
- data/vendor/deps/listen/spec/support/platform_helper.rb +17 -0
- data/vendor/deps/observer/.github/dependabot.yml +6 -0
- data/vendor/deps/observer/.github/workflows/test.yml +33 -0
- data/vendor/deps/observer/.gitignore +8 -0
- data/vendor/deps/observer/BSDL +22 -0
- data/vendor/deps/observer/COPYING +56 -0
- data/vendor/deps/observer/Gemfile +9 -0
- data/vendor/deps/observer/README.md +139 -0
- data/vendor/deps/observer/Rakefile +10 -0
- data/vendor/deps/observer/bin/console +14 -0
- data/vendor/deps/observer/bin/setup +8 -0
- data/vendor/deps/observer/lib/observer.rb +229 -0
- data/vendor/deps/observer/observer.gemspec +32 -0
- data/vendor/deps/observer/test/test_observer.rb +66 -0
- data/vendor/deps/webrick/.gitignore +9 -0
- data/vendor/deps/webrick/Gemfile +3 -0
- data/vendor/deps/webrick/LICENSE.txt +22 -0
- data/vendor/deps/webrick/README.md +61 -0
- data/vendor/deps/webrick/Rakefile +10 -0
- data/vendor/deps/webrick/lib/webrick/accesslog.rb +157 -0
- data/vendor/deps/webrick/lib/webrick/cgi.rb +313 -0
- data/vendor/deps/webrick/lib/webrick/compat.rb +36 -0
- data/vendor/deps/webrick/lib/webrick/config.rb +158 -0
- data/vendor/deps/webrick/lib/webrick/cookie.rb +172 -0
- data/vendor/deps/webrick/lib/webrick/htmlutils.rb +30 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/authenticator.rb +117 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/basicauth.rb +116 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/digestauth.rb +395 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htdigest.rb +132 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htgroup.rb +97 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htpasswd.rb +158 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/userdb.rb +53 -0
- data/vendor/deps/webrick/lib/webrick/httpauth.rb +96 -0
- data/vendor/deps/webrick/lib/webrick/httpproxy.rb +354 -0
- data/vendor/deps/webrick/lib/webrick/httprequest.rb +636 -0
- data/vendor/deps/webrick/lib/webrick/httpresponse.rb +564 -0
- data/vendor/deps/webrick/lib/webrick/https.rb +152 -0
- data/vendor/deps/webrick/lib/webrick/httpserver.rb +294 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/abstract.rb +152 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/cgi_runner.rb +47 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/cgihandler.rb +126 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/erbhandler.rb +88 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/filehandler.rb +552 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/prochandler.rb +47 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet.rb +23 -0
- data/vendor/deps/webrick/lib/webrick/httpstatus.rb +194 -0
- data/vendor/deps/webrick/lib/webrick/httputils.rb +512 -0
- data/vendor/deps/webrick/lib/webrick/httpversion.rb +76 -0
- data/vendor/deps/webrick/lib/webrick/log.rb +156 -0
- data/vendor/deps/webrick/lib/webrick/server.rb +381 -0
- data/vendor/deps/webrick/lib/webrick/ssl.rb +215 -0
- data/vendor/deps/webrick/lib/webrick/utils.rb +265 -0
- data/vendor/deps/webrick/lib/webrick/version.rb +18 -0
- data/vendor/deps/webrick/lib/webrick.rb +232 -0
- data/vendor/deps/webrick/webrick.gemspec +74 -0
- metadata +412 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# httpauth/htpasswd -- Apache compatible htpasswd file
|
|
4
|
+
#
|
|
5
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
|
6
|
+
# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
|
|
7
|
+
# reserved.
|
|
8
|
+
#
|
|
9
|
+
# $IPR: htpasswd.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $
|
|
10
|
+
|
|
11
|
+
require_relative 'userdb'
|
|
12
|
+
require_relative 'basicauth'
|
|
13
|
+
require 'tempfile'
|
|
14
|
+
|
|
15
|
+
module WEBrick
|
|
16
|
+
module HTTPAuth
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Htpasswd accesses apache-compatible password files. Passwords are
|
|
20
|
+
# matched to a realm where they are valid. For security, the path for a
|
|
21
|
+
# password database should be stored outside of the paths available to the
|
|
22
|
+
# HTTP server.
|
|
23
|
+
#
|
|
24
|
+
# Htpasswd is intended for use with WEBrick::HTTPAuth::BasicAuth.
|
|
25
|
+
#
|
|
26
|
+
# To create an Htpasswd database with a single user:
|
|
27
|
+
#
|
|
28
|
+
# htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file'
|
|
29
|
+
# htpasswd.set_passwd 'my realm', 'username', 'password'
|
|
30
|
+
# htpasswd.flush
|
|
31
|
+
|
|
32
|
+
class Htpasswd
|
|
33
|
+
include UserDB
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# Open a password database at +path+
|
|
37
|
+
|
|
38
|
+
def initialize(path, password_hash: nil)
|
|
39
|
+
@path = path
|
|
40
|
+
@mtime = Time.at(0)
|
|
41
|
+
@passwd = Hash.new
|
|
42
|
+
@auth_type = BasicAuth
|
|
43
|
+
@password_hash = password_hash
|
|
44
|
+
|
|
45
|
+
case @password_hash
|
|
46
|
+
when nil
|
|
47
|
+
# begin
|
|
48
|
+
# require "string/crypt"
|
|
49
|
+
# rescue LoadError
|
|
50
|
+
# warn("Unable to load string/crypt, proceeding with deprecated use of String#crypt, consider using password_hash: :bcrypt")
|
|
51
|
+
# end
|
|
52
|
+
@password_hash = :crypt
|
|
53
|
+
when :crypt
|
|
54
|
+
# require "string/crypt"
|
|
55
|
+
when :bcrypt
|
|
56
|
+
require "bcrypt"
|
|
57
|
+
else
|
|
58
|
+
raise ArgumentError, "only :crypt and :bcrypt are supported for password_hash keyword argument"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
File.open(@path,"a").close unless File.exist?(@path)
|
|
62
|
+
reload
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# Reload passwords from the database
|
|
67
|
+
|
|
68
|
+
def reload
|
|
69
|
+
mtime = File::mtime(@path)
|
|
70
|
+
if mtime > @mtime
|
|
71
|
+
@passwd.clear
|
|
72
|
+
File.open(@path){|io|
|
|
73
|
+
while line = io.gets
|
|
74
|
+
line.chomp!
|
|
75
|
+
case line
|
|
76
|
+
when %r!\A[^:]+:[a-zA-Z0-9./]{13}\z!
|
|
77
|
+
if @password_hash == :bcrypt
|
|
78
|
+
raise StandardError, ".htpasswd file contains crypt password, only bcrypt passwords supported"
|
|
79
|
+
end
|
|
80
|
+
user, pass = line.split(":")
|
|
81
|
+
when %r!\A[^:]+:\$2[aby]\$\d{2}\$.{53}\z!
|
|
82
|
+
if @password_hash == :crypt
|
|
83
|
+
raise StandardError, ".htpasswd file contains bcrypt password, only crypt passwords supported"
|
|
84
|
+
end
|
|
85
|
+
user, pass = line.split(":")
|
|
86
|
+
when /:\$/, /:{SHA}/
|
|
87
|
+
raise NotImplementedError,
|
|
88
|
+
'MD5, SHA1 .htpasswd file not supported'
|
|
89
|
+
else
|
|
90
|
+
raise StandardError, 'bad .htpasswd file'
|
|
91
|
+
end
|
|
92
|
+
@passwd[user] = pass
|
|
93
|
+
end
|
|
94
|
+
}
|
|
95
|
+
@mtime = mtime
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
# Flush the password database. If +output+ is given the database will
|
|
101
|
+
# be written there instead of to the original path.
|
|
102
|
+
|
|
103
|
+
def flush(output=nil)
|
|
104
|
+
output ||= @path
|
|
105
|
+
tmp = Tempfile.create("htpasswd", File::dirname(output))
|
|
106
|
+
renamed = false
|
|
107
|
+
begin
|
|
108
|
+
each{|item| tmp.puts(item.join(":")) }
|
|
109
|
+
tmp.close
|
|
110
|
+
File::rename(tmp.path, output)
|
|
111
|
+
renamed = true
|
|
112
|
+
ensure
|
|
113
|
+
tmp.close
|
|
114
|
+
File.unlink(tmp.path) if !renamed
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
##
|
|
119
|
+
# Retrieves a password from the database for +user+ in +realm+. If
|
|
120
|
+
# +reload_db+ is true the database will be reloaded first.
|
|
121
|
+
|
|
122
|
+
def get_passwd(realm, user, reload_db)
|
|
123
|
+
reload() if reload_db
|
|
124
|
+
@passwd[user]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Sets a password in the database for +user+ in +realm+ to +pass+.
|
|
129
|
+
|
|
130
|
+
def set_passwd(realm, user, pass)
|
|
131
|
+
if @password_hash == :bcrypt
|
|
132
|
+
# Cost of 5 to match Apache default, and because the
|
|
133
|
+
# bcrypt default of 10 will introduce significant delays
|
|
134
|
+
# for every request.
|
|
135
|
+
@passwd[user] = BCrypt::Password.create(pass, :cost=>5)
|
|
136
|
+
else
|
|
137
|
+
@passwd[user] = make_passwd(realm, user, pass)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
##
|
|
142
|
+
# Removes a password from the database for +user+ in +realm+.
|
|
143
|
+
|
|
144
|
+
def delete_passwd(realm, user)
|
|
145
|
+
@passwd.delete(user)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
##
|
|
149
|
+
# Iterate passwords in the database.
|
|
150
|
+
|
|
151
|
+
def each # :yields: [user, password]
|
|
152
|
+
@passwd.keys.sort.each{|user|
|
|
153
|
+
yield([user, @passwd[user]])
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#--
|
|
3
|
+
# httpauth/userdb.rb -- UserDB mix-in module.
|
|
4
|
+
#
|
|
5
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
|
6
|
+
# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
|
|
7
|
+
# reserved.
|
|
8
|
+
#
|
|
9
|
+
# $IPR: userdb.rb,v 1.2 2003/02/20 07:15:48 gotoyuzo Exp $
|
|
10
|
+
|
|
11
|
+
module WEBrick
|
|
12
|
+
module HTTPAuth
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# User database mixin for HTTPAuth. This mixin dispatches user record
|
|
16
|
+
# access to the underlying auth_type for this database.
|
|
17
|
+
|
|
18
|
+
module UserDB
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# The authentication type.
|
|
22
|
+
#
|
|
23
|
+
# WEBrick::HTTPAuth::BasicAuth or WEBrick::HTTPAuth::DigestAuth are
|
|
24
|
+
# built-in.
|
|
25
|
+
|
|
26
|
+
attr_accessor :auth_type
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Creates an obscured password in +realm+ with +user+ and +password+
|
|
30
|
+
# using the auth_type of this database.
|
|
31
|
+
|
|
32
|
+
def make_passwd(realm, user, pass)
|
|
33
|
+
@auth_type::make_passwd(realm, user, pass)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# Sets a password in +realm+ with +user+ and +password+ for the
|
|
38
|
+
# auth_type of this database.
|
|
39
|
+
|
|
40
|
+
def set_passwd(realm, user, pass)
|
|
41
|
+
self[user] = pass
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
# Retrieves a password in +realm+ for +user+ for the auth_type of this
|
|
46
|
+
# database. +reload_db+ is a dummy value.
|
|
47
|
+
|
|
48
|
+
def get_passwd(realm, user, reload_db=false)
|
|
49
|
+
make_passwd(realm, user, self[user])
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# httpauth.rb -- HTTP access authentication
|
|
4
|
+
#
|
|
5
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
|
6
|
+
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
|
7
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
|
8
|
+
# reserved.
|
|
9
|
+
#
|
|
10
|
+
# $IPR: httpauth.rb,v 1.14 2003/07/22 19:20:42 gotoyuzo Exp $
|
|
11
|
+
|
|
12
|
+
require_relative 'httpauth/basicauth'
|
|
13
|
+
require_relative 'httpauth/digestauth'
|
|
14
|
+
require_relative 'httpauth/htpasswd'
|
|
15
|
+
require_relative 'httpauth/htdigest'
|
|
16
|
+
require_relative 'httpauth/htgroup'
|
|
17
|
+
|
|
18
|
+
module WEBrick
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# HTTPAuth provides both basic and digest authentication.
|
|
22
|
+
#
|
|
23
|
+
# To enable authentication for requests in WEBrick you will need a user
|
|
24
|
+
# database and an authenticator. To start, here's an Htpasswd database for
|
|
25
|
+
# use with a DigestAuth authenticator:
|
|
26
|
+
#
|
|
27
|
+
# config = { :Realm => 'DigestAuth example realm' }
|
|
28
|
+
#
|
|
29
|
+
# htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file'
|
|
30
|
+
# htpasswd.auth_type = WEBrick::HTTPAuth::DigestAuth
|
|
31
|
+
# htpasswd.set_passwd config[:Realm], 'username', 'password'
|
|
32
|
+
# htpasswd.flush
|
|
33
|
+
#
|
|
34
|
+
# The +:Realm+ is used to provide different access to different groups
|
|
35
|
+
# across several resources on a server. Typically you'll need only one
|
|
36
|
+
# realm for a server.
|
|
37
|
+
#
|
|
38
|
+
# This database can be used to create an authenticator:
|
|
39
|
+
#
|
|
40
|
+
# config[:UserDB] = htpasswd
|
|
41
|
+
#
|
|
42
|
+
# digest_auth = WEBrick::HTTPAuth::DigestAuth.new config
|
|
43
|
+
#
|
|
44
|
+
# To authenticate a request call #authenticate with a request and response
|
|
45
|
+
# object in a servlet:
|
|
46
|
+
#
|
|
47
|
+
# def do_GET req, res
|
|
48
|
+
# @authenticator.authenticate req, res
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# For digest authentication the authenticator must not be created every
|
|
52
|
+
# request, it must be passed in as an option via WEBrick::HTTPServer#mount.
|
|
53
|
+
|
|
54
|
+
module HTTPAuth
|
|
55
|
+
module_function
|
|
56
|
+
|
|
57
|
+
def _basic_auth(req, res, realm, req_field, res_field, err_type,
|
|
58
|
+
block) # :nodoc:
|
|
59
|
+
user = pass = nil
|
|
60
|
+
if /^Basic\s+(.*)/o =~ req[req_field]
|
|
61
|
+
userpass = $1
|
|
62
|
+
user, pass = userpass.unpack("m*")[0].split(":", 2)
|
|
63
|
+
end
|
|
64
|
+
if block.call(user, pass)
|
|
65
|
+
req.user = user
|
|
66
|
+
return
|
|
67
|
+
end
|
|
68
|
+
res[res_field] = "Basic realm=\"#{realm}\""
|
|
69
|
+
raise err_type
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
##
|
|
73
|
+
# Simple wrapper for providing basic authentication for a request. When
|
|
74
|
+
# called with a request +req+, response +res+, authentication +realm+ and
|
|
75
|
+
# +block+ the block will be called with a +username+ and +password+. If
|
|
76
|
+
# the block returns true the request is allowed to continue, otherwise an
|
|
77
|
+
# HTTPStatus::Unauthorized error is raised.
|
|
78
|
+
|
|
79
|
+
def basic_auth(req, res, realm, &block) # :yield: username, password
|
|
80
|
+
_basic_auth(req, res, realm, "Authorization", "WWW-Authenticate",
|
|
81
|
+
HTTPStatus::Unauthorized, block)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Simple wrapper for providing basic authentication for a proxied request.
|
|
86
|
+
# When called with a request +req+, response +res+, authentication +realm+
|
|
87
|
+
# and +block+ the block will be called with a +username+ and +password+.
|
|
88
|
+
# If the block returns true the request is allowed to continue, otherwise
|
|
89
|
+
# an HTTPStatus::ProxyAuthenticationRequired error is raised.
|
|
90
|
+
|
|
91
|
+
def proxy_basic_auth(req, res, realm, &block) # :yield: username, password
|
|
92
|
+
_basic_auth(req, res, realm, "Proxy-Authorization", "Proxy-Authenticate",
|
|
93
|
+
HTTPStatus::ProxyAuthenticationRequired, block)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# httpproxy.rb -- HTTPProxy Class
|
|
4
|
+
#
|
|
5
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
|
6
|
+
# Copyright (c) 2002 GOTO Kentaro
|
|
7
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
|
8
|
+
# reserved.
|
|
9
|
+
#
|
|
10
|
+
# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
|
|
11
|
+
# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
|
|
12
|
+
|
|
13
|
+
require_relative "httpserver"
|
|
14
|
+
require "net/http"
|
|
15
|
+
|
|
16
|
+
module WEBrick
|
|
17
|
+
|
|
18
|
+
NullReader = Object.new # :nodoc:
|
|
19
|
+
class << NullReader # :nodoc:
|
|
20
|
+
def read(*args)
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
alias gets read
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
FakeProxyURI = Object.new # :nodoc:
|
|
27
|
+
class << FakeProxyURI # :nodoc:
|
|
28
|
+
def method_missing(meth, *args)
|
|
29
|
+
if %w(scheme host port path query userinfo).member?(meth.to_s)
|
|
30
|
+
return nil
|
|
31
|
+
end
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# :startdoc:
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# An HTTP Proxy server which proxies GET, HEAD and POST requests.
|
|
40
|
+
#
|
|
41
|
+
# To create a simple proxy server:
|
|
42
|
+
#
|
|
43
|
+
# require 'webrick'
|
|
44
|
+
# require 'webrick/httpproxy'
|
|
45
|
+
#
|
|
46
|
+
# proxy = WEBrick::HTTPProxyServer.new Port: 8000
|
|
47
|
+
#
|
|
48
|
+
# trap 'INT' do proxy.shutdown end
|
|
49
|
+
# trap 'TERM' do proxy.shutdown end
|
|
50
|
+
#
|
|
51
|
+
# proxy.start
|
|
52
|
+
#
|
|
53
|
+
# See ::new for proxy-specific configuration items.
|
|
54
|
+
#
|
|
55
|
+
# == Modifying proxied responses
|
|
56
|
+
#
|
|
57
|
+
# To modify content the proxy server returns use the +:ProxyContentHandler+
|
|
58
|
+
# option:
|
|
59
|
+
#
|
|
60
|
+
# handler = proc do |req, res|
|
|
61
|
+
# if res['content-type'] == 'text/plain' then
|
|
62
|
+
# res.body << "\nThis content was proxied!\n"
|
|
63
|
+
# end
|
|
64
|
+
# end
|
|
65
|
+
#
|
|
66
|
+
# proxy =
|
|
67
|
+
# WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler
|
|
68
|
+
|
|
69
|
+
class HTTPProxyServer < HTTPServer
|
|
70
|
+
|
|
71
|
+
##
|
|
72
|
+
# Proxy server configurations. The proxy server handles the following
|
|
73
|
+
# configuration items in addition to those supported by HTTPServer:
|
|
74
|
+
#
|
|
75
|
+
# :ProxyAuthProc:: Called with a request and response to authorize a
|
|
76
|
+
# request
|
|
77
|
+
# :ProxyVia:: Appended to the via header
|
|
78
|
+
# :ProxyURI:: The proxy server's URI
|
|
79
|
+
# :ProxyContentHandler:: Called with a request and response and allows
|
|
80
|
+
# modification of the response
|
|
81
|
+
# :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60
|
|
82
|
+
# seconds for read operations
|
|
83
|
+
|
|
84
|
+
def initialize(config={}, default=Config::HTTP)
|
|
85
|
+
super(config, default)
|
|
86
|
+
c = @config
|
|
87
|
+
@via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# :stopdoc:
|
|
91
|
+
def service(req, res)
|
|
92
|
+
if req.request_method == "CONNECT"
|
|
93
|
+
do_CONNECT(req, res)
|
|
94
|
+
elsif req.unparsed_uri =~ %r!^http://!
|
|
95
|
+
proxy_service(req, res)
|
|
96
|
+
else
|
|
97
|
+
super(req, res)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def proxy_auth(req, res)
|
|
102
|
+
if proc = @config[:ProxyAuthProc]
|
|
103
|
+
proc.call(req, res)
|
|
104
|
+
end
|
|
105
|
+
req.header.delete("proxy-authorization")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def proxy_uri(req, res)
|
|
109
|
+
# should return upstream proxy server's URI
|
|
110
|
+
return @config[:ProxyURI]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def proxy_service(req, res)
|
|
114
|
+
# Proxy Authentication
|
|
115
|
+
proxy_auth(req, res)
|
|
116
|
+
|
|
117
|
+
begin
|
|
118
|
+
public_send("do_#{req.request_method}", req, res)
|
|
119
|
+
rescue NoMethodError
|
|
120
|
+
raise HTTPStatus::MethodNotAllowed,
|
|
121
|
+
"unsupported method `#{req.request_method}'."
|
|
122
|
+
rescue => err
|
|
123
|
+
logger.debug("#{err.class}: #{err.message}")
|
|
124
|
+
raise HTTPStatus::ServiceUnavailable, err.message
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Process contents
|
|
128
|
+
if handler = @config[:ProxyContentHandler]
|
|
129
|
+
handler.call(req, res)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def do_CONNECT(req, res)
|
|
134
|
+
# Proxy Authentication
|
|
135
|
+
proxy_auth(req, res)
|
|
136
|
+
|
|
137
|
+
ua = Thread.current[:WEBrickSocket] # User-Agent
|
|
138
|
+
raise HTTPStatus::InternalServerError,
|
|
139
|
+
"[BUG] cannot get socket" unless ua
|
|
140
|
+
|
|
141
|
+
host, port = req.unparsed_uri.split(":", 2)
|
|
142
|
+
# Proxy authentication for upstream proxy server
|
|
143
|
+
if proxy = proxy_uri(req, res)
|
|
144
|
+
proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
|
|
145
|
+
if proxy.userinfo
|
|
146
|
+
credentials = "Basic " + [proxy.userinfo].pack("m0")
|
|
147
|
+
end
|
|
148
|
+
host, port = proxy.host, proxy.port
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
begin
|
|
152
|
+
@logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.")
|
|
153
|
+
os = TCPSocket.new(host, port) # origin server
|
|
154
|
+
|
|
155
|
+
if proxy
|
|
156
|
+
@logger.debug("CONNECT: sending a Request-Line")
|
|
157
|
+
os << proxy_request_line << CRLF
|
|
158
|
+
@logger.debug("CONNECT: > #{proxy_request_line}")
|
|
159
|
+
if credentials
|
|
160
|
+
@logger.debug("CONNECT: sending credentials")
|
|
161
|
+
os << "Proxy-Authorization: " << credentials << CRLF
|
|
162
|
+
end
|
|
163
|
+
os << CRLF
|
|
164
|
+
proxy_status_line = os.gets(LF)
|
|
165
|
+
@logger.debug("CONNECT: read Status-Line from the upstream server")
|
|
166
|
+
@logger.debug("CONNECT: < #{proxy_status_line}")
|
|
167
|
+
if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line
|
|
168
|
+
while line = os.gets(LF)
|
|
169
|
+
break if /\A(#{CRLF}|#{LF})\z/om =~ line
|
|
170
|
+
end
|
|
171
|
+
else
|
|
172
|
+
raise HTTPStatus::BadGateway
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
@logger.debug("CONNECT #{host}:#{port}: succeeded")
|
|
176
|
+
res.status = HTTPStatus::RC_OK
|
|
177
|
+
rescue => ex
|
|
178
|
+
@logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'")
|
|
179
|
+
res.set_error(ex)
|
|
180
|
+
raise HTTPStatus::EOFError
|
|
181
|
+
ensure
|
|
182
|
+
if handler = @config[:ProxyContentHandler]
|
|
183
|
+
handler.call(req, res)
|
|
184
|
+
end
|
|
185
|
+
res.send_response(ua)
|
|
186
|
+
access_log(@config, req, res)
|
|
187
|
+
|
|
188
|
+
# Should clear request-line not to send the response twice.
|
|
189
|
+
# see: HTTPServer#run
|
|
190
|
+
req.parse(NullReader) rescue nil
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
begin
|
|
194
|
+
while fds = IO::select([ua, os])
|
|
195
|
+
if fds[0].member?(ua)
|
|
196
|
+
buf = ua.readpartial(1024);
|
|
197
|
+
@logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
|
|
198
|
+
os.write(buf)
|
|
199
|
+
elsif fds[0].member?(os)
|
|
200
|
+
buf = os.readpartial(1024);
|
|
201
|
+
@logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
|
|
202
|
+
ua.write(buf)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
rescue
|
|
206
|
+
os.close
|
|
207
|
+
@logger.debug("CONNECT #{host}:#{port}: closed")
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
raise HTTPStatus::EOFError
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def do_GET(req, res)
|
|
214
|
+
perform_proxy_request(req, res, Net::HTTP::Get)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def do_HEAD(req, res)
|
|
218
|
+
perform_proxy_request(req, res, Net::HTTP::Head)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def do_POST(req, res)
|
|
222
|
+
perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def do_OPTIONS(req, res)
|
|
226
|
+
res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT"
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
private
|
|
230
|
+
|
|
231
|
+
# Some header fields should not be transferred.
|
|
232
|
+
HopByHop = %w( connection keep-alive proxy-authenticate upgrade
|
|
233
|
+
proxy-authorization te trailers transfer-encoding )
|
|
234
|
+
ShouldNotTransfer = %w( set-cookie proxy-connection )
|
|
235
|
+
def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end
|
|
236
|
+
|
|
237
|
+
def choose_header(src, dst)
|
|
238
|
+
connections = split_field(src['connection'])
|
|
239
|
+
src.each{|key, value|
|
|
240
|
+
key = key.downcase
|
|
241
|
+
if HopByHop.member?(key) || # RFC2616: 13.5.1
|
|
242
|
+
connections.member?(key) || # RFC2616: 14.10
|
|
243
|
+
ShouldNotTransfer.member?(key) # pragmatics
|
|
244
|
+
@logger.debug("choose_header: `#{key}: #{value}'")
|
|
245
|
+
next
|
|
246
|
+
end
|
|
247
|
+
dst[key] = value
|
|
248
|
+
}
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Net::HTTP is stupid about the multiple header fields.
|
|
252
|
+
# Here is workaround:
|
|
253
|
+
def set_cookie(src, dst)
|
|
254
|
+
if str = src['set-cookie']
|
|
255
|
+
cookies = []
|
|
256
|
+
str.split(/,\s*/).each{|token|
|
|
257
|
+
if /^[^=]+;/o =~ token
|
|
258
|
+
cookies[-1] << ", " << token
|
|
259
|
+
elsif /=/o =~ token
|
|
260
|
+
cookies << token
|
|
261
|
+
else
|
|
262
|
+
cookies[-1] << ", " << token
|
|
263
|
+
end
|
|
264
|
+
}
|
|
265
|
+
dst.cookies.replace(cookies)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def set_via(h)
|
|
270
|
+
if @config[:ProxyVia]
|
|
271
|
+
if h['via']
|
|
272
|
+
h['via'] << ", " << @via
|
|
273
|
+
else
|
|
274
|
+
h['via'] = @via
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def setup_proxy_header(req, res)
|
|
280
|
+
# Choose header fields to transfer
|
|
281
|
+
header = Hash.new
|
|
282
|
+
choose_header(req, header)
|
|
283
|
+
set_via(header)
|
|
284
|
+
return header
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def setup_upstream_proxy_authentication(req, res, header)
|
|
288
|
+
if upstream = proxy_uri(req, res)
|
|
289
|
+
if upstream.userinfo
|
|
290
|
+
header['proxy-authorization'] =
|
|
291
|
+
"Basic " + [upstream.userinfo].pack("m0")
|
|
292
|
+
end
|
|
293
|
+
return upstream
|
|
294
|
+
end
|
|
295
|
+
return FakeProxyURI
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def create_net_http(uri, upstream)
|
|
299
|
+
Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def perform_proxy_request(req, res, req_class, body_stream = nil)
|
|
303
|
+
uri = req.request_uri
|
|
304
|
+
path = uri.path.dup
|
|
305
|
+
path << "?" << uri.query if uri.query
|
|
306
|
+
header = setup_proxy_header(req, res)
|
|
307
|
+
upstream = setup_upstream_proxy_authentication(req, res, header)
|
|
308
|
+
|
|
309
|
+
body_tmp = []
|
|
310
|
+
http = create_net_http(uri, upstream)
|
|
311
|
+
req_fib = Fiber.new do
|
|
312
|
+
http.start do
|
|
313
|
+
if @config[:ProxyTimeout]
|
|
314
|
+
################################## these issues are
|
|
315
|
+
http.open_timeout = 30 # secs # necessary (maybe because
|
|
316
|
+
http.read_timeout = 60 # secs # Ruby's bug, but why?)
|
|
317
|
+
##################################
|
|
318
|
+
end
|
|
319
|
+
if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i
|
|
320
|
+
header['Transfer-Encoding'] = 'chunked'
|
|
321
|
+
end
|
|
322
|
+
http_req = req_class.new(path, header)
|
|
323
|
+
http_req.body_stream = body_stream if body_stream
|
|
324
|
+
http.request(http_req) do |response|
|
|
325
|
+
# Persistent connection requirements are mysterious for me.
|
|
326
|
+
# So I will close the connection in every response.
|
|
327
|
+
res['proxy-connection'] = "close"
|
|
328
|
+
res['connection'] = "close"
|
|
329
|
+
|
|
330
|
+
# stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
|
|
331
|
+
res.status = response.code.to_i
|
|
332
|
+
res.chunked = response.chunked?
|
|
333
|
+
choose_header(response, res)
|
|
334
|
+
set_cookie(response, res)
|
|
335
|
+
set_via(res)
|
|
336
|
+
response.read_body do |buf|
|
|
337
|
+
body_tmp << buf
|
|
338
|
+
Fiber.yield # wait for res.body Proc#call
|
|
339
|
+
end
|
|
340
|
+
end # http.request
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
req_fib.resume # read HTTP response headers and first chunk of the body
|
|
344
|
+
res.body = ->(socket) do
|
|
345
|
+
while buf = body_tmp.shift
|
|
346
|
+
socket.write(buf)
|
|
347
|
+
buf.clear
|
|
348
|
+
req_fib.resume # continue response.read_body
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
# :stopdoc:
|
|
353
|
+
end
|
|
354
|
+
end
|