simple-client 0.0.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.
- data/.bundle/config +4 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +23 -0
- data/bin/rake +16 -0
- data/lib/simple-client/simple-client.rb +229 -0
- data/lib/simple-client/version.rb +4 -0
- data/lib/simple-client.rb +1 -0
- data/test/test_simple-client.rb +236 -0
- data/vendor/bundle/ruby/1.8/bin/rake +19 -0
- data/vendor/bundle/ruby/1.8/cache/addressable-2.2.8.gem +0 -0
- data/vendor/bundle/ruby/1.8/cache/crack-0.3.1.gem +0 -0
- data/vendor/bundle/ruby/1.8/cache/rake-0.9.2.2.gem +0 -0
- data/vendor/bundle/ruby/1.8/cache/webmock-1.8.8.gem +0 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/CHANGELOG.md +126 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/Gemfile +17 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/Gemfile.lock +35 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/LICENSE.txt +202 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/README.md +83 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/Rakefile +37 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/lib/addressable/idna/native.rb +43 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/lib/addressable/idna/pure.rb +4886 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/lib/addressable/idna.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/lib/addressable/template.rb +1047 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/lib/addressable/uri.rb +2288 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/lib/addressable/version.rb +30 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/spec/addressable/idna_spec.rb +216 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/spec/addressable/net_http_compat_spec.rb +26 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/spec/addressable/template_spec.rb +2144 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/spec/addressable/uri_spec.rb +4928 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/clobber.rake +2 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/gem.rake +85 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/git.rake +45 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/metrics.rake +22 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/rspec.rake +58 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/rubyforge.rake +89 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/tasks/yard.rake +27 -0
- data/vendor/bundle/ruby/1.8/gems/addressable-2.2.8/website/index.html +110 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/History +25 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/LICENSE +20 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/README.rdoc +42 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/Rakefile +32 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/crack.gemspec +53 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/lib/crack/json.rb +79 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/lib/crack/util.rb +17 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/lib/crack/xml.rb +232 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/lib/crack.rb +8 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/crack_test.rb +4 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/data/twittersearch-firefox.json +1 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/data/twittersearch-ie.json +1 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/hash_test.rb +28 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/json_test.rb +82 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/parser_test.rb +27 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/string_test.rb +31 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/test_helper.rb +12 -0
- data/vendor/bundle/ruby/1.8/gems/crack-0.3.1/test/xml_test.rb +499 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/CHANGES +522 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/MIT-LICENSE +21 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/README.rdoc +197 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/Rakefile +369 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/TODO +20 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/bin/rake +33 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/command_line_usage.rdoc +114 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/example/Rakefile1 +38 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/example/Rakefile2 +35 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/example/a.c +6 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/example/b.c +6 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/example/main.c +11 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/glossary.rdoc +51 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/jamis.rb +591 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/proto_rake.rdoc +127 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/rake.1.gz +0 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/rakefile.rdoc +557 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/rational.rdoc +151 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.4.14.rdoc +23 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.4.15.rdoc +35 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.5.0.rdoc +53 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.5.3.rdoc +78 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.5.4.rdoc +46 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.6.0.rdoc +141 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.7.0.rdoc +119 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.7.1.rdoc +59 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.7.2.rdoc +121 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.7.3.rdoc +47 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.0.rdoc +114 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.2.rdoc +165 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.3.rdoc +112 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.4.rdoc +147 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.5.rdoc +53 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.6.rdoc +55 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.8.7.rdoc +55 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.9.0.rdoc +112 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.9.1.rdoc +52 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/doc/release_notes/rake-0.9.2.rdoc +49 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/install.rb +90 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/alt_system.rb +109 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/application.rb +595 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/classic_namespace.rb +11 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/clean.rb +32 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/cloneable.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/contrib/compositepublisher.rb +21 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/contrib/ftptools.rb +150 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/contrib/publisher.rb +73 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/contrib/rubyforgepublisher.rb +16 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/contrib/sshpublisher.rb +50 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/contrib/sys.rb +191 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/default_loader.rb +10 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/dsl_definition.rb +176 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/early_time.rb +18 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/ext/core.rb +27 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/ext/module.rb +39 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/ext/string.rb +167 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/ext/time.rb +14 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/file_creation_task.rb +24 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/file_list.rb +403 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/file_task.rb +47 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/file_utils.rb +114 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/file_utils_ext.rb +145 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/gempackagetask.rb +15 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/invocation_chain.rb +51 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/invocation_exception_mixin.rb +16 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/loaders/makefile.rb +40 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/multi_task.rb +16 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/name_space.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/packagetask.rb +185 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/pathmap.rb +1 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/pseudo_status.rb +24 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/rake_module.rb +29 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb +22 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/rdoctask.rb +234 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/ruby182_test_unit_fix.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/rule_recursion_overflow_error.rb +20 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/runtest.rb +21 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/task.rb +327 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/task_argument_error.rb +7 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/task_arguments.rb +78 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/task_manager.rb +307 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/tasklib.rb +22 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/testtask.rb +191 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/version.rb +8 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake/win32.rb +55 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/lib/rake.rb +69 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/file_creation.rb +34 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/helper.rb +492 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake.rb +40 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_application.rb +489 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_application_options.rb +335 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_clean.rb +14 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_definitions.rb +80 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_directory_task.rb +46 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_dsl.rb +77 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_early_time.rb +31 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_extension.rb +59 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_file_creation_task.rb +56 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_file_list.rb +628 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_file_list_path_map.rb +8 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_file_task.rb +102 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_file_utils.rb +305 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_ftp_file.rb +59 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_functional.rb +450 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_invocation_chain.rb +52 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_makefile_loader.rb +44 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_multi_task.rb +51 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_name_space.rb +43 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_package_task.rb +79 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_path_map.rb +157 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_path_map_explode.rb +34 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_path_map_partial.rb +18 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_pseudo_status.rb +21 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_rake_test_loader.rb +21 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_rdoc_task.rb +83 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_require.rb +40 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_rules.rb +327 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task.rb +267 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task_argument_parsing.rb +103 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task_arguments.rb +88 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task_lib.rb +9 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task_manager.rb +157 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task_manager_argument_resolution.rb +36 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_task_with_arguments.rb +173 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_test_task.rb +120 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_top_level_functions.rb +111 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_rake_win32.rb +72 -0
- data/vendor/bundle/ruby/1.8/gems/rake-0.9.2.2/test/test_sys.rb +20 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/CHANGELOG.md +749 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/Gemfile +21 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/Guardfile +24 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/LICENSE +20 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/README.md +728 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/Rakefile +65 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/api.rb +63 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/assertion_failure.rb +11 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/callback_registry.rb +35 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/config.rb +10 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/cucumber.rb +8 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/deprecation.rb +9 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/errors.rb +33 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/curb_adapter.rb +287 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/em_http_request/em_http_request_0_x.rb +151 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +212 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +11 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/excon_adapter.rb +95 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/httpclient_adapter.rb +193 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/net_http.rb +279 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/patron_adapter.rb +129 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +180 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/matchers/hash_including_matcher.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/minitest.rb +15 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/rack_response.rb +63 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/request_execution_verifier.rb +56 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/request_pattern.rb +282 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/request_registry.rb +35 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/request_signature.rb +50 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/request_stub.rb +97 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/response.rb +144 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/responses_sequence.rb +40 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/rspec/matchers/request_pattern_matcher.rb +42 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/rspec/matchers/webmock_matcher.rb +46 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/rspec/matchers.rb +28 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/rspec.rb +33 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/stub_registry.rb +61 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/stub_request_snippet.rb +30 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/test_unit.rb +20 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/util/hash_counter.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/util/hash_keys_stringifier.rb +23 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/util/headers.rb +43 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/util/json.rb +54 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/util/uri.rb +101 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/util/version_checker.rb +73 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/version.rb +3 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock/webmock.rb +124 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/lib/webmock.rb +49 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/minitest/test_helper.rb +29 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/minitest/test_webmock.rb +6 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/minitest/webmock_spec.rb +50 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/curb/curb_spec.rb +340 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/curb/curb_spec_helper.rb +144 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/em_http_request/em_http_request_spec.rb +183 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +72 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/excon/excon_spec.rb +15 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/excon/excon_spec_helper.rb +38 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/httpclient/httpclient_spec.rb +76 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/httpclient/httpclient_spec_helper.rb +48 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/net_http/net_http_shared.rb +125 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/net_http/net_http_spec.rb +255 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/net_http/net_http_spec_helper.rb +55 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/patron/patron_spec.rb +136 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/patron/patron_spec_helper.rb +50 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +142 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/callbacks.rb +146 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/request_expectations.rb +666 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/returning_declared_responses.rb +367 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/shared/stubbing_requests.rb +447 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +74 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +56 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/acceptance/webmock_shared.rb +41 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/quality_spec.rb +60 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/spec_helper.rb +57 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/support/example_curl_output.txt +22 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/support/my_rack_app.rb +48 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/support/network_connection.rb +25 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/support/webmock_server.rb +65 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/errors_spec.rb +32 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/rack_response_spec.rb +74 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/request_execution_verifier_spec.rb +100 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/request_pattern_spec.rb +479 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/request_registry_spec.rb +75 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/request_signature_spec.rb +113 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/request_stub_spec.rb +198 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/response_spec.rb +267 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/stub_registry_spec.rb +86 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/stub_request_snippet_spec.rb +95 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/util/hash_counter_spec.rb +39 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/util/headers_spec.rb +28 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/util/json_spec.rb +7 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/util/uri_spec.rb +257 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/util/version_checker_spec.rb +59 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/spec/unit/webmock_spec.rb +7 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/test/http_request.rb +24 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/test/shared_test.rb +76 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/test/test_helper.rb +23 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/test/test_webmock.rb +6 -0
- data/vendor/bundle/ruby/1.8/gems/webmock-1.8.8/webmock.gemspec +35 -0
- data/vendor/bundle/ruby/1.8/specifications/addressable-2.2.8.gemspec +38 -0
- data/vendor/bundle/ruby/1.8/specifications/crack-0.3.1.gemspec +25 -0
- data/vendor/bundle/ruby/1.8/specifications/rake-0.9.2.2.gemspec +33 -0
- data/vendor/bundle/ruby/1.8/specifications/webmock-1.8.8.gemspec +61 -0
- metadata +390 -0
@@ -0,0 +1,1047 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
#--
|
3
|
+
# Copyright (C) 2006-2011 Bob Aman
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#++
|
17
|
+
|
18
|
+
|
19
|
+
require "addressable/version"
|
20
|
+
require "addressable/uri"
|
21
|
+
|
22
|
+
module Addressable
|
23
|
+
##
|
24
|
+
# This is an implementation of a URI template based on
|
25
|
+
# <a href="http://tinyurl.com/uritemplatedraft03">URI Template draft 03</a>.
|
26
|
+
class Template
|
27
|
+
# Constants used throughout the template code.
|
28
|
+
anything =
|
29
|
+
Addressable::URI::CharacterClasses::RESERVED +
|
30
|
+
Addressable::URI::CharacterClasses::UNRESERVED
|
31
|
+
OPERATOR_EXPANSION =
|
32
|
+
/\{-([a-zA-Z]+)\|([#{anything}]+)\|([#{anything}]+)\}/
|
33
|
+
VARIABLE_EXPANSION = /\{([#{anything}]+?)(?:=([#{anything}]+))?\}/
|
34
|
+
|
35
|
+
##
|
36
|
+
# Raised if an invalid template value is supplied.
|
37
|
+
class InvalidTemplateValueError < StandardError
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Raised if an invalid template operator is used in a pattern.
|
42
|
+
class InvalidTemplateOperatorError < StandardError
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Raised if an invalid template operator is used in a pattern.
|
47
|
+
class TemplateOperatorAbortedError < StandardError
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# This class represents the data that is extracted when a Template
|
52
|
+
# is matched against a URI.
|
53
|
+
class MatchData
|
54
|
+
##
|
55
|
+
# Creates a new MatchData object.
|
56
|
+
# MatchData objects should never be instantiated directly.
|
57
|
+
#
|
58
|
+
# @param [Addressable::URI] uri
|
59
|
+
# The URI that the template was matched against.
|
60
|
+
def initialize(uri, template, mapping)
|
61
|
+
@uri = uri.dup.freeze
|
62
|
+
@template = template
|
63
|
+
@mapping = mapping.dup.freeze
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# @return [Addressable::URI]
|
68
|
+
# The URI that the Template was matched against.
|
69
|
+
attr_reader :uri
|
70
|
+
|
71
|
+
##
|
72
|
+
# @return [Addressable::Template]
|
73
|
+
# The Template used for the match.
|
74
|
+
attr_reader :template
|
75
|
+
|
76
|
+
##
|
77
|
+
# @return [Hash]
|
78
|
+
# The mapping that resulted from the match.
|
79
|
+
# Note that this mapping does not include keys or values for
|
80
|
+
# variables that appear in the Template, but are not present
|
81
|
+
# in the URI.
|
82
|
+
attr_reader :mapping
|
83
|
+
|
84
|
+
##
|
85
|
+
# @return [Array]
|
86
|
+
# The list of variables that were present in the Template.
|
87
|
+
# Note that this list will include variables which do not appear
|
88
|
+
# in the mapping because they were not present in URI.
|
89
|
+
def variables
|
90
|
+
self.template.variables
|
91
|
+
end
|
92
|
+
alias_method :keys, :variables
|
93
|
+
|
94
|
+
##
|
95
|
+
# @return [Array]
|
96
|
+
# The list of values that were captured by the Template.
|
97
|
+
# Note that this list will include nils for any variables which
|
98
|
+
# were in the Template, but did not appear in the URI.
|
99
|
+
def values
|
100
|
+
@values ||= self.variables.inject([]) do |accu, key|
|
101
|
+
accu << self.mapping[key]
|
102
|
+
accu
|
103
|
+
end
|
104
|
+
end
|
105
|
+
alias_method :captures, :values
|
106
|
+
|
107
|
+
##
|
108
|
+
# Returns a <tt>String</tt> representation of the MatchData's state.
|
109
|
+
#
|
110
|
+
# @return [String] The MatchData's state, as a <tt>String</tt>.
|
111
|
+
def inspect
|
112
|
+
sprintf("#<%s:%#0x RESULT:%s>",
|
113
|
+
self.class.to_s, self.object_id, self.mapping.inspect)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Creates a new <tt>Addressable::Template</tt> object.
|
119
|
+
#
|
120
|
+
# @param [#to_str] pattern The URI Template pattern.
|
121
|
+
#
|
122
|
+
# @return [Addressable::Template] The initialized Template object.
|
123
|
+
def initialize(pattern)
|
124
|
+
if !pattern.respond_to?(:to_str)
|
125
|
+
raise TypeError, "Can't convert #{pattern.class} into String."
|
126
|
+
end
|
127
|
+
@pattern = pattern.to_str.freeze
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# @return [String] The Template object's pattern.
|
132
|
+
attr_reader :pattern
|
133
|
+
|
134
|
+
##
|
135
|
+
# Returns a <tt>String</tt> representation of the Template object's state.
|
136
|
+
#
|
137
|
+
# @return [String] The Template object's state, as a <tt>String</tt>.
|
138
|
+
def inspect
|
139
|
+
sprintf("#<%s:%#0x PATTERN:%s>",
|
140
|
+
self.class.to_s, self.object_id, self.pattern)
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Extracts a mapping from the URI using a URI Template pattern.
|
145
|
+
#
|
146
|
+
# @param [Addressable::URI, #to_str] uri
|
147
|
+
# The URI to extract from.
|
148
|
+
#
|
149
|
+
# @param [#restore, #match] processor
|
150
|
+
# A template processor object may optionally be supplied.
|
151
|
+
#
|
152
|
+
# The object should respond to either the <tt>restore</tt> or
|
153
|
+
# <tt>match</tt> messages or both. The <tt>restore</tt> method should
|
154
|
+
# take two parameters: `[String] name` and `[String] value`.
|
155
|
+
# The <tt>restore</tt> method should reverse any transformations that
|
156
|
+
# have been performed on the value to ensure a valid URI.
|
157
|
+
# The <tt>match</tt> method should take a single
|
158
|
+
# parameter: `[String] name`. The <tt>match</tt> method should return
|
159
|
+
# a <tt>String</tt> containing a regular expression capture group for
|
160
|
+
# matching on that particular variable. The default value is `".*?"`.
|
161
|
+
# The <tt>match</tt> method has no effect on multivariate operator
|
162
|
+
# expansions.
|
163
|
+
#
|
164
|
+
# @return [Hash, NilClass]
|
165
|
+
# The <tt>Hash</tt> mapping that was extracted from the URI, or
|
166
|
+
# <tt>nil</tt> if the URI didn't match the template.
|
167
|
+
#
|
168
|
+
# @example
|
169
|
+
# class ExampleProcessor
|
170
|
+
# def self.restore(name, value)
|
171
|
+
# return value.gsub(/\+/, " ") if name == "query"
|
172
|
+
# return value
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
# def self.match(name)
|
176
|
+
# return ".*?" if name == "first"
|
177
|
+
# return ".*"
|
178
|
+
# end
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
# uri = Addressable::URI.parse(
|
182
|
+
# "http://example.com/search/an+example+search+query/"
|
183
|
+
# )
|
184
|
+
# Addressable::Template.new(
|
185
|
+
# "http://example.com/search/{query}/"
|
186
|
+
# ).extract(uri, ExampleProcessor)
|
187
|
+
# #=> {"query" => "an example search query"}
|
188
|
+
#
|
189
|
+
# uri = Addressable::URI.parse("http://example.com/a/b/c/")
|
190
|
+
# Addressable::Template.new(
|
191
|
+
# "http://example.com/{first}/{second}/"
|
192
|
+
# ).extract(uri, ExampleProcessor)
|
193
|
+
# #=> {"first" => "a", "second" => "b/c"}
|
194
|
+
#
|
195
|
+
# uri = Addressable::URI.parse("http://example.com/a/b/c/")
|
196
|
+
# Addressable::Template.new(
|
197
|
+
# "http://example.com/{first}/{-list|/|second}/"
|
198
|
+
# ).extract(uri)
|
199
|
+
# #=> {"first" => "a", "second" => ["b", "c"]}
|
200
|
+
def extract(uri, processor=nil)
|
201
|
+
match_data = self.match(uri, processor)
|
202
|
+
return (match_data ? match_data.mapping : nil)
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Extracts match data from the URI using a URI Template pattern.
|
207
|
+
#
|
208
|
+
# @param [Addressable::URI, #to_str] uri
|
209
|
+
# The URI to extract from.
|
210
|
+
#
|
211
|
+
# @param [#restore, #match] processor
|
212
|
+
# A template processor object may optionally be supplied.
|
213
|
+
#
|
214
|
+
# The object should respond to either the <tt>restore</tt> or
|
215
|
+
# <tt>match</tt> messages or both. The <tt>restore</tt> method should
|
216
|
+
# take two parameters: `[String] name` and `[String] value`.
|
217
|
+
# The <tt>restore</tt> method should reverse any transformations that
|
218
|
+
# have been performed on the value to ensure a valid URI.
|
219
|
+
# The <tt>match</tt> method should take a single
|
220
|
+
# parameter: `[String] name`. The <tt>match</tt> method should return
|
221
|
+
# a <tt>String</tt> containing a regular expression capture group for
|
222
|
+
# matching on that particular variable. The default value is `".*?"`.
|
223
|
+
# The <tt>match</tt> method has no effect on multivariate operator
|
224
|
+
# expansions.
|
225
|
+
#
|
226
|
+
# @return [Hash, NilClass]
|
227
|
+
# The <tt>Hash</tt> mapping that was extracted from the URI, or
|
228
|
+
# <tt>nil</tt> if the URI didn't match the template.
|
229
|
+
#
|
230
|
+
# @example
|
231
|
+
# class ExampleProcessor
|
232
|
+
# def self.restore(name, value)
|
233
|
+
# return value.gsub(/\+/, " ") if name == "query"
|
234
|
+
# return value
|
235
|
+
# end
|
236
|
+
#
|
237
|
+
# def self.match(name)
|
238
|
+
# return ".*?" if name == "first"
|
239
|
+
# return ".*"
|
240
|
+
# end
|
241
|
+
# end
|
242
|
+
#
|
243
|
+
# uri = Addressable::URI.parse(
|
244
|
+
# "http://example.com/search/an+example+search+query/"
|
245
|
+
# )
|
246
|
+
# match = Addressable::Template.new(
|
247
|
+
# "http://example.com/search/{query}/"
|
248
|
+
# ).match(uri, ExampleProcessor)
|
249
|
+
# match.variables
|
250
|
+
# #=> ["query"]
|
251
|
+
# match.captures
|
252
|
+
# #=> ["an example search query"]
|
253
|
+
#
|
254
|
+
# uri = Addressable::URI.parse("http://example.com/a/b/c/")
|
255
|
+
# match = Addressable::Template.new(
|
256
|
+
# "http://example.com/{first}/{second}/"
|
257
|
+
# ).match(uri, ExampleProcessor)
|
258
|
+
# match.variables
|
259
|
+
# #=> ["first", "second"]
|
260
|
+
# match.captures
|
261
|
+
# #=> ["a", "b/c"]
|
262
|
+
#
|
263
|
+
# uri = Addressable::URI.parse("http://example.com/a/b/c/")
|
264
|
+
# match = Addressable::Template.new(
|
265
|
+
# "http://example.com/{first}/{-list|/|second}/"
|
266
|
+
# ).match(uri)
|
267
|
+
# match.variables
|
268
|
+
# #=> ["first", "second"]
|
269
|
+
# match.captures
|
270
|
+
# #=> ["a", ["b", "c"]]
|
271
|
+
def match(uri, processor=nil)
|
272
|
+
uri = Addressable::URI.parse(uri)
|
273
|
+
mapping = {}
|
274
|
+
|
275
|
+
# First, we need to process the pattern, and extract the values.
|
276
|
+
expansions, expansion_regexp =
|
277
|
+
parse_template_pattern(pattern, processor)
|
278
|
+
unparsed_values = uri.to_str.scan(expansion_regexp).flatten
|
279
|
+
|
280
|
+
if uri.to_str == pattern
|
281
|
+
return Addressable::Template::MatchData.new(uri, self, mapping)
|
282
|
+
elsif expansions.size > 0 && expansions.size == unparsed_values.size
|
283
|
+
expansions.each_with_index do |expansion, index|
|
284
|
+
unparsed_value = unparsed_values[index]
|
285
|
+
if expansion =~ OPERATOR_EXPANSION
|
286
|
+
operator, argument, variables =
|
287
|
+
parse_template_expansion(expansion)
|
288
|
+
extract_method = "extract_#{operator}_operator"
|
289
|
+
if ([extract_method, extract_method.to_sym] &
|
290
|
+
private_methods).empty?
|
291
|
+
raise InvalidTemplateOperatorError,
|
292
|
+
"Invalid template operator: #{operator}"
|
293
|
+
else
|
294
|
+
begin
|
295
|
+
send(
|
296
|
+
extract_method.to_sym, unparsed_value, processor,
|
297
|
+
argument, variables, mapping
|
298
|
+
)
|
299
|
+
rescue TemplateOperatorAbortedError
|
300
|
+
return nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
else
|
304
|
+
name = expansion[VARIABLE_EXPANSION, 1]
|
305
|
+
value = unparsed_value
|
306
|
+
if processor != nil && processor.respond_to?(:restore)
|
307
|
+
value = processor.restore(name, value)
|
308
|
+
end
|
309
|
+
if mapping[name] == nil || mapping[name] == value
|
310
|
+
mapping[name] = value
|
311
|
+
else
|
312
|
+
return nil
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
return Addressable::Template::MatchData.new(uri, self, mapping)
|
317
|
+
else
|
318
|
+
return nil
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
##
|
323
|
+
# Expands a URI template into another URI template.
|
324
|
+
#
|
325
|
+
# @param [Hash] mapping The mapping that corresponds to the pattern.
|
326
|
+
# @param [#validate, #transform] processor
|
327
|
+
# An optional processor object may be supplied.
|
328
|
+
#
|
329
|
+
# The object should respond to either the <tt>validate</tt> or
|
330
|
+
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
331
|
+
# <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
|
332
|
+
# <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
|
333
|
+
# or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
|
334
|
+
# <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
|
335
|
+
# exception will be raised if the value is invalid. The <tt>transform</tt>
|
336
|
+
# method should return the transformed variable value as a <tt>String</tt>.
|
337
|
+
# If a <tt>transform</tt> method is used, the value will not be percent
|
338
|
+
# encoded automatically. Unicode normalization will be performed both
|
339
|
+
# before and after sending the value to the transform method.
|
340
|
+
#
|
341
|
+
# @return [Addressable::Template] The partially expanded URI template.
|
342
|
+
#
|
343
|
+
# @example
|
344
|
+
# Addressable::Template.new(
|
345
|
+
# "http://example.com/{one}/{two}/"
|
346
|
+
# ).partial_expand({"one" => "1"}).pattern
|
347
|
+
# #=> "http://example.com/1/{two}/"
|
348
|
+
#
|
349
|
+
# Addressable::Template.new(
|
350
|
+
# "http://example.com/search/{-list|+|query}/"
|
351
|
+
# ).partial_expand(
|
352
|
+
# {"query" => "an example search query".split(" ")}
|
353
|
+
# ).pattern
|
354
|
+
# #=> "http://example.com/search/an+example+search+query/"
|
355
|
+
#
|
356
|
+
# Addressable::Template.new(
|
357
|
+
# "http://example.com/{-join|&|one,two}/"
|
358
|
+
# ).partial_expand({"one" => "1"}).pattern
|
359
|
+
# #=> "http://example.com/?one=1{-prefix|&two=|two}"
|
360
|
+
#
|
361
|
+
# Addressable::Template.new(
|
362
|
+
# "http://example.com/{-join|&|one,two,three}/"
|
363
|
+
# ).partial_expand({"one" => "1", "three" => 3}).pattern
|
364
|
+
# #=> "http://example.com/?one=1{-prefix|&two=|two}&three=3"
|
365
|
+
def partial_expand(mapping, processor=nil)
|
366
|
+
result = self.pattern.dup
|
367
|
+
transformed_mapping = transform_mapping(mapping, processor)
|
368
|
+
result.gsub!(
|
369
|
+
/#{OPERATOR_EXPANSION}|#{VARIABLE_EXPANSION}/
|
370
|
+
) do |capture|
|
371
|
+
if capture =~ OPERATOR_EXPANSION
|
372
|
+
operator, argument, variables, default_mapping =
|
373
|
+
parse_template_expansion(capture, transformed_mapping)
|
374
|
+
expand_method = "expand_#{operator}_operator"
|
375
|
+
if ([expand_method, expand_method.to_sym] & private_methods).empty?
|
376
|
+
raise InvalidTemplateOperatorError,
|
377
|
+
"Invalid template operator: #{operator}"
|
378
|
+
else
|
379
|
+
send(
|
380
|
+
expand_method.to_sym, argument, variables,
|
381
|
+
default_mapping, true
|
382
|
+
)
|
383
|
+
end
|
384
|
+
else
|
385
|
+
varname, _, vardefault = capture.scan(/^\{(.+?)(=(.*))?\}$/)[0]
|
386
|
+
if transformed_mapping[varname]
|
387
|
+
transformed_mapping[varname]
|
388
|
+
elsif vardefault
|
389
|
+
"{#{varname}=#{vardefault}}"
|
390
|
+
else
|
391
|
+
"{#{varname}}"
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
return Addressable::Template.new(result)
|
396
|
+
end
|
397
|
+
|
398
|
+
##
|
399
|
+
# Expands a URI template into a full URI.
|
400
|
+
#
|
401
|
+
# @param [Hash] mapping The mapping that corresponds to the pattern.
|
402
|
+
# @param [#validate, #transform] processor
|
403
|
+
# An optional processor object may be supplied.
|
404
|
+
#
|
405
|
+
# The object should respond to either the <tt>validate</tt> or
|
406
|
+
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
407
|
+
# <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
|
408
|
+
# <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
|
409
|
+
# or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
|
410
|
+
# <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
|
411
|
+
# exception will be raised if the value is invalid. The <tt>transform</tt>
|
412
|
+
# method should return the transformed variable value as a <tt>String</tt>.
|
413
|
+
# If a <tt>transform</tt> method is used, the value will not be percent
|
414
|
+
# encoded automatically. Unicode normalization will be performed both
|
415
|
+
# before and after sending the value to the transform method.
|
416
|
+
#
|
417
|
+
# @return [Addressable::URI] The expanded URI template.
|
418
|
+
#
|
419
|
+
# @example
|
420
|
+
# class ExampleProcessor
|
421
|
+
# def self.validate(name, value)
|
422
|
+
# return !!(value =~ /^[\w ]+$/) if name == "query"
|
423
|
+
# return true
|
424
|
+
# end
|
425
|
+
#
|
426
|
+
# def self.transform(name, value)
|
427
|
+
# return value.gsub(/ /, "+") if name == "query"
|
428
|
+
# return value
|
429
|
+
# end
|
430
|
+
# end
|
431
|
+
#
|
432
|
+
# Addressable::Template.new(
|
433
|
+
# "http://example.com/search/{query}/"
|
434
|
+
# ).expand(
|
435
|
+
# {"query" => "an example search query"},
|
436
|
+
# ExampleProcessor
|
437
|
+
# ).to_str
|
438
|
+
# #=> "http://example.com/search/an+example+search+query/"
|
439
|
+
#
|
440
|
+
# Addressable::Template.new(
|
441
|
+
# "http://example.com/search/{-list|+|query}/"
|
442
|
+
# ).expand(
|
443
|
+
# {"query" => "an example search query".split(" ")}
|
444
|
+
# ).to_str
|
445
|
+
# #=> "http://example.com/search/an+example+search+query/"
|
446
|
+
#
|
447
|
+
# Addressable::Template.new(
|
448
|
+
# "http://example.com/search/{query}/"
|
449
|
+
# ).expand(
|
450
|
+
# {"query" => "bogus!"},
|
451
|
+
# ExampleProcessor
|
452
|
+
# ).to_str
|
453
|
+
# #=> Addressable::Template::InvalidTemplateValueError
|
454
|
+
def expand(mapping, processor=nil)
|
455
|
+
result = self.pattern.dup
|
456
|
+
transformed_mapping = transform_mapping(mapping, processor)
|
457
|
+
result.gsub!(
|
458
|
+
/#{OPERATOR_EXPANSION}|#{VARIABLE_EXPANSION}/
|
459
|
+
) do |capture|
|
460
|
+
if capture =~ OPERATOR_EXPANSION
|
461
|
+
operator, argument, variables, default_mapping =
|
462
|
+
parse_template_expansion(capture, transformed_mapping)
|
463
|
+
expand_method = "expand_#{operator}_operator"
|
464
|
+
if ([expand_method, expand_method.to_sym] & private_methods).empty?
|
465
|
+
raise InvalidTemplateOperatorError,
|
466
|
+
"Invalid template operator: #{operator}"
|
467
|
+
else
|
468
|
+
send(expand_method.to_sym, argument, variables, default_mapping)
|
469
|
+
end
|
470
|
+
else
|
471
|
+
varname, _, vardefault = capture.scan(/^\{(.+?)(=(.*))?\}$/)[0]
|
472
|
+
transformed_mapping[varname] || vardefault
|
473
|
+
end
|
474
|
+
end
|
475
|
+
return Addressable::URI.parse(result)
|
476
|
+
end
|
477
|
+
|
478
|
+
##
|
479
|
+
# Returns an Array of variables used within the template pattern.
|
480
|
+
# The variables are listed in the Array in the order they appear within
|
481
|
+
# the pattern. Multiple occurrences of a variable within a pattern are
|
482
|
+
# not represented in this Array.
|
483
|
+
#
|
484
|
+
# @return [Array] The variables present in the template's pattern.
|
485
|
+
def variables
|
486
|
+
@variables ||= ordered_variable_defaults.map { |var, val| var }.uniq
|
487
|
+
end
|
488
|
+
alias_method :keys, :variables
|
489
|
+
|
490
|
+
##
|
491
|
+
# Returns a mapping of variables to their default values specified
|
492
|
+
# in the template. Variables without defaults are not returned.
|
493
|
+
#
|
494
|
+
# @return [Hash] Mapping of template variables to their defaults
|
495
|
+
def variable_defaults
|
496
|
+
@variable_defaults ||=
|
497
|
+
Hash[*ordered_variable_defaults.reject { |k, v| v.nil? }.flatten]
|
498
|
+
end
|
499
|
+
|
500
|
+
private
|
501
|
+
def ordered_variable_defaults
|
502
|
+
@ordered_variable_defaults ||= (begin
|
503
|
+
expansions, expansion_regexp = parse_template_pattern(pattern)
|
504
|
+
|
505
|
+
expansions.inject([]) do |result, expansion|
|
506
|
+
case expansion
|
507
|
+
when OPERATOR_EXPANSION
|
508
|
+
_, _, variables, mapping = parse_template_expansion(expansion)
|
509
|
+
result.concat variables.map { |var| [var, mapping[var]] }
|
510
|
+
when VARIABLE_EXPANSION
|
511
|
+
result << [$1, $2]
|
512
|
+
end
|
513
|
+
result
|
514
|
+
end
|
515
|
+
end)
|
516
|
+
end
|
517
|
+
|
518
|
+
##
|
519
|
+
# Transforms a mapping so that values can be substituted into the
|
520
|
+
# template.
|
521
|
+
#
|
522
|
+
# @param [Hash] mapping The mapping of variables to values.
|
523
|
+
# @param [#validate, #transform] processor
|
524
|
+
# An optional processor object may be supplied.
|
525
|
+
#
|
526
|
+
# The object should respond to either the <tt>validate</tt> or
|
527
|
+
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
528
|
+
# <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
|
529
|
+
# <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
|
530
|
+
# or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
|
531
|
+
# <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt> exception
|
532
|
+
# will be raised if the value is invalid. The <tt>transform</tt> method
|
533
|
+
# should return the transformed variable value as a <tt>String</tt>. If a
|
534
|
+
# <tt>transform</tt> method is used, the value will not be percent encoded
|
535
|
+
# automatically. Unicode normalization will be performed both before and
|
536
|
+
# after sending the value to the transform method.
|
537
|
+
#
|
538
|
+
# @return [Hash] The transformed mapping.
|
539
|
+
def transform_mapping(mapping, processor=nil)
|
540
|
+
return mapping.inject({}) do |accu, pair|
|
541
|
+
name, value = pair
|
542
|
+
value = value.to_s if Numeric === value || Symbol === value
|
543
|
+
|
544
|
+
unless value.respond_to?(:to_ary) || value.respond_to?(:to_str)
|
545
|
+
raise TypeError,
|
546
|
+
"Can't convert #{value.class} into String or Array."
|
547
|
+
end
|
548
|
+
|
549
|
+
if Symbol === name
|
550
|
+
name = name.to_s
|
551
|
+
elsif name.respond_to?(:to_str)
|
552
|
+
name = name.to_str
|
553
|
+
else
|
554
|
+
raise TypeError,
|
555
|
+
"Can't convert #{name.class} into String."
|
556
|
+
end
|
557
|
+
value = value.respond_to?(:to_ary) ? value.to_ary : value.to_str
|
558
|
+
|
559
|
+
# Handle unicode normalization
|
560
|
+
if value.kind_of?(Array)
|
561
|
+
value.map! { |val| Addressable::IDNA.unicode_normalize_kc(val) }
|
562
|
+
else
|
563
|
+
value = Addressable::IDNA.unicode_normalize_kc(value)
|
564
|
+
end
|
565
|
+
|
566
|
+
if processor == nil || !processor.respond_to?(:transform)
|
567
|
+
# Handle percent escaping
|
568
|
+
if value.kind_of?(Array)
|
569
|
+
transformed_value = value.map do |val|
|
570
|
+
Addressable::URI.encode_component(
|
571
|
+
val, Addressable::URI::CharacterClasses::UNRESERVED)
|
572
|
+
end
|
573
|
+
else
|
574
|
+
transformed_value = Addressable::URI.encode_component(
|
575
|
+
value, Addressable::URI::CharacterClasses::UNRESERVED)
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
# Process, if we've got a processor
|
580
|
+
if processor != nil
|
581
|
+
if processor.respond_to?(:validate)
|
582
|
+
if !processor.validate(name, value)
|
583
|
+
display_value = value.kind_of?(Array) ? value.inspect : value
|
584
|
+
raise InvalidTemplateValueError,
|
585
|
+
"#{name}=#{display_value} is an invalid template value."
|
586
|
+
end
|
587
|
+
end
|
588
|
+
if processor.respond_to?(:transform)
|
589
|
+
transformed_value = processor.transform(name, value)
|
590
|
+
if transformed_value.kind_of?(Array)
|
591
|
+
transformed_value.map! do |val|
|
592
|
+
Addressable::IDNA.unicode_normalize_kc(val)
|
593
|
+
end
|
594
|
+
else
|
595
|
+
transformed_value =
|
596
|
+
Addressable::IDNA.unicode_normalize_kc(transformed_value)
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
accu[name] = transformed_value
|
602
|
+
accu
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
##
|
607
|
+
# Expands a URI Template opt operator.
|
608
|
+
#
|
609
|
+
# @param [String] argument The argument to the operator.
|
610
|
+
# @param [Array] variables The variables the operator is working on.
|
611
|
+
# @param [Hash] mapping The mapping of variables to values.
|
612
|
+
#
|
613
|
+
# @return [String] The expanded result.
|
614
|
+
def expand_opt_operator(argument, variables, mapping, partial=false)
|
615
|
+
variables_present = variables.any? do |variable|
|
616
|
+
mapping[variable] != [] &&
|
617
|
+
mapping[variable]
|
618
|
+
end
|
619
|
+
if partial && !variables_present
|
620
|
+
"{-opt|#{argument}|#{variables.join(",")}}"
|
621
|
+
elsif variables_present
|
622
|
+
argument
|
623
|
+
else
|
624
|
+
""
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
##
|
629
|
+
# Expands a URI Template neg operator.
|
630
|
+
#
|
631
|
+
# @param [String] argument The argument to the operator.
|
632
|
+
# @param [Array] variables The variables the operator is working on.
|
633
|
+
# @param [Hash] mapping The mapping of variables to values.
|
634
|
+
#
|
635
|
+
# @return [String] The expanded result.
|
636
|
+
def expand_neg_operator(argument, variables, mapping, partial=false)
|
637
|
+
variables_present = variables.any? do |variable|
|
638
|
+
mapping[variable] != [] &&
|
639
|
+
mapping[variable]
|
640
|
+
end
|
641
|
+
if partial && !variables_present
|
642
|
+
"{-neg|#{argument}|#{variables.join(",")}}"
|
643
|
+
elsif variables_present
|
644
|
+
""
|
645
|
+
else
|
646
|
+
argument
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
##
|
651
|
+
# Expands a URI Template prefix operator.
|
652
|
+
#
|
653
|
+
# @param [String] argument The argument to the operator.
|
654
|
+
# @param [Array] variables The variables the operator is working on.
|
655
|
+
# @param [Hash] mapping The mapping of variables to values.
|
656
|
+
#
|
657
|
+
# @return [String] The expanded result.
|
658
|
+
def expand_prefix_operator(argument, variables, mapping, partial=false)
|
659
|
+
if variables.size != 1
|
660
|
+
raise InvalidTemplateOperatorError,
|
661
|
+
"Template operator 'prefix' takes exactly one variable."
|
662
|
+
end
|
663
|
+
value = mapping[variables.first]
|
664
|
+
if !partial || value
|
665
|
+
if value.kind_of?(Array)
|
666
|
+
(value.map { |list_value| argument + list_value }).join("")
|
667
|
+
elsif value
|
668
|
+
argument + value.to_s
|
669
|
+
end
|
670
|
+
else
|
671
|
+
"{-prefix|#{argument}|#{variables.first}}"
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
##
|
676
|
+
# Expands a URI Template suffix operator.
|
677
|
+
#
|
678
|
+
# @param [String] argument The argument to the operator.
|
679
|
+
# @param [Array] variables The variables the operator is working on.
|
680
|
+
# @param [Hash] mapping The mapping of variables to values.
|
681
|
+
#
|
682
|
+
# @return [String] The expanded result.
|
683
|
+
def expand_suffix_operator(argument, variables, mapping, partial=false)
|
684
|
+
if variables.size != 1
|
685
|
+
raise InvalidTemplateOperatorError,
|
686
|
+
"Template operator 'suffix' takes exactly one variable."
|
687
|
+
end
|
688
|
+
value = mapping[variables.first]
|
689
|
+
if !partial || value
|
690
|
+
if value.kind_of?(Array)
|
691
|
+
(value.map { |list_value| list_value + argument }).join("")
|
692
|
+
elsif value
|
693
|
+
value.to_s + argument
|
694
|
+
end
|
695
|
+
else
|
696
|
+
"{-suffix|#{argument}|#{variables.first}}"
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
##
|
701
|
+
# Expands a URI Template join operator.
|
702
|
+
#
|
703
|
+
# @param [String] argument The argument to the operator.
|
704
|
+
# @param [Array] variables The variables the operator is working on.
|
705
|
+
# @param [Hash] mapping The mapping of variables to values.
|
706
|
+
#
|
707
|
+
# @return [String] The expanded result.
|
708
|
+
def expand_join_operator(argument, variables, mapping, partial=false)
|
709
|
+
if !partial
|
710
|
+
variable_values = variables.inject([]) do |accu, variable|
|
711
|
+
if !mapping[variable].kind_of?(Array)
|
712
|
+
if mapping[variable]
|
713
|
+
accu << variable + "=" + (mapping[variable])
|
714
|
+
end
|
715
|
+
else
|
716
|
+
raise InvalidTemplateOperatorError,
|
717
|
+
"Template operator 'join' does not accept Array values."
|
718
|
+
end
|
719
|
+
accu
|
720
|
+
end
|
721
|
+
variable_values.join(argument)
|
722
|
+
else
|
723
|
+
buffer = ""
|
724
|
+
state = :suffix
|
725
|
+
variables.each_with_index do |variable, index|
|
726
|
+
if !mapping[variable].kind_of?(Array)
|
727
|
+
if mapping[variable]
|
728
|
+
if buffer.empty? || buffer[-1..-1] == "}"
|
729
|
+
buffer << (variable + "=" + (mapping[variable]))
|
730
|
+
elsif state == :suffix
|
731
|
+
buffer << argument
|
732
|
+
buffer << (variable + "=" + (mapping[variable]))
|
733
|
+
else
|
734
|
+
buffer << (variable + "=" + (mapping[variable]))
|
735
|
+
end
|
736
|
+
else
|
737
|
+
if !buffer.empty? && (buffer[-1..-1] != "}" || state == :prefix)
|
738
|
+
buffer << "{-opt|#{argument}|#{variable}}"
|
739
|
+
state = :prefix
|
740
|
+
end
|
741
|
+
if buffer.empty? && variables.size == 1
|
742
|
+
# Evaluates back to itself
|
743
|
+
buffer << "{-join|#{argument}|#{variable}}"
|
744
|
+
else
|
745
|
+
buffer << "{-prefix|#{variable}=|#{variable}}"
|
746
|
+
end
|
747
|
+
if (index != (variables.size - 1) && state == :suffix)
|
748
|
+
buffer << "{-opt|#{argument}|#{variable}}"
|
749
|
+
elsif index != (variables.size - 1) &&
|
750
|
+
mapping[variables[index + 1]]
|
751
|
+
buffer << argument
|
752
|
+
state = :prefix
|
753
|
+
end
|
754
|
+
end
|
755
|
+
else
|
756
|
+
raise InvalidTemplateOperatorError,
|
757
|
+
"Template operator 'join' does not accept Array values."
|
758
|
+
end
|
759
|
+
end
|
760
|
+
buffer
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
##
|
765
|
+
# Expands a URI Template list operator.
|
766
|
+
#
|
767
|
+
# @param [String] argument The argument to the operator.
|
768
|
+
# @param [Array] variables The variables the operator is working on.
|
769
|
+
# @param [Hash] mapping The mapping of variables to values.
|
770
|
+
#
|
771
|
+
# @return [String] The expanded result.
|
772
|
+
def expand_list_operator(argument, variables, mapping, partial=false)
|
773
|
+
if variables.size != 1
|
774
|
+
raise InvalidTemplateOperatorError,
|
775
|
+
"Template operator 'list' takes exactly one variable."
|
776
|
+
end
|
777
|
+
if !partial || mapping[variables.first]
|
778
|
+
values = mapping[variables.first]
|
779
|
+
if values
|
780
|
+
if values.kind_of?(Array)
|
781
|
+
values.join(argument)
|
782
|
+
else
|
783
|
+
raise InvalidTemplateOperatorError,
|
784
|
+
"Template operator 'list' only accepts Array values."
|
785
|
+
end
|
786
|
+
end
|
787
|
+
else
|
788
|
+
"{-list|#{argument}|#{variables.first}}"
|
789
|
+
end
|
790
|
+
end
|
791
|
+
|
792
|
+
##
|
793
|
+
# Parses a URI template expansion <tt>String</tt>.
|
794
|
+
#
|
795
|
+
# @param [String] expansion The operator <tt>String</tt>.
|
796
|
+
# @param [Hash] mapping An optional mapping to merge defaults into.
|
797
|
+
#
|
798
|
+
# @return [Array]
|
799
|
+
# A tuple of the operator, argument, variables, and mapping.
|
800
|
+
def parse_template_expansion(capture, mapping={})
|
801
|
+
operator, argument, variables = capture[1...-1].split("|", -1)
|
802
|
+
operator.gsub!(/^\-/, "")
|
803
|
+
variables = variables.split(",", -1)
|
804
|
+
mapping = (variables.inject({}) do |accu, var|
|
805
|
+
varname, _, vardefault = var.scan(/^(.+?)(=(.*))?$/)[0]
|
806
|
+
accu[varname] = vardefault
|
807
|
+
accu
|
808
|
+
end).merge(mapping)
|
809
|
+
variables = variables.map { |var| var.gsub(/=.*$/, "") }
|
810
|
+
return operator, argument, variables, mapping
|
811
|
+
end
|
812
|
+
|
813
|
+
##
|
814
|
+
# Generates the <tt>Regexp</tt> that parses a template pattern.
|
815
|
+
#
|
816
|
+
# @param [String] pattern The URI template pattern.
|
817
|
+
# @param [#match] processor The template processor to use.
|
818
|
+
#
|
819
|
+
# @return [Regexp]
|
820
|
+
# A regular expression which may be used to parse a template pattern.
|
821
|
+
def parse_template_pattern(pattern, processor=nil)
|
822
|
+
# Escape the pattern. The two gsubs restore the escaped curly braces
|
823
|
+
# back to their original form. Basically, escape everything that isn't
|
824
|
+
# within an expansion.
|
825
|
+
escaped_pattern = Regexp.escape(
|
826
|
+
pattern
|
827
|
+
).gsub(/\\\{(.*?)\\\}/) do |escaped|
|
828
|
+
escaped.gsub(/\\(.)/, "\\1")
|
829
|
+
end
|
830
|
+
|
831
|
+
expansions = []
|
832
|
+
|
833
|
+
# Create a regular expression that captures the values of the
|
834
|
+
# variables in the URI.
|
835
|
+
regexp_string = escaped_pattern.gsub(
|
836
|
+
/#{OPERATOR_EXPANSION}|#{VARIABLE_EXPANSION}/
|
837
|
+
) do |expansion|
|
838
|
+
expansions << expansion
|
839
|
+
if expansion =~ OPERATOR_EXPANSION
|
840
|
+
capture_group = "(.*)"
|
841
|
+
operator, argument, names, _ =
|
842
|
+
parse_template_expansion(expansion)
|
843
|
+
if processor != nil && processor.respond_to?(:match)
|
844
|
+
# We can only lookup the match values for single variable
|
845
|
+
# operator expansions. Besides, ".*" is usually the only
|
846
|
+
# reasonable value for multivariate operators anyways.
|
847
|
+
if ["prefix", "suffix", "list"].include?(operator)
|
848
|
+
capture_group = "(#{processor.match(names.first)})"
|
849
|
+
end
|
850
|
+
elsif operator == "prefix"
|
851
|
+
capture_group = "(#{Regexp.escape(argument)}.*?)"
|
852
|
+
elsif operator == "suffix"
|
853
|
+
capture_group = "(.*?#{Regexp.escape(argument)})"
|
854
|
+
end
|
855
|
+
capture_group
|
856
|
+
else
|
857
|
+
capture_group = "(.*?)"
|
858
|
+
if processor != nil && processor.respond_to?(:match)
|
859
|
+
name = expansion[/\{([^\}=]+)(=[^\}]+)?\}/, 1]
|
860
|
+
capture_group = "(#{processor.match(name)})"
|
861
|
+
end
|
862
|
+
capture_group
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
866
|
+
# Ensure that the regular expression matches the whole URI.
|
867
|
+
regexp_string = "^#{regexp_string}$"
|
868
|
+
|
869
|
+
return expansions, Regexp.new(regexp_string)
|
870
|
+
end
|
871
|
+
|
872
|
+
##
|
873
|
+
# Extracts a URI Template opt operator.
|
874
|
+
#
|
875
|
+
# @param [String] value The unparsed value to extract from.
|
876
|
+
# @param [#restore] processor The processor object.
|
877
|
+
# @param [String] argument The argument to the operator.
|
878
|
+
# @param [Array] variables The variables the operator is working on.
|
879
|
+
# @param [Hash] mapping The mapping of variables to values.
|
880
|
+
#
|
881
|
+
# @return [String] The extracted result.
|
882
|
+
def extract_opt_operator(
|
883
|
+
value, processor, argument, variables, mapping)
|
884
|
+
if value != "" && value != argument
|
885
|
+
raise TemplateOperatorAbortedError,
|
886
|
+
"Value for template operator 'opt' was unexpected."
|
887
|
+
end
|
888
|
+
end
|
889
|
+
|
890
|
+
##
|
891
|
+
# Extracts a URI Template neg operator.
|
892
|
+
#
|
893
|
+
# @param [String] value The unparsed value to extract from.
|
894
|
+
# @param [#restore] processor The processor object.
|
895
|
+
# @param [String] argument The argument to the operator.
|
896
|
+
# @param [Array] variables The variables the operator is working on.
|
897
|
+
# @param [Hash] mapping The mapping of variables to values.
|
898
|
+
#
|
899
|
+
# @return [String] The extracted result.
|
900
|
+
def extract_neg_operator(
|
901
|
+
value, processor, argument, variables, mapping)
|
902
|
+
if value != "" && value != argument
|
903
|
+
raise TemplateOperatorAbortedError,
|
904
|
+
"Value for template operator 'neg' was unexpected."
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
##
|
909
|
+
# Extracts a URI Template prefix operator.
|
910
|
+
#
|
911
|
+
# @param [String] value The unparsed value to extract from.
|
912
|
+
# @param [#restore] processor The processor object.
|
913
|
+
# @param [String] argument The argument to the operator.
|
914
|
+
# @param [Array] variables The variables the operator is working on.
|
915
|
+
# @param [Hash] mapping The mapping of variables to values.
|
916
|
+
#
|
917
|
+
# @return [String] The extracted result.
|
918
|
+
def extract_prefix_operator(
|
919
|
+
value, processor, argument, variables, mapping)
|
920
|
+
if variables.size != 1
|
921
|
+
raise InvalidTemplateOperatorError,
|
922
|
+
"Template operator 'prefix' takes exactly one variable."
|
923
|
+
end
|
924
|
+
if value[0...argument.size] != argument
|
925
|
+
raise TemplateOperatorAbortedError,
|
926
|
+
"Value for template operator 'prefix' missing expected prefix."
|
927
|
+
end
|
928
|
+
values = value.split(argument, -1)
|
929
|
+
values << "" if value[-argument.size..-1] == argument
|
930
|
+
values.shift if values[0] == ""
|
931
|
+
values.pop if values[-1] == ""
|
932
|
+
|
933
|
+
if processor && processor.respond_to?(:restore)
|
934
|
+
values.map! { |val| processor.restore(variables.first, val) }
|
935
|
+
end
|
936
|
+
values = values.first if values.size == 1
|
937
|
+
if mapping[variables.first] == nil || mapping[variables.first] == values
|
938
|
+
mapping[variables.first] = values
|
939
|
+
else
|
940
|
+
raise TemplateOperatorAbortedError,
|
941
|
+
"Value mismatch for repeated variable."
|
942
|
+
end
|
943
|
+
end
|
944
|
+
|
945
|
+
##
|
946
|
+
# Extracts a URI Template suffix operator.
|
947
|
+
#
|
948
|
+
# @param [String] value The unparsed value to extract from.
|
949
|
+
# @param [#restore] processor The processor object.
|
950
|
+
# @param [String] argument The argument to the operator.
|
951
|
+
# @param [Array] variables The variables the operator is working on.
|
952
|
+
# @param [Hash] mapping The mapping of variables to values.
|
953
|
+
#
|
954
|
+
# @return [String] The extracted result.
|
955
|
+
def extract_suffix_operator(
|
956
|
+
value, processor, argument, variables, mapping)
|
957
|
+
if variables.size != 1
|
958
|
+
raise InvalidTemplateOperatorError,
|
959
|
+
"Template operator 'suffix' takes exactly one variable."
|
960
|
+
end
|
961
|
+
if value[-argument.size..-1] != argument
|
962
|
+
raise TemplateOperatorAbortedError,
|
963
|
+
"Value for template operator 'suffix' missing expected suffix."
|
964
|
+
end
|
965
|
+
values = value.split(argument, -1)
|
966
|
+
values.pop if values[-1] == ""
|
967
|
+
if processor && processor.respond_to?(:restore)
|
968
|
+
values.map! { |val| processor.restore(variables.first, val) }
|
969
|
+
end
|
970
|
+
values = values.first if values.size == 1
|
971
|
+
if mapping[variables.first] == nil || mapping[variables.first] == values
|
972
|
+
mapping[variables.first] = values
|
973
|
+
else
|
974
|
+
raise TemplateOperatorAbortedError,
|
975
|
+
"Value mismatch for repeated variable."
|
976
|
+
end
|
977
|
+
end
|
978
|
+
|
979
|
+
##
|
980
|
+
# Extracts a URI Template join operator.
|
981
|
+
#
|
982
|
+
# @param [String] value The unparsed value to extract from.
|
983
|
+
# @param [#restore] processor The processor object.
|
984
|
+
# @param [String] argument The argument to the operator.
|
985
|
+
# @param [Array] variables The variables the operator is working on.
|
986
|
+
# @param [Hash] mapping The mapping of variables to values.
|
987
|
+
#
|
988
|
+
# @return [String] The extracted result.
|
989
|
+
def extract_join_operator(value, processor, argument, variables, mapping)
|
990
|
+
unparsed_values = value.split(argument)
|
991
|
+
parsed_variables = []
|
992
|
+
for unparsed_value in unparsed_values
|
993
|
+
name = unparsed_value[/^(.+?)=(.+)$/, 1]
|
994
|
+
parsed_variables << name
|
995
|
+
parsed_value = unparsed_value[/^(.+?)=(.+)$/, 2]
|
996
|
+
if processor && processor.respond_to?(:restore)
|
997
|
+
parsed_value = processor.restore(name, parsed_value)
|
998
|
+
end
|
999
|
+
if mapping[name] == nil || mapping[name] == parsed_value
|
1000
|
+
mapping[name] = parsed_value
|
1001
|
+
else
|
1002
|
+
raise TemplateOperatorAbortedError,
|
1003
|
+
"Value mismatch for repeated variable."
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
for variable in variables
|
1007
|
+
if !parsed_variables.include?(variable) && mapping[variable] != nil
|
1008
|
+
raise TemplateOperatorAbortedError,
|
1009
|
+
"Value mismatch for repeated variable."
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
if (parsed_variables & variables) != parsed_variables
|
1013
|
+
raise TemplateOperatorAbortedError,
|
1014
|
+
"Template operator 'join' variable mismatch: " +
|
1015
|
+
"#{parsed_variables.inspect}, #{variables.inspect}"
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
##
|
1020
|
+
# Extracts a URI Template list operator.
|
1021
|
+
#
|
1022
|
+
# @param [String] value The unparsed value to extract from.
|
1023
|
+
# @param [#restore] processor The processor object.
|
1024
|
+
# @param [String] argument The argument to the operator.
|
1025
|
+
# @param [Array] variables The variables the operator is working on.
|
1026
|
+
# @param [Hash] mapping The mapping of variables to values.
|
1027
|
+
#
|
1028
|
+
# @return [String] The extracted result.
|
1029
|
+
def extract_list_operator(value, processor, argument, variables, mapping)
|
1030
|
+
if variables.size != 1
|
1031
|
+
raise InvalidTemplateOperatorError,
|
1032
|
+
"Template operator 'list' takes exactly one variable."
|
1033
|
+
end
|
1034
|
+
values = value.split(argument, -1)
|
1035
|
+
values.pop if values[-1] == ""
|
1036
|
+
if processor && processor.respond_to?(:restore)
|
1037
|
+
values.map! { |val| processor.restore(variables.first, val) }
|
1038
|
+
end
|
1039
|
+
if mapping[variables.first] == nil || mapping[variables.first] == values
|
1040
|
+
mapping[variables.first] = values
|
1041
|
+
else
|
1042
|
+
raise TemplateOperatorAbortedError,
|
1043
|
+
"Value mismatch for repeated variable."
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
end
|