opendal 0.1.6.pre.rc.1
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/.standard.yml +20 -0
- data/.tool-versions +1 -0
- data/.yardopts +1 -0
- data/Cargo.toml +65 -0
- data/DEPENDENCIES.md +9 -0
- data/DEPENDENCIES.rust.tsv +277 -0
- data/Gemfile +35 -0
- data/README.md +159 -0
- data/Rakefile +149 -0
- data/build.rs +22 -0
- data/core/CHANGELOG.md +4929 -0
- data/core/CONTRIBUTING.md +61 -0
- data/core/Cargo.lock +10259 -0
- data/core/Cargo.toml +437 -0
- data/core/DEPENDENCIES.md +3 -0
- data/core/DEPENDENCIES.rust.tsv +185 -0
- data/core/LICENSE +201 -0
- data/core/README.md +228 -0
- data/core/benches/README.md +18 -0
- data/core/benches/ops/README.md +26 -0
- data/core/benches/ops/main.rs +25 -0
- data/core/benches/ops/read.rs +100 -0
- data/core/benches/ops/utils.rs +59 -0
- data/core/benches/ops/write.rs +106 -0
- data/core/benches/types/README.md +9 -0
- data/core/benches/types/buffer.rs +114 -0
- data/core/benches/types/main.rs +23 -0
- data/core/benches/types/tasks.rs +64 -0
- data/core/benches/vs_fs/Cargo.toml +32 -0
- data/core/benches/vs_fs/README.md +35 -0
- data/core/benches/vs_fs/src/main.rs +83 -0
- data/core/benches/vs_s3/Cargo.toml +38 -0
- data/core/benches/vs_s3/README.md +55 -0
- data/core/benches/vs_s3/src/main.rs +123 -0
- data/core/edge/README.md +3 -0
- data/core/edge/file_write_on_full_disk/Cargo.toml +31 -0
- data/core/edge/file_write_on_full_disk/README.md +14 -0
- data/core/edge/file_write_on_full_disk/src/main.rs +43 -0
- data/core/edge/s3_aws_assume_role_with_web_identity/Cargo.toml +30 -0
- data/core/edge/s3_aws_assume_role_with_web_identity/README.md +18 -0
- data/core/edge/s3_aws_assume_role_with_web_identity/src/main.rs +34 -0
- data/core/edge/s3_read_on_wasm/.gitignore +3 -0
- data/core/edge/s3_read_on_wasm/Cargo.toml +38 -0
- data/core/edge/s3_read_on_wasm/README.md +42 -0
- data/core/edge/s3_read_on_wasm/src/lib.rs +60 -0
- data/core/edge/s3_read_on_wasm/webdriver.json +15 -0
- data/core/examples/README.md +23 -0
- data/core/examples/basic/Cargo.toml +29 -0
- data/core/examples/basic/README.md +15 -0
- data/core/examples/basic/src/main.rs +51 -0
- data/core/examples/concurrent-upload/Cargo.toml +29 -0
- data/core/examples/concurrent-upload/README.md +15 -0
- data/core/examples/concurrent-upload/src/main.rs +68 -0
- data/core/examples/multipart-upload/Cargo.toml +29 -0
- data/core/examples/multipart-upload/README.md +15 -0
- data/core/examples/multipart-upload/src/main.rs +56 -0
- data/core/fuzz/.gitignore +5 -0
- data/core/fuzz/Cargo.toml +92 -0
- data/core/fuzz/README.md +68 -0
- data/core/fuzz/fuzz_reader.rs +102 -0
- data/core/fuzz/fuzz_writer.rs +123 -0
- data/core/src/blocking/delete.rs +74 -0
- data/core/src/blocking/list.rs +71 -0
- data/core/src/blocking/mod.rs +33 -0
- data/core/src/blocking/operator.rs +729 -0
- data/core/src/blocking/read/buffer_iterator.rs +66 -0
- data/core/src/blocking/read/mod.rs +27 -0
- data/core/src/blocking/read/reader.rs +124 -0
- data/core/src/blocking/read/std_bytes_iterator.rs +69 -0
- data/core/src/blocking/read/std_reader.rs +95 -0
- data/core/src/blocking/write/mod.rs +22 -0
- data/core/src/blocking/write/std_writer.rs +82 -0
- data/core/src/blocking/write/writer.rs +109 -0
- data/core/src/docs/comparisons/mod.rs +30 -0
- data/core/src/docs/comparisons/vs_object_store.md +183 -0
- data/core/src/docs/concepts.rs +135 -0
- data/core/src/docs/internals/accessor.rs +306 -0
- data/core/src/docs/internals/layer.rs +42 -0
- data/core/src/docs/internals/mod.rs +62 -0
- data/core/src/docs/mod.rs +43 -0
- data/core/src/docs/performance/concurrent_write.md +101 -0
- data/core/src/docs/performance/http_optimization.md +124 -0
- data/core/src/docs/performance/mod.rs +32 -0
- data/core/src/docs/rfcs/0000_example.md +74 -0
- data/core/src/docs/rfcs/0000_foyer_integration.md +111 -0
- data/core/src/docs/rfcs/0041_object_native_api.md +185 -0
- data/core/src/docs/rfcs/0044_error_handle.md +198 -0
- data/core/src/docs/rfcs/0057_auto_region.md +160 -0
- data/core/src/docs/rfcs/0069_object_stream.md +145 -0
- data/core/src/docs/rfcs/0090_limited_reader.md +155 -0
- data/core/src/docs/rfcs/0112_path_normalization.md +79 -0
- data/core/src/docs/rfcs/0191_async_streaming_io.md +328 -0
- data/core/src/docs/rfcs/0203_remove_credential.md +96 -0
- data/core/src/docs/rfcs/0221_create_dir.md +89 -0
- data/core/src/docs/rfcs/0247_retryable_error.md +87 -0
- data/core/src/docs/rfcs/0293_object_id.md +67 -0
- data/core/src/docs/rfcs/0337_dir_entry.md +191 -0
- data/core/src/docs/rfcs/0409_accessor_capabilities.md +67 -0
- data/core/src/docs/rfcs/0413_presign.md +154 -0
- data/core/src/docs/rfcs/0423_command_line_interface.md +268 -0
- data/core/src/docs/rfcs/0429_init_from_iter.md +107 -0
- data/core/src/docs/rfcs/0438_multipart.md +163 -0
- data/core/src/docs/rfcs/0443_gateway.md +73 -0
- data/core/src/docs/rfcs/0501_new_builder.md +111 -0
- data/core/src/docs/rfcs/0554_write_refactor.md +96 -0
- data/core/src/docs/rfcs/0561_list_metadata_reuse.md +210 -0
- data/core/src/docs/rfcs/0599_blocking_api.md +157 -0
- data/core/src/docs/rfcs/0623_redis_service.md +300 -0
- data/core/src/docs/rfcs/0627_split_capabilities.md +89 -0
- data/core/src/docs/rfcs/0661_path_in_accessor.md +126 -0
- data/core/src/docs/rfcs/0793_generic_kv_services.md +209 -0
- data/core/src/docs/rfcs/0926_object_reader.md +93 -0
- data/core/src/docs/rfcs/0977_refactor_error.md +151 -0
- data/core/src/docs/rfcs/1085_object_handler.md +73 -0
- data/core/src/docs/rfcs/1391_object_metadataer.md +110 -0
- data/core/src/docs/rfcs/1398_query_based_metadata.md +125 -0
- data/core/src/docs/rfcs/1420_object_writer.md +147 -0
- data/core/src/docs/rfcs/1477_remove_object_concept.md +159 -0
- data/core/src/docs/rfcs/1735_operation_extension.md +117 -0
- data/core/src/docs/rfcs/2083_writer_sink_api.md +106 -0
- data/core/src/docs/rfcs/2133_append_api.md +88 -0
- data/core/src/docs/rfcs/2299_chain_based_operator_api.md +99 -0
- data/core/src/docs/rfcs/2602_object_versioning.md +138 -0
- data/core/src/docs/rfcs/2758_merge_append_into_write.md +79 -0
- data/core/src/docs/rfcs/2774_lister_api.md +66 -0
- data/core/src/docs/rfcs/2779_list_with_metakey.md +143 -0
- data/core/src/docs/rfcs/2852_native_capability.md +58 -0
- data/core/src/docs/rfcs/2884_merge_range_read_into_read.md +80 -0
- data/core/src/docs/rfcs/3017_remove_write_copy_from.md +94 -0
- data/core/src/docs/rfcs/3197_config.md +237 -0
- data/core/src/docs/rfcs/3232_align_list_api.md +69 -0
- data/core/src/docs/rfcs/3243_list_prefix.md +128 -0
- data/core/src/docs/rfcs/3356_lazy_reader.md +111 -0
- data/core/src/docs/rfcs/3526_list_recursive.md +59 -0
- data/core/src/docs/rfcs/3574_concurrent_stat_in_list.md +80 -0
- data/core/src/docs/rfcs/3734_buffered_reader.md +64 -0
- data/core/src/docs/rfcs/3898_concurrent_writer.md +66 -0
- data/core/src/docs/rfcs/3911_deleter_api.md +165 -0
- data/core/src/docs/rfcs/4382_range_based_read.md +213 -0
- data/core/src/docs/rfcs/4638_executor.md +215 -0
- data/core/src/docs/rfcs/5314_remove_metakey.md +120 -0
- data/core/src/docs/rfcs/5444_operator_from_uri.md +162 -0
- data/core/src/docs/rfcs/5479_context.md +140 -0
- data/core/src/docs/rfcs/5485_conditional_reader.md +112 -0
- data/core/src/docs/rfcs/5495_list_with_deleted.md +81 -0
- data/core/src/docs/rfcs/5556_write_returns_metadata.md +121 -0
- data/core/src/docs/rfcs/5871_read_returns_metadata.md +112 -0
- data/core/src/docs/rfcs/6189_remove_native_blocking.md +106 -0
- data/core/src/docs/rfcs/6209_glob_support.md +132 -0
- data/core/src/docs/rfcs/6213_options_api.md +142 -0
- data/core/src/docs/rfcs/README.md +62 -0
- data/core/src/docs/rfcs/mod.rs +278 -0
- data/core/src/docs/upgrade.md +1556 -0
- data/core/src/layers/async_backtrace.rs +174 -0
- data/core/src/layers/await_tree.rs +202 -0
- data/core/src/layers/capability_check.rs +239 -0
- data/core/src/layers/chaos.rs +170 -0
- data/core/src/layers/complete.rs +385 -0
- data/core/src/layers/concurrent_limit.rs +322 -0
- data/core/src/layers/correctness_check.rs +440 -0
- data/core/src/layers/dtrace.rs +294 -0
- data/core/src/layers/error_context.rs +310 -0
- data/core/src/layers/fastmetrics.rs +525 -0
- data/core/src/layers/fastrace.rs +271 -0
- data/core/src/layers/http_client.rs +206 -0
- data/core/src/layers/immutable_index.rs +408 -0
- data/core/src/layers/logging.rs +842 -0
- data/core/src/layers/metrics.rs +182 -0
- data/core/src/layers/mime_guess.rs +199 -0
- data/core/src/layers/mod.rs +130 -0
- data/core/src/layers/observe/metrics.rs +936 -0
- data/core/src/layers/observe/mod.rs +93 -0
- data/core/src/layers/otelmetrics.rs +496 -0
- data/core/src/layers/oteltrace.rs +203 -0
- data/core/src/layers/prometheus.rs +686 -0
- data/core/src/layers/prometheus_client.rs +519 -0
- data/core/src/layers/retry.rs +933 -0
- data/core/src/layers/throttle.rs +204 -0
- data/core/src/layers/timeout.rs +513 -0
- data/core/src/layers/tracing.rs +349 -0
- data/core/src/layers/type_eraser.rs +91 -0
- data/core/src/lib.rs +204 -0
- data/core/src/raw/accessor.rs +856 -0
- data/core/src/raw/adapters/kv/api.rs +164 -0
- data/core/src/raw/adapters/kv/backend.rs +253 -0
- data/core/src/raw/adapters/kv/mod.rs +31 -0
- data/core/src/raw/adapters/mod.rs +50 -0
- data/core/src/raw/adapters/typed_kv/api.rs +171 -0
- data/core/src/raw/adapters/typed_kv/backend.rs +279 -0
- data/core/src/raw/adapters/typed_kv/mod.rs +29 -0
- data/core/src/raw/atomic_util.rs +57 -0
- data/core/src/raw/azure.rs +570 -0
- data/core/src/raw/chrono_util.rs +109 -0
- data/core/src/raw/enum_utils.rs +201 -0
- data/core/src/raw/futures_util.rs +470 -0
- data/core/src/raw/http_util/body.rs +144 -0
- data/core/src/raw/http_util/bytes_content_range.rs +239 -0
- data/core/src/raw/http_util/bytes_range.rs +260 -0
- data/core/src/raw/http_util/client.rs +276 -0
- data/core/src/raw/http_util/error.rs +68 -0
- data/core/src/raw/http_util/header.rs +356 -0
- data/core/src/raw/http_util/mod.rs +78 -0
- data/core/src/raw/http_util/multipart.rs +1180 -0
- data/core/src/raw/http_util/uri.rs +190 -0
- data/core/src/raw/layer.rs +295 -0
- data/core/src/raw/mod.rs +101 -0
- data/core/src/raw/oio/buf/flex_buf.rs +118 -0
- data/core/src/raw/oio/buf/mod.rs +25 -0
- data/core/src/raw/oio/buf/pooled_buf.rs +126 -0
- data/core/src/raw/oio/buf/queue_buf.rs +117 -0
- data/core/src/raw/oio/delete/api.rs +102 -0
- data/core/src/raw/oio/delete/batch_delete.rs +127 -0
- data/core/src/raw/oio/delete/mod.rs +30 -0
- data/core/src/raw/oio/delete/one_shot_delete.rs +79 -0
- data/core/src/raw/oio/entry.rs +89 -0
- data/core/src/raw/oio/list/api.rs +69 -0
- data/core/src/raw/oio/list/flat_list.rs +137 -0
- data/core/src/raw/oio/list/hierarchy_list.rs +135 -0
- data/core/src/raw/oio/list/mod.rs +35 -0
- data/core/src/raw/oio/list/page_list.rs +105 -0
- data/core/src/raw/oio/list/prefix_list.rs +64 -0
- data/core/src/raw/oio/mod.rs +40 -0
- data/core/src/raw/oio/read/api.rs +119 -0
- data/core/src/raw/oio/read/mod.rs +21 -0
- data/core/src/raw/oio/write/api.rs +103 -0
- data/core/src/raw/oio/write/append_write.rs +111 -0
- data/core/src/raw/oio/write/block_write.rs +405 -0
- data/core/src/raw/oio/write/mod.rs +42 -0
- data/core/src/raw/oio/write/multipart_write.rs +518 -0
- data/core/src/raw/oio/write/one_shot_write.rs +77 -0
- data/core/src/raw/oio/write/position_write.rs +284 -0
- data/core/src/raw/operation.rs +88 -0
- data/core/src/raw/ops.rs +917 -0
- data/core/src/raw/path.rs +451 -0
- data/core/src/raw/path_cache.rs +244 -0
- data/core/src/raw/rps.rs +249 -0
- data/core/src/raw/serde_util.rs +423 -0
- data/core/src/raw/std_io_util.rs +65 -0
- data/core/src/raw/tests/mod.rs +30 -0
- data/core/src/raw/tests/read.rs +116 -0
- data/core/src/raw/tests/utils.rs +80 -0
- data/core/src/raw/tests/write.rs +79 -0
- data/core/src/raw/tokio_util.rs +24 -0
- data/core/src/raw/version.rs +19 -0
- data/core/src/services/aliyun_drive/backend.rs +421 -0
- data/core/src/services/aliyun_drive/config.rs +72 -0
- data/core/src/services/aliyun_drive/core.rs +651 -0
- data/core/src/services/aliyun_drive/delete.rs +51 -0
- data/core/src/services/aliyun_drive/docs.md +61 -0
- data/core/src/services/aliyun_drive/error.rs +56 -0
- data/core/src/services/aliyun_drive/lister.rs +134 -0
- data/core/src/services/aliyun_drive/mod.rs +39 -0
- data/core/src/services/aliyun_drive/writer.rs +114 -0
- data/core/src/services/alluxio/backend.rs +257 -0
- data/core/src/services/alluxio/config.rs +50 -0
- data/core/src/services/alluxio/core.rs +367 -0
- data/core/src/services/alluxio/delete.rs +38 -0
- data/core/src/services/alluxio/docs.md +45 -0
- data/core/src/services/alluxio/error.rs +99 -0
- data/core/src/services/alluxio/lister.rs +73 -0
- data/core/src/services/alluxio/mod.rs +39 -0
- data/core/src/services/alluxio/writer.rs +74 -0
- data/core/src/services/azblob/backend.rs +594 -0
- data/core/src/services/azblob/config.rs +220 -0
- data/core/src/services/azblob/core.rs +937 -0
- data/core/src/services/azblob/delete.rs +108 -0
- data/core/src/services/azblob/docs.md +77 -0
- data/core/src/services/azblob/error.rs +164 -0
- data/core/src/services/azblob/lister.rs +107 -0
- data/core/src/services/azblob/mod.rs +38 -0
- data/core/src/services/azblob/writer.rs +177 -0
- data/core/src/services/azdls/backend.rs +435 -0
- data/core/src/services/azdls/config.rs +89 -0
- data/core/src/services/azdls/core.rs +388 -0
- data/core/src/services/azdls/delete.rs +48 -0
- data/core/src/services/azdls/docs.md +73 -0
- data/core/src/services/azdls/error.rs +107 -0
- data/core/src/services/azdls/lister.rs +165 -0
- data/core/src/services/azdls/mod.rs +38 -0
- data/core/src/services/azdls/writer.rs +129 -0
- data/core/src/services/azfile/backend.rs +373 -0
- data/core/src/services/azfile/config.rs +61 -0
- data/core/src/services/azfile/core.rs +435 -0
- data/core/src/services/azfile/delete.rs +51 -0
- data/core/src/services/azfile/docs.md +65 -0
- data/core/src/services/azfile/error.rs +108 -0
- data/core/src/services/azfile/lister.rs +217 -0
- data/core/src/services/azfile/mod.rs +39 -0
- data/core/src/services/azfile/writer.rs +92 -0
- data/core/src/services/b2/backend.rs +434 -0
- data/core/src/services/b2/config.rs +64 -0
- data/core/src/services/b2/core.rs +742 -0
- data/core/src/services/b2/delete.rs +56 -0
- data/core/src/services/b2/docs.md +54 -0
- data/core/src/services/b2/error.rs +132 -0
- data/core/src/services/b2/lister.rs +110 -0
- data/core/src/services/b2/mod.rs +39 -0
- data/core/src/services/b2/writer.rs +189 -0
- data/core/src/services/cacache/backend.rs +160 -0
- data/core/src/services/cacache/config.rs +28 -0
- data/core/src/services/cacache/core.rs +96 -0
- data/core/src/services/cacache/delete.rs +39 -0
- data/core/src/services/cacache/docs.md +38 -0
- data/core/src/services/cacache/mod.rs +34 -0
- data/core/src/services/cacache/writer.rs +61 -0
- data/core/src/services/cloudflare_kv/backend.rs +513 -0
- data/core/src/services/cloudflare_kv/config.rs +55 -0
- data/core/src/services/cloudflare_kv/core.rs +168 -0
- data/core/src/services/cloudflare_kv/delete.rs +119 -0
- data/core/src/services/cloudflare_kv/docs.md +21 -0
- data/core/src/services/cloudflare_kv/error.rs +79 -0
- data/core/src/services/cloudflare_kv/lister.rs +170 -0
- data/core/src/services/cloudflare_kv/mod.rs +39 -0
- data/core/src/services/cloudflare_kv/model.rs +76 -0
- data/core/src/services/cloudflare_kv/writer.rs +68 -0
- data/core/src/services/compfs/backend.rs +290 -0
- data/core/src/services/compfs/config.rs +30 -0
- data/core/src/services/compfs/core.rs +159 -0
- data/core/src/services/compfs/delete.rs +53 -0
- data/core/src/services/compfs/lister.rs +98 -0
- data/core/src/services/compfs/mod.rs +38 -0
- data/core/src/services/compfs/reader.rs +79 -0
- data/core/src/services/compfs/writer.rs +90 -0
- data/core/src/services/cos/backend.rs +442 -0
- data/core/src/services/cos/config.rs +54 -0
- data/core/src/services/cos/core.rs +761 -0
- data/core/src/services/cos/delete.rs +48 -0
- data/core/src/services/cos/docs.md +55 -0
- data/core/src/services/cos/error.rs +105 -0
- data/core/src/services/cos/lister.rs +237 -0
- data/core/src/services/cos/mod.rs +39 -0
- data/core/src/services/cos/writer.rs +234 -0
- data/core/src/services/d1/backend.rs +330 -0
- data/core/src/services/d1/config.rs +55 -0
- data/core/src/services/d1/docs.md +48 -0
- data/core/src/services/d1/error.rs +79 -0
- data/core/src/services/d1/mod.rs +29 -0
- data/core/src/services/d1/model.rs +125 -0
- data/core/src/services/dashmap/backend.rs +203 -0
- data/core/src/services/dashmap/config.rs +37 -0
- data/core/src/services/dashmap/core.rs +61 -0
- data/core/src/services/dashmap/delete.rs +40 -0
- data/core/src/services/dashmap/docs.md +38 -0
- data/core/src/services/dashmap/lister.rs +63 -0
- data/core/src/services/dashmap/mod.rs +36 -0
- data/core/src/services/dashmap/writer.rs +87 -0
- data/core/src/services/dbfs/backend.rs +258 -0
- data/core/src/services/dbfs/config.rs +48 -0
- data/core/src/services/dbfs/core.rs +191 -0
- data/core/src/services/dbfs/delete.rs +49 -0
- data/core/src/services/dbfs/docs.md +57 -0
- data/core/src/services/dbfs/error.rs +74 -0
- data/core/src/services/dbfs/lister.rs +96 -0
- data/core/src/services/dbfs/mod.rs +38 -0
- data/core/src/services/dbfs/writer.rs +64 -0
- data/core/src/services/dropbox/backend.rs +187 -0
- data/core/src/services/dropbox/builder.rs +222 -0
- data/core/src/services/dropbox/config.rs +47 -0
- data/core/src/services/dropbox/core.rs +496 -0
- data/core/src/services/dropbox/delete.rs +54 -0
- data/core/src/services/dropbox/docs.md +64 -0
- data/core/src/services/dropbox/error.rs +85 -0
- data/core/src/services/dropbox/lister.rs +117 -0
- data/core/src/services/dropbox/mod.rs +40 -0
- data/core/src/services/dropbox/writer.rs +51 -0
- data/core/src/services/etcd/backend.rs +345 -0
- data/core/src/services/etcd/config.rs +86 -0
- data/core/src/services/etcd/core.rs +143 -0
- data/core/src/services/etcd/deleter.rs +41 -0
- data/core/src/services/etcd/docs.md +45 -0
- data/core/src/services/etcd/error.rs +26 -0
- data/core/src/services/etcd/lister.rs +79 -0
- data/core/src/services/etcd/mod.rs +36 -0
- data/core/src/services/etcd/writer.rs +61 -0
- data/core/src/services/foundationdb/backend.rs +171 -0
- data/core/src/services/foundationdb/config.rs +45 -0
- data/core/src/services/foundationdb/docs.md +42 -0
- data/core/src/services/foundationdb/mod.rs +24 -0
- data/core/src/services/fs/backend.rs +299 -0
- data/core/src/services/fs/config.rs +33 -0
- data/core/src/services/fs/core.rs +227 -0
- data/core/src/services/fs/delete.rs +53 -0
- data/core/src/services/fs/docs.md +49 -0
- data/core/src/services/fs/error.rs +31 -0
- data/core/src/services/fs/lister.rs +81 -0
- data/core/src/services/fs/mod.rs +40 -0
- data/core/src/services/fs/reader.rs +83 -0
- data/core/src/services/fs/writer.rs +212 -0
- data/core/src/services/ftp/backend.rs +388 -0
- data/core/src/services/ftp/config.rs +46 -0
- data/core/src/services/ftp/core.rs +136 -0
- data/core/src/services/ftp/delete.rs +62 -0
- data/core/src/services/ftp/docs.md +42 -0
- data/core/src/services/ftp/err.rs +47 -0
- data/core/src/services/ftp/lister.rs +72 -0
- data/core/src/services/ftp/mod.rs +41 -0
- data/core/src/services/ftp/reader.rs +84 -0
- data/core/src/services/ftp/writer.rs +122 -0
- data/core/src/services/gcs/backend.rs +499 -0
- data/core/src/services/gcs/config.rs +168 -0
- data/core/src/services/gcs/core.rs +1079 -0
- data/core/src/services/gcs/delete.rs +98 -0
- data/core/src/services/gcs/docs.md +76 -0
- data/core/src/services/gcs/error.rs +122 -0
- data/core/src/services/gcs/lister.rs +136 -0
- data/core/src/services/gcs/mod.rs +40 -0
- data/core/src/services/gcs/uri.rs +75 -0
- data/core/src/services/gcs/writer.rs +163 -0
- data/core/src/services/gdrive/backend.rs +176 -0
- data/core/src/services/gdrive/builder.rs +228 -0
- data/core/src/services/gdrive/config.rs +47 -0
- data/core/src/services/gdrive/core.rs +499 -0
- data/core/src/services/gdrive/delete.rs +57 -0
- data/core/src/services/gdrive/docs.md +65 -0
- data/core/src/services/gdrive/error.rs +80 -0
- data/core/src/services/gdrive/lister.rs +110 -0
- data/core/src/services/gdrive/mod.rs +40 -0
- data/core/src/services/gdrive/writer.rs +77 -0
- data/core/src/services/ghac/backend.rs +285 -0
- data/core/src/services/ghac/config.rs +36 -0
- data/core/src/services/ghac/core.rs +459 -0
- data/core/src/services/ghac/docs.md +84 -0
- data/core/src/services/ghac/error.rs +52 -0
- data/core/src/services/ghac/mod.rs +35 -0
- data/core/src/services/ghac/writer.rs +201 -0
- data/core/src/services/github/backend.rs +285 -0
- data/core/src/services/github/config.rs +59 -0
- data/core/src/services/github/core.rs +351 -0
- data/core/src/services/github/delete.rs +41 -0
- data/core/src/services/github/docs.md +52 -0
- data/core/src/services/github/error.rs +101 -0
- data/core/src/services/github/lister.rs +112 -0
- data/core/src/services/github/mod.rs +38 -0
- data/core/src/services/github/writer.rs +51 -0
- data/core/src/services/gridfs/backend.rs +166 -0
- data/core/src/services/gridfs/config.rs +50 -0
- data/core/src/services/gridfs/core.rs +154 -0
- data/core/src/services/gridfs/docs.md +46 -0
- data/core/src/services/gridfs/mod.rs +26 -0
- data/core/src/services/hdfs/backend.rs +413 -0
- data/core/src/services/hdfs/config.rs +59 -0
- data/core/src/services/hdfs/delete.rs +62 -0
- data/core/src/services/hdfs/docs.md +140 -0
- data/core/src/services/hdfs/lister.rs +70 -0
- data/core/src/services/hdfs/mod.rs +36 -0
- data/core/src/services/hdfs/reader.rs +79 -0
- data/core/src/services/hdfs/writer.rs +104 -0
- data/core/src/services/hdfs_native/backend.rs +340 -0
- data/core/src/services/hdfs_native/config.rs +45 -0
- data/core/src/services/hdfs_native/delete.rs +47 -0
- data/core/src/services/hdfs_native/docs.md +35 -0
- data/core/src/services/hdfs_native/error.rs +59 -0
- data/core/src/services/hdfs_native/lister.rs +85 -0
- data/core/src/services/hdfs_native/mod.rs +39 -0
- data/core/src/services/hdfs_native/reader.rs +62 -0
- data/core/src/services/hdfs_native/writer.rs +61 -0
- data/core/src/services/http/backend.rs +291 -0
- data/core/src/services/http/config.rs +49 -0
- data/core/src/services/http/core.rs +125 -0
- data/core/src/services/http/docs.md +45 -0
- data/core/src/services/http/error.rs +53 -0
- data/core/src/services/http/mod.rs +32 -0
- data/core/src/services/huggingface/backend.rs +289 -0
- data/core/src/services/huggingface/config.rs +75 -0
- data/core/src/services/huggingface/core.rs +406 -0
- data/core/src/services/huggingface/docs.md +61 -0
- data/core/src/services/huggingface/error.rs +93 -0
- data/core/src/services/huggingface/lister.rs +91 -0
- data/core/src/services/huggingface/mod.rs +34 -0
- data/core/src/services/ipfs/backend.rs +257 -0
- data/core/src/services/ipfs/config.rs +32 -0
- data/core/src/services/ipfs/core.rs +239 -0
- data/core/src/services/ipfs/docs.md +45 -0
- data/core/src/services/ipfs/error.rs +52 -0
- data/core/src/services/ipfs/ipld.rs +162 -0
- data/core/src/services/ipfs/mod.rs +34 -0
- data/core/src/services/ipmfs/backend.rs +147 -0
- data/core/src/services/ipmfs/builder.rs +166 -0
- data/core/src/services/ipmfs/config.rs +32 -0
- data/core/src/services/ipmfs/core.rs +142 -0
- data/core/src/services/ipmfs/delete.rs +48 -0
- data/core/src/services/ipmfs/docs.md +14 -0
- data/core/src/services/ipmfs/error.rs +83 -0
- data/core/src/services/ipmfs/lister.rs +135 -0
- data/core/src/services/ipmfs/mod.rs +40 -0
- data/core/src/services/ipmfs/writer.rs +49 -0
- data/core/src/services/koofr/backend.rs +361 -0
- data/core/src/services/koofr/config.rs +50 -0
- data/core/src/services/koofr/core.rs +458 -0
- data/core/src/services/koofr/delete.rs +50 -0
- data/core/src/services/koofr/docs.md +51 -0
- data/core/src/services/koofr/error.rs +72 -0
- data/core/src/services/koofr/lister.rs +88 -0
- data/core/src/services/koofr/mod.rs +38 -0
- data/core/src/services/koofr/writer.rs +53 -0
- data/core/src/services/lakefs/backend.rs +309 -0
- data/core/src/services/lakefs/config.rs +81 -0
- data/core/src/services/lakefs/core.rs +261 -0
- data/core/src/services/lakefs/delete.rs +54 -0
- data/core/src/services/lakefs/docs.md +62 -0
- data/core/src/services/lakefs/error.rs +93 -0
- data/core/src/services/lakefs/lister.rs +120 -0
- data/core/src/services/lakefs/mod.rs +38 -0
- data/core/src/services/lakefs/writer.rs +50 -0
- data/core/src/services/memcached/backend.rs +284 -0
- data/core/src/services/memcached/binary.rs +289 -0
- data/core/src/services/memcached/config.rs +43 -0
- data/core/src/services/memcached/docs.md +47 -0
- data/core/src/services/memcached/mod.rs +27 -0
- data/core/src/services/memory/backend.rs +205 -0
- data/core/src/services/memory/config.rs +30 -0
- data/core/src/services/memory/core.rs +80 -0
- data/core/src/services/memory/delete.rs +42 -0
- data/core/src/services/memory/docs.md +36 -0
- data/core/src/services/memory/lister.rs +56 -0
- data/core/src/services/memory/mod.rs +36 -0
- data/core/src/services/memory/writer.rs +85 -0
- data/core/src/services/mini_moka/backend.rs +260 -0
- data/core/src/services/mini_moka/config.rs +56 -0
- data/core/src/services/mini_moka/core.rs +52 -0
- data/core/src/services/mini_moka/delete.rs +42 -0
- data/core/src/services/mini_moka/docs.md +19 -0
- data/core/src/services/mini_moka/lister.rs +68 -0
- data/core/src/services/mini_moka/mod.rs +36 -0
- data/core/src/services/mini_moka/writer.rs +84 -0
- data/core/src/services/mod.rs +206 -0
- data/core/src/services/moka/backend.rs +326 -0
- data/core/src/services/moka/config.rs +59 -0
- data/core/src/services/moka/core.rs +62 -0
- data/core/src/services/moka/delete.rs +42 -0
- data/core/src/services/moka/docs.md +42 -0
- data/core/src/services/moka/lister.rs +65 -0
- data/core/src/services/moka/mod.rs +41 -0
- data/core/src/services/moka/writer.rs +83 -0
- data/core/src/services/mongodb/backend.rs +291 -0
- data/core/src/services/mongodb/config.rs +54 -0
- data/core/src/services/mongodb/docs.md +49 -0
- data/core/src/services/mongodb/mod.rs +24 -0
- data/core/src/services/monoiofs/backend.rs +238 -0
- data/core/src/services/monoiofs/config.rs +34 -0
- data/core/src/services/monoiofs/core.rs +313 -0
- data/core/src/services/monoiofs/delete.rs +64 -0
- data/core/src/services/monoiofs/docs.md +46 -0
- data/core/src/services/monoiofs/mod.rs +36 -0
- data/core/src/services/monoiofs/reader.rs +147 -0
- data/core/src/services/monoiofs/writer.rs +189 -0
- data/core/src/services/mysql/backend.rs +256 -0
- data/core/src/services/mysql/config.rs +66 -0
- data/core/src/services/mysql/docs.md +47 -0
- data/core/src/services/mysql/mod.rs +24 -0
- data/core/src/services/obs/backend.rs +442 -0
- data/core/src/services/obs/config.rs +53 -0
- data/core/src/services/obs/core.rs +608 -0
- data/core/src/services/obs/delete.rs +48 -0
- data/core/src/services/obs/docs.md +54 -0
- data/core/src/services/obs/error.rs +106 -0
- data/core/src/services/obs/lister.rs +101 -0
- data/core/src/services/obs/mod.rs +38 -0
- data/core/src/services/obs/writer.rs +235 -0
- data/core/src/services/onedrive/backend.rs +127 -0
- data/core/src/services/onedrive/builder.rs +236 -0
- data/core/src/services/onedrive/config.rs +49 -0
- data/core/src/services/onedrive/core.rs +691 -0
- data/core/src/services/onedrive/delete.rs +47 -0
- data/core/src/services/onedrive/docs.md +115 -0
- data/core/src/services/onedrive/error.rs +61 -0
- data/core/src/services/onedrive/graph_model.rs +425 -0
- data/core/src/services/onedrive/lister.rs +150 -0
- data/core/src/services/onedrive/mod.rs +42 -0
- data/core/src/services/onedrive/writer.rs +168 -0
- data/core/src/services/opfs/backend.rs +50 -0
- data/core/src/services/opfs/config.rs +25 -0
- data/core/src/services/opfs/core.rs +74 -0
- data/core/src/services/opfs/docs.md +18 -0
- data/core/src/services/opfs/error.rs +27 -0
- data/core/src/services/opfs/mod.rs +30 -0
- data/core/src/services/opfs/utils.rs +70 -0
- data/core/src/services/oss/backend.rs +734 -0
- data/core/src/services/oss/config.rs +113 -0
- data/core/src/services/oss/core.rs +1088 -0
- data/core/src/services/oss/delete.rs +109 -0
- data/core/src/services/oss/docs.md +74 -0
- data/core/src/services/oss/error.rs +109 -0
- data/core/src/services/oss/lister.rs +256 -0
- data/core/src/services/oss/mod.rs +38 -0
- data/core/src/services/oss/writer.rs +228 -0
- data/core/src/services/pcloud/backend.rs +358 -0
- data/core/src/services/pcloud/config.rs +51 -0
- data/core/src/services/pcloud/core.rs +461 -0
- data/core/src/services/pcloud/delete.rs +66 -0
- data/core/src/services/pcloud/docs.md +51 -0
- data/core/src/services/pcloud/error.rs +88 -0
- data/core/src/services/pcloud/lister.rs +95 -0
- data/core/src/services/pcloud/mod.rs +38 -0
- data/core/src/services/pcloud/writer.rs +66 -0
- data/core/src/services/persy/backend.rs +226 -0
- data/core/src/services/persy/config.rs +32 -0
- data/core/src/services/persy/docs.md +43 -0
- data/core/src/services/persy/mod.rs +24 -0
- data/core/src/services/postgresql/backend.rs +258 -0
- data/core/src/services/postgresql/config.rs +66 -0
- data/core/src/services/postgresql/docs.md +47 -0
- data/core/src/services/postgresql/mod.rs +24 -0
- data/core/src/services/redb/backend.rs +280 -0
- data/core/src/services/redb/config.rs +34 -0
- data/core/src/services/redb/docs.md +41 -0
- data/core/src/services/redb/mod.rs +24 -0
- data/core/src/services/redis/backend.rs +442 -0
- data/core/src/services/redis/config.rs +79 -0
- data/core/src/services/redis/core.rs +209 -0
- data/core/src/services/redis/delete.rs +40 -0
- data/core/src/services/redis/docs.md +43 -0
- data/core/src/services/redis/mod.rs +34 -0
- data/core/src/services/redis/writer.rs +57 -0
- data/core/src/services/rocksdb/backend.rs +159 -0
- data/core/src/services/rocksdb/config.rs +34 -0
- data/core/src/services/rocksdb/docs.md +54 -0
- data/core/src/services/rocksdb/mod.rs +24 -0
- data/core/src/services/s3/backend.rs +1293 -0
- data/core/src/services/s3/compatible_services.md +126 -0
- data/core/src/services/s3/config.rs +327 -0
- data/core/src/services/s3/core.rs +1741 -0
- data/core/src/services/s3/delete.rs +109 -0
- data/core/src/services/s3/docs.md +244 -0
- data/core/src/services/s3/error.rs +171 -0
- data/core/src/services/s3/lister.rs +405 -0
- data/core/src/services/s3/mod.rs +38 -0
- data/core/src/services/s3/writer.rs +262 -0
- data/core/src/services/seafile/backend.rs +297 -0
- data/core/src/services/seafile/config.rs +56 -0
- data/core/src/services/seafile/core.rs +475 -0
- data/core/src/services/seafile/delete.rs +40 -0
- data/core/src/services/seafile/docs.md +54 -0
- data/core/src/services/seafile/error.rs +86 -0
- data/core/src/services/seafile/lister.rs +83 -0
- data/core/src/services/seafile/mod.rs +38 -0
- data/core/src/services/seafile/writer.rs +55 -0
- data/core/src/services/sftp/backend.rs +397 -0
- data/core/src/services/sftp/config.rs +50 -0
- data/core/src/services/sftp/core.rs +154 -0
- data/core/src/services/sftp/delete.rs +55 -0
- data/core/src/services/sftp/docs.md +49 -0
- data/core/src/services/sftp/error.rs +57 -0
- data/core/src/services/sftp/lister.rs +88 -0
- data/core/src/services/sftp/mod.rs +42 -0
- data/core/src/services/sftp/reader.rs +78 -0
- data/core/src/services/sftp/utils.rs +51 -0
- data/core/src/services/sftp/writer.rs +67 -0
- data/core/src/services/sled/backend.rs +194 -0
- data/core/src/services/sled/config.rs +45 -0
- data/core/src/services/sled/docs.md +39 -0
- data/core/src/services/sled/mod.rs +24 -0
- data/core/src/services/sqlite/backend.rs +326 -0
- data/core/src/services/sqlite/config.rs +70 -0
- data/core/src/services/sqlite/docs.md +46 -0
- data/core/src/services/sqlite/mod.rs +24 -0
- data/core/src/services/surrealdb/backend.rs +365 -0
- data/core/src/services/surrealdb/config.rs +64 -0
- data/core/src/services/surrealdb/docs.md +54 -0
- data/core/src/services/surrealdb/mod.rs +24 -0
- data/core/src/services/swift/backend.rs +275 -0
- data/core/src/services/swift/compatible_services.md +53 -0
- data/core/src/services/swift/config.rs +53 -0
- data/core/src/services/swift/core.rs +310 -0
- data/core/src/services/swift/delete.rs +49 -0
- data/core/src/services/swift/docs.md +52 -0
- data/core/src/services/swift/error.rs +90 -0
- data/core/src/services/swift/lister.rs +119 -0
- data/core/src/services/swift/mod.rs +38 -0
- data/core/src/services/swift/writer.rs +53 -0
- data/core/src/services/tikv/backend.rs +237 -0
- data/core/src/services/tikv/config.rs +52 -0
- data/core/src/services/tikv/docs.md +43 -0
- data/core/src/services/tikv/mod.rs +24 -0
- data/core/src/services/upyun/backend.rs +317 -0
- data/core/src/services/upyun/config.rs +51 -0
- data/core/src/services/upyun/core.rs +521 -0
- data/core/src/services/upyun/delete.rs +50 -0
- data/core/src/services/upyun/docs.md +51 -0
- data/core/src/services/upyun/error.rs +97 -0
- data/core/src/services/upyun/lister.rs +101 -0
- data/core/src/services/upyun/mod.rs +38 -0
- data/core/src/services/upyun/writer.rs +127 -0
- data/core/src/services/vercel_artifacts/backend.rs +99 -0
- data/core/src/services/vercel_artifacts/builder.rs +117 -0
- data/core/src/services/vercel_artifacts/config.rs +39 -0
- data/core/src/services/vercel_artifacts/core.rs +112 -0
- data/core/src/services/vercel_artifacts/docs.md +40 -0
- data/core/src/services/vercel_artifacts/error.rs +50 -0
- data/core/src/services/vercel_artifacts/mod.rs +36 -0
- data/core/src/services/vercel_artifacts/writer.rs +58 -0
- data/core/src/services/vercel_blob/backend.rs +251 -0
- data/core/src/services/vercel_blob/config.rs +45 -0
- data/core/src/services/vercel_blob/core.rs +449 -0
- data/core/src/services/vercel_blob/delete.rs +38 -0
- data/core/src/services/vercel_blob/docs.md +45 -0
- data/core/src/services/vercel_blob/error.rs +110 -0
- data/core/src/services/vercel_blob/lister.rs +69 -0
- data/core/src/services/vercel_blob/mod.rs +38 -0
- data/core/src/services/vercel_blob/writer.rs +143 -0
- data/core/src/services/webdav/backend.rs +318 -0
- data/core/src/services/webdav/config.rs +53 -0
- data/core/src/services/webdav/core.rs +859 -0
- data/core/src/services/webdav/delete.rs +47 -0
- data/core/src/services/webdav/docs.md +49 -0
- data/core/src/services/webdav/error.rs +53 -0
- data/core/src/services/webdav/lister.rs +106 -0
- data/core/src/services/webdav/mod.rs +38 -0
- data/core/src/services/webdav/writer.rs +56 -0
- data/core/src/services/webhdfs/backend.rs +376 -0
- data/core/src/services/webhdfs/config.rs +52 -0
- data/core/src/services/webhdfs/core.rs +398 -0
- data/core/src/services/webhdfs/delete.rs +46 -0
- data/core/src/services/webhdfs/docs.md +90 -0
- data/core/src/services/webhdfs/error.rs +126 -0
- data/core/src/services/webhdfs/lister.rs +130 -0
- data/core/src/services/webhdfs/message.rs +249 -0
- data/core/src/services/webhdfs/mod.rs +41 -0
- data/core/src/services/webhdfs/writer.rs +177 -0
- data/core/src/services/yandex_disk/backend.rs +267 -0
- data/core/src/services/yandex_disk/config.rs +45 -0
- data/core/src/services/yandex_disk/core.rs +340 -0
- data/core/src/services/yandex_disk/delete.rs +54 -0
- data/core/src/services/yandex_disk/docs.md +45 -0
- data/core/src/services/yandex_disk/error.rs +104 -0
- data/core/src/services/yandex_disk/lister.rs +113 -0
- data/core/src/services/yandex_disk/mod.rs +38 -0
- data/core/src/services/yandex_disk/writer.rs +52 -0
- data/core/src/types/buffer.rs +991 -0
- data/core/src/types/builder.rs +152 -0
- data/core/src/types/capability.rs +209 -0
- data/core/src/types/context/mod.rs +22 -0
- data/core/src/types/context/read.rs +231 -0
- data/core/src/types/context/write.rs +441 -0
- data/core/src/types/delete/deleter.rs +220 -0
- data/core/src/types/delete/futures_delete_sink.rs +176 -0
- data/core/src/types/delete/input.rs +97 -0
- data/core/src/types/delete/mod.rs +26 -0
- data/core/src/types/entry.rs +69 -0
- data/core/src/types/error.rs +570 -0
- data/core/src/types/execute/api.rs +110 -0
- data/core/src/types/execute/executor.rs +96 -0
- data/core/src/types/execute/executors/mod.rs +27 -0
- data/core/src/types/execute/executors/tokio_executor.rs +60 -0
- data/core/src/types/execute/mod.rs +25 -0
- data/core/src/types/list.rs +137 -0
- data/core/src/types/metadata.rs +436 -0
- data/core/src/types/mod.rs +72 -0
- data/core/src/types/mode.rs +68 -0
- data/core/src/types/operator/builder.rs +535 -0
- data/core/src/types/operator/info.rs +63 -0
- data/core/src/types/operator/mod.rs +33 -0
- data/core/src/types/operator/operator.rs +2236 -0
- data/core/src/types/operator/operator_futures.rs +1430 -0
- data/core/src/types/operator/registry.rs +129 -0
- data/core/src/types/options.rs +548 -0
- data/core/src/types/read/buffer_stream.rs +273 -0
- data/core/src/types/read/futures_async_reader.rs +289 -0
- data/core/src/types/read/futures_bytes_stream.rs +157 -0
- data/core/src/types/read/mod.rs +29 -0
- data/core/src/types/read/reader.rs +604 -0
- data/core/src/types/scheme.rs +475 -0
- data/core/src/types/write/buffer_sink.rs +188 -0
- data/core/src/types/write/futures_async_writer.rs +136 -0
- data/core/src/types/write/futures_bytes_sink.rs +103 -0
- data/core/src/types/write/mod.rs +26 -0
- data/core/src/types/write/writer.rs +411 -0
- data/core/tests/behavior/README.md +77 -0
- data/core/tests/behavior/async_copy.rs +314 -0
- data/core/tests/behavior/async_create_dir.rs +53 -0
- data/core/tests/behavior/async_delete.rs +354 -0
- data/core/tests/behavior/async_list.rs +739 -0
- data/core/tests/behavior/async_presign.rs +175 -0
- data/core/tests/behavior/async_read.rs +871 -0
- data/core/tests/behavior/async_rename.rs +210 -0
- data/core/tests/behavior/async_stat.rs +628 -0
- data/core/tests/behavior/async_write.rs +819 -0
- data/core/tests/behavior/main.rs +78 -0
- data/core/tests/behavior/utils.rs +187 -0
- data/core/tests/data/normal_dir/.gitkeep +0 -0
- data/core/tests/data/normal_file.txt +1041 -0
- data/core/tests/data/special_dir !@#$%^&()_+-=;',/.gitkeep +0 -0
- data/core/tests/data/special_file !@#$%^&()_+-=;',.txt +1041 -0
- data/core/users.md +13 -0
- data/extconf.rb +24 -0
- data/lib/opendal.rb +25 -0
- data/lib/opendal_ruby/entry.rb +35 -0
- data/lib/opendal_ruby/io.rb +70 -0
- data/lib/opendal_ruby/metadata.rb +44 -0
- data/lib/opendal_ruby/operator.rb +29 -0
- data/lib/opendal_ruby/operator_info.rb +26 -0
- data/src/capability.rs +146 -0
- data/src/io.rs +464 -0
- data/src/lib.rs +63 -0
- data/src/lister.rs +141 -0
- data/src/metadata.rs +111 -0
- data/src/middlewares.rs +174 -0
- data/src/operator.rs +310 -0
- data/src/operator_info.rs +83 -0
- data/test/blocking_op_test.rb +112 -0
- data/test/capability_test.rb +42 -0
- data/test/io_test.rb +172 -0
- data/test/lister_test.rb +77 -0
- data/test/metadata_test.rb +78 -0
- data/test/middlewares_test.rb +46 -0
- data/test/operator_info_test.rb +35 -0
- data/test/test_helper.rb +36 -0
- metadata +857 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
// Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. 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,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
use std::convert::Infallible;
|
|
19
|
+
use std::fmt::Debug;
|
|
20
|
+
use std::fmt::Formatter;
|
|
21
|
+
use std::future;
|
|
22
|
+
use std::mem;
|
|
23
|
+
use std::ops::Deref;
|
|
24
|
+
use std::pin::Pin;
|
|
25
|
+
use std::str::FromStr;
|
|
26
|
+
use std::sync::Arc;
|
|
27
|
+
use std::sync::LazyLock;
|
|
28
|
+
use std::task::Context;
|
|
29
|
+
use std::task::Poll;
|
|
30
|
+
|
|
31
|
+
use bytes::Bytes;
|
|
32
|
+
use futures::Future;
|
|
33
|
+
use futures::TryStreamExt;
|
|
34
|
+
use http::Request;
|
|
35
|
+
use http::Response;
|
|
36
|
+
use http_body::Frame;
|
|
37
|
+
use http_body::SizeHint;
|
|
38
|
+
use raw::oio::Read;
|
|
39
|
+
|
|
40
|
+
use super::parse_content_encoding;
|
|
41
|
+
use super::parse_content_length;
|
|
42
|
+
use super::HttpBody;
|
|
43
|
+
use crate::raw::*;
|
|
44
|
+
use crate::*;
|
|
45
|
+
|
|
46
|
+
/// Http client used across opendal for loading credentials.
|
|
47
|
+
/// This is merely a temporary solution because reqsign requires a reqwest client to be passed.
|
|
48
|
+
/// We will remove it after the next major version of reqsign, which will enable users to provide their own client.
|
|
49
|
+
#[allow(dead_code)]
|
|
50
|
+
pub(crate) static GLOBAL_REQWEST_CLIENT: LazyLock<reqwest::Client> =
|
|
51
|
+
LazyLock::new(reqwest::Client::new);
|
|
52
|
+
|
|
53
|
+
/// HttpFetcher is a type erased [`HttpFetch`].
|
|
54
|
+
pub type HttpFetcher = Arc<dyn HttpFetchDyn>;
|
|
55
|
+
|
|
56
|
+
/// A HTTP client instance for OpenDAL's services.
|
|
57
|
+
///
|
|
58
|
+
/// # Notes
|
|
59
|
+
///
|
|
60
|
+
/// * A http client must support redirections that follows 3xx response.
|
|
61
|
+
#[derive(Clone)]
|
|
62
|
+
pub struct HttpClient {
|
|
63
|
+
fetcher: HttpFetcher,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// We don't want users to know details about our clients.
|
|
67
|
+
impl Debug for HttpClient {
|
|
68
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
69
|
+
f.debug_struct("HttpClient").finish()
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
impl Default for HttpClient {
|
|
74
|
+
fn default() -> Self {
|
|
75
|
+
Self {
|
|
76
|
+
fetcher: Arc::new(GLOBAL_REQWEST_CLIENT.clone()),
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
impl HttpClient {
|
|
82
|
+
/// Create a new http client in async context.
|
|
83
|
+
pub fn new() -> Result<Self> {
|
|
84
|
+
Ok(Self::default())
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Construct `Self` with given [`reqwest::Client`]
|
|
88
|
+
pub fn with(client: impl HttpFetch) -> Self {
|
|
89
|
+
let fetcher = Arc::new(client);
|
|
90
|
+
Self { fetcher }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Get the inner http client.
|
|
94
|
+
pub(crate) fn into_inner(self) -> HttpFetcher {
|
|
95
|
+
self.fetcher
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// Build a new http client in async context.
|
|
99
|
+
#[deprecated]
|
|
100
|
+
pub fn build(builder: reqwest::ClientBuilder) -> Result<Self> {
|
|
101
|
+
let client = builder.build().map_err(|err| {
|
|
102
|
+
Error::new(ErrorKind::Unexpected, "http client build failed").set_source(err)
|
|
103
|
+
})?;
|
|
104
|
+
let fetcher = Arc::new(client);
|
|
105
|
+
Ok(Self { fetcher })
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Send a request and consume response.
|
|
109
|
+
pub async fn send(&self, req: Request<Buffer>) -> Result<Response<Buffer>> {
|
|
110
|
+
let (parts, mut body) = self.fetch(req).await?.into_parts();
|
|
111
|
+
let buffer = body.read_all().await?;
|
|
112
|
+
Ok(Response::from_parts(parts, buffer))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// Fetch a request and return a streamable [`HttpBody`].
|
|
116
|
+
///
|
|
117
|
+
/// Services can use [`HttpBody`] as [`Access::Read`].
|
|
118
|
+
pub async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
|
|
119
|
+
self.fetcher.fetch(req).await
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/// HttpFetch is the trait to fetch a request in async way.
|
|
124
|
+
/// User should implement this trait to provide their own http client.
|
|
125
|
+
pub trait HttpFetch: Send + Sync + Unpin + 'static {
|
|
126
|
+
/// Fetch a request in async way.
|
|
127
|
+
fn fetch(
|
|
128
|
+
&self,
|
|
129
|
+
req: Request<Buffer>,
|
|
130
|
+
) -> impl Future<Output = Result<Response<HttpBody>>> + MaybeSend;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// HttpFetchDyn is the dyn version of [`HttpFetch`]
|
|
134
|
+
/// which make it possible to use as `Arc<dyn HttpFetchDyn>`.
|
|
135
|
+
/// User should never implement this trait, but use `HttpFetch` instead.
|
|
136
|
+
pub trait HttpFetchDyn: Send + Sync + Unpin + 'static {
|
|
137
|
+
/// The dyn version of [`HttpFetch::fetch`].
|
|
138
|
+
///
|
|
139
|
+
/// This function returns a boxed future to make it object safe.
|
|
140
|
+
fn fetch_dyn(&self, req: Request<Buffer>) -> BoxedFuture<'_, Result<Response<HttpBody>>>;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
impl<T: HttpFetch + ?Sized> HttpFetchDyn for T {
|
|
144
|
+
fn fetch_dyn(&self, req: Request<Buffer>) -> BoxedFuture<'_, Result<Response<HttpBody>>> {
|
|
145
|
+
Box::pin(self.fetch(req))
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
impl<T: HttpFetchDyn + ?Sized> HttpFetch for Arc<T> {
|
|
150
|
+
async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
|
|
151
|
+
self.deref().fetch_dyn(req).await
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
impl HttpFetch for reqwest::Client {
|
|
156
|
+
async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
|
|
157
|
+
// Uri stores all string alike data in `Bytes` which means
|
|
158
|
+
// the clone here is cheap.
|
|
159
|
+
let uri = req.uri().clone();
|
|
160
|
+
let is_head = req.method() == http::Method::HEAD;
|
|
161
|
+
|
|
162
|
+
let (parts, body) = req.into_parts();
|
|
163
|
+
|
|
164
|
+
let url = reqwest::Url::from_str(&uri.to_string()).map_err(|err| {
|
|
165
|
+
Error::new(ErrorKind::Unexpected, "request url is invalid")
|
|
166
|
+
.with_operation("http_util::Client::send::fetch")
|
|
167
|
+
.with_context("url", uri.to_string())
|
|
168
|
+
.set_source(err)
|
|
169
|
+
})?;
|
|
170
|
+
|
|
171
|
+
let mut req_builder = self.request(parts.method, url).headers(parts.headers);
|
|
172
|
+
|
|
173
|
+
// Client under wasm doesn't support set version.
|
|
174
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
175
|
+
{
|
|
176
|
+
req_builder = req_builder.version(parts.version);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Don't set body if body is empty.
|
|
180
|
+
if !body.is_empty() {
|
|
181
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
182
|
+
{
|
|
183
|
+
req_builder = req_builder.body(reqwest::Body::wrap(HttpBufferBody(body)))
|
|
184
|
+
}
|
|
185
|
+
#[cfg(target_arch = "wasm32")]
|
|
186
|
+
{
|
|
187
|
+
req_builder = req_builder.body(reqwest::Body::from(body.to_bytes()))
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let mut resp = req_builder.send().await.map_err(|err| {
|
|
192
|
+
Error::new(ErrorKind::Unexpected, "send http request")
|
|
193
|
+
.with_operation("http_util::Client::send")
|
|
194
|
+
.with_context("url", uri.to_string())
|
|
195
|
+
.with_temporary(is_temporary_error(&err))
|
|
196
|
+
.set_source(err)
|
|
197
|
+
})?;
|
|
198
|
+
|
|
199
|
+
// Get content length from header so that we can check it.
|
|
200
|
+
//
|
|
201
|
+
// - If the request method is HEAD, we will ignore content length.
|
|
202
|
+
// - If response contains content_encoding, we should omit its content length.
|
|
203
|
+
let content_length = if is_head || parse_content_encoding(resp.headers())?.is_some() {
|
|
204
|
+
None
|
|
205
|
+
} else {
|
|
206
|
+
parse_content_length(resp.headers())?
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
let mut hr = Response::builder()
|
|
210
|
+
.status(resp.status())
|
|
211
|
+
// Insert uri into response extension so that we can fetch
|
|
212
|
+
// it later.
|
|
213
|
+
.extension(uri.clone());
|
|
214
|
+
|
|
215
|
+
// Response builder under wasm doesn't support set version.
|
|
216
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
217
|
+
{
|
|
218
|
+
hr = hr.version(resp.version());
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Swap headers directly instead of copy the entire map.
|
|
222
|
+
mem::swap(hr.headers_mut().unwrap(), resp.headers_mut());
|
|
223
|
+
|
|
224
|
+
let bs = HttpBody::new(
|
|
225
|
+
resp.bytes_stream()
|
|
226
|
+
.try_filter(|v| future::ready(!v.is_empty()))
|
|
227
|
+
.map_ok(Buffer::from)
|
|
228
|
+
.map_err(move |err| {
|
|
229
|
+
Error::new(ErrorKind::Unexpected, "read data from http response")
|
|
230
|
+
.with_operation("http_util::Client::send")
|
|
231
|
+
.with_context("url", uri.to_string())
|
|
232
|
+
.with_temporary(is_temporary_error(&err))
|
|
233
|
+
.set_source(err)
|
|
234
|
+
}),
|
|
235
|
+
content_length,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
let resp = hr.body(bs).expect("response must build succeed");
|
|
239
|
+
Ok(resp)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#[inline]
|
|
244
|
+
fn is_temporary_error(err: &reqwest::Error) -> bool {
|
|
245
|
+
// error sending request
|
|
246
|
+
err.is_request()||
|
|
247
|
+
// request or response body error
|
|
248
|
+
err.is_body() ||
|
|
249
|
+
// error decoding response body, for example, connection reset.
|
|
250
|
+
err.is_decode()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
struct HttpBufferBody(Buffer);
|
|
254
|
+
|
|
255
|
+
impl http_body::Body for HttpBufferBody {
|
|
256
|
+
type Data = Bytes;
|
|
257
|
+
type Error = Infallible;
|
|
258
|
+
|
|
259
|
+
fn poll_frame(
|
|
260
|
+
mut self: Pin<&mut Self>,
|
|
261
|
+
_: &mut Context<'_>,
|
|
262
|
+
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
|
|
263
|
+
match self.0.next() {
|
|
264
|
+
Some(bs) => Poll::Ready(Some(Ok(Frame::data(bs)))),
|
|
265
|
+
None => Poll::Ready(None),
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
fn is_end_stream(&self) -> bool {
|
|
270
|
+
self.0.is_empty()
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
fn size_hint(&self) -> SizeHint {
|
|
274
|
+
SizeHint::with_exact(self.0.len() as u64)
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. 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,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
use http::response::Parts;
|
|
19
|
+
use http::Uri;
|
|
20
|
+
|
|
21
|
+
use crate::Error;
|
|
22
|
+
use crate::ErrorKind;
|
|
23
|
+
|
|
24
|
+
/// Create a new error happened during building request.
|
|
25
|
+
pub fn new_request_build_error(err: http::Error) -> Error {
|
|
26
|
+
Error::new(ErrorKind::Unexpected, "building http request")
|
|
27
|
+
.with_operation("http::Request::build")
|
|
28
|
+
.set_source(err)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Create a new error happened during signing request.
|
|
32
|
+
pub fn new_request_credential_error(err: anyhow::Error) -> Error {
|
|
33
|
+
Error::new(
|
|
34
|
+
ErrorKind::Unexpected,
|
|
35
|
+
"loading credential to sign http request",
|
|
36
|
+
)
|
|
37
|
+
.set_temporary()
|
|
38
|
+
.with_operation("reqsign::LoadCredential")
|
|
39
|
+
.set_source(err)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Create a new error happened during signing request.
|
|
43
|
+
pub fn new_request_sign_error(err: anyhow::Error) -> Error {
|
|
44
|
+
Error::new(ErrorKind::Unexpected, "signing http request")
|
|
45
|
+
.with_operation("reqsign::Sign")
|
|
46
|
+
.set_source(err)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// Add response context to error.
|
|
50
|
+
///
|
|
51
|
+
/// This helper function will:
|
|
52
|
+
///
|
|
53
|
+
/// - remove sensitive or useless headers from parts.
|
|
54
|
+
/// - fetch uri if parts extensions contains `Uri`.
|
|
55
|
+
pub fn with_error_response_context(mut err: Error, mut parts: Parts) -> Error {
|
|
56
|
+
if let Some(uri) = parts.extensions.get::<Uri>() {
|
|
57
|
+
err = err.with_context("uri", uri.to_string());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The following headers may contains sensitive information.
|
|
61
|
+
parts.headers.remove("Set-Cookie");
|
|
62
|
+
parts.headers.remove("WWW-Authenticate");
|
|
63
|
+
parts.headers.remove("Proxy-Authenticate");
|
|
64
|
+
|
|
65
|
+
err = err.with_context("response", format!("{parts:?}"));
|
|
66
|
+
|
|
67
|
+
err
|
|
68
|
+
}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
// Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. 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,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
use std::collections::HashMap;
|
|
19
|
+
|
|
20
|
+
use base64::engine::general_purpose;
|
|
21
|
+
use base64::Engine;
|
|
22
|
+
use chrono::DateTime;
|
|
23
|
+
use chrono::Utc;
|
|
24
|
+
use http::header::CACHE_CONTROL;
|
|
25
|
+
use http::header::CONTENT_DISPOSITION;
|
|
26
|
+
use http::header::CONTENT_ENCODING;
|
|
27
|
+
use http::header::CONTENT_LENGTH;
|
|
28
|
+
use http::header::CONTENT_RANGE;
|
|
29
|
+
use http::header::CONTENT_TYPE;
|
|
30
|
+
use http::header::ETAG;
|
|
31
|
+
use http::header::LAST_MODIFIED;
|
|
32
|
+
use http::header::LOCATION;
|
|
33
|
+
use http::HeaderMap;
|
|
34
|
+
use http::HeaderName;
|
|
35
|
+
use http::HeaderValue;
|
|
36
|
+
use md5::Digest;
|
|
37
|
+
|
|
38
|
+
use crate::raw::*;
|
|
39
|
+
use crate::EntryMode;
|
|
40
|
+
use crate::Error;
|
|
41
|
+
use crate::ErrorKind;
|
|
42
|
+
use crate::Metadata;
|
|
43
|
+
use crate::Result;
|
|
44
|
+
|
|
45
|
+
/// Parse redirect location from header map
|
|
46
|
+
///
|
|
47
|
+
/// # Note
|
|
48
|
+
/// The returned value maybe a relative path, like `/index.html`, `/robots.txt`, etc.
|
|
49
|
+
pub fn parse_location(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
50
|
+
parse_header_to_str(headers, LOCATION)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Parse cache control from header map.
|
|
54
|
+
///
|
|
55
|
+
/// # Note
|
|
56
|
+
///
|
|
57
|
+
/// The returned value is the raw string of `cache-control` header,
|
|
58
|
+
/// maybe `no-cache`, `max-age=3600`, etc.
|
|
59
|
+
pub fn parse_cache_control(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
60
|
+
parse_header_to_str(headers, CACHE_CONTROL)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Parse content length from header map.
|
|
64
|
+
pub fn parse_content_length(headers: &HeaderMap) -> Result<Option<u64>> {
|
|
65
|
+
parse_header_to_str(headers, CONTENT_LENGTH)?
|
|
66
|
+
.map(|v| {
|
|
67
|
+
v.parse::<u64>().map_err(|e| {
|
|
68
|
+
Error::new(ErrorKind::Unexpected, "header value is not valid integer").set_source(e)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
.transpose()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Parse content md5 from header map.
|
|
75
|
+
pub fn parse_content_md5(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
76
|
+
parse_header_to_str(headers, "content-md5")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Parse content type from header map.
|
|
80
|
+
pub fn parse_content_type(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
81
|
+
parse_header_to_str(headers, CONTENT_TYPE)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// Parse content encoding from header map.
|
|
85
|
+
pub fn parse_content_encoding(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
86
|
+
parse_header_to_str(headers, CONTENT_ENCODING)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// Parse content range from header map.
|
|
90
|
+
pub fn parse_content_range(headers: &HeaderMap) -> Result<Option<BytesContentRange>> {
|
|
91
|
+
parse_header_to_str(headers, CONTENT_RANGE)?
|
|
92
|
+
.map(|v| v.parse())
|
|
93
|
+
.transpose()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/// Parse last modified from header map.
|
|
97
|
+
pub fn parse_last_modified(headers: &HeaderMap) -> Result<Option<DateTime<Utc>>> {
|
|
98
|
+
parse_header_to_str(headers, LAST_MODIFIED)?
|
|
99
|
+
.map(parse_datetime_from_rfc2822)
|
|
100
|
+
.transpose()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// Parse etag from header map.
|
|
104
|
+
pub fn parse_etag(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
105
|
+
parse_header_to_str(headers, ETAG)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Parse Content-Disposition for header map
|
|
109
|
+
pub fn parse_content_disposition(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
110
|
+
parse_header_to_str(headers, CONTENT_DISPOSITION)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// Parse multipart boundary from header map.
|
|
114
|
+
pub fn parse_multipart_boundary(headers: &HeaderMap) -> Result<Option<&str>> {
|
|
115
|
+
parse_header_to_str(headers, CONTENT_TYPE).map(|v| v.and_then(|v| v.split("boundary=").nth(1)))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// Parse header value to string according to name.
|
|
119
|
+
#[inline]
|
|
120
|
+
pub fn parse_header_to_str<K>(headers: &HeaderMap, name: K) -> Result<Option<&str>>
|
|
121
|
+
where
|
|
122
|
+
HeaderName: TryFrom<K>,
|
|
123
|
+
{
|
|
124
|
+
let name = HeaderName::try_from(name).map_err(|_| {
|
|
125
|
+
Error::new(
|
|
126
|
+
ErrorKind::Unexpected,
|
|
127
|
+
"header name must be valid http header name but not",
|
|
128
|
+
)
|
|
129
|
+
.with_operation("http_util::parse_header_to_str")
|
|
130
|
+
})?;
|
|
131
|
+
|
|
132
|
+
let value = if let Some(v) = headers.get(&name) {
|
|
133
|
+
v
|
|
134
|
+
} else {
|
|
135
|
+
return Ok(None);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
Ok(Some(value.to_str().map_err(|e| {
|
|
139
|
+
Error::new(
|
|
140
|
+
ErrorKind::Unexpected,
|
|
141
|
+
"header value must be valid utf-8 string but not",
|
|
142
|
+
)
|
|
143
|
+
.with_operation("http_util::parse_header_to_str")
|
|
144
|
+
.with_context("header_name", name.as_str())
|
|
145
|
+
.set_source(e)
|
|
146
|
+
})?))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// parse_into_metadata will parse standards http headers into Metadata.
|
|
150
|
+
///
|
|
151
|
+
/// # Notes
|
|
152
|
+
///
|
|
153
|
+
/// parse_into_metadata only handles the standard behavior of http
|
|
154
|
+
/// headers. If services have their own logic, they should update the parsed
|
|
155
|
+
/// metadata on demand.
|
|
156
|
+
pub fn parse_into_metadata(path: &str, headers: &HeaderMap) -> Result<Metadata> {
|
|
157
|
+
let mode = if path.ends_with('/') {
|
|
158
|
+
EntryMode::DIR
|
|
159
|
+
} else {
|
|
160
|
+
EntryMode::FILE
|
|
161
|
+
};
|
|
162
|
+
let mut m = Metadata::new(mode);
|
|
163
|
+
|
|
164
|
+
if let Some(v) = parse_cache_control(headers)? {
|
|
165
|
+
m.set_cache_control(v);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if let Some(v) = parse_content_length(headers)? {
|
|
169
|
+
m.set_content_length(v);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if let Some(v) = parse_content_type(headers)? {
|
|
173
|
+
m.set_content_type(v);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if let Some(v) = parse_content_encoding(headers)? {
|
|
177
|
+
m.set_content_encoding(v);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if let Some(v) = parse_content_range(headers)? {
|
|
181
|
+
m.set_content_range(v);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if let Some(v) = parse_etag(headers)? {
|
|
185
|
+
m.set_etag(v);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if let Some(v) = parse_content_md5(headers)? {
|
|
189
|
+
m.set_content_md5(v);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if let Some(v) = parse_last_modified(headers)? {
|
|
193
|
+
m.set_last_modified(v);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if let Some(v) = parse_content_disposition(headers)? {
|
|
197
|
+
m.set_content_disposition(v);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
Ok(m)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/// Parse prefixed headers and return a map with the prefix of each header removed.
|
|
204
|
+
pub fn parse_prefixed_headers(headers: &HeaderMap, prefix: &str) -> HashMap<String, String> {
|
|
205
|
+
headers
|
|
206
|
+
.iter()
|
|
207
|
+
.filter_map(|(name, value)| {
|
|
208
|
+
name.as_str().strip_prefix(prefix).and_then(|stripped_key| {
|
|
209
|
+
value
|
|
210
|
+
.to_str()
|
|
211
|
+
.ok()
|
|
212
|
+
.map(|parsed_value| (stripped_key.to_string(), parsed_value.to_string()))
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
.collect()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// format content md5 header by given input.
|
|
219
|
+
pub fn format_content_md5(bs: &[u8]) -> String {
|
|
220
|
+
let mut hasher = md5::Md5::new();
|
|
221
|
+
hasher.update(bs);
|
|
222
|
+
|
|
223
|
+
general_purpose::STANDARD.encode(hasher.finalize())
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// format authorization header by basic auth.
|
|
227
|
+
///
|
|
228
|
+
/// # Errors
|
|
229
|
+
///
|
|
230
|
+
/// If input username is empty, function will return an unexpected error.
|
|
231
|
+
pub fn format_authorization_by_basic(username: &str, password: &str) -> Result<String> {
|
|
232
|
+
if username.is_empty() {
|
|
233
|
+
return Err(Error::new(
|
|
234
|
+
ErrorKind::Unexpected,
|
|
235
|
+
"can't build authorization header with empty username",
|
|
236
|
+
));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let value = general_purpose::STANDARD.encode(format!("{username}:{password}"));
|
|
240
|
+
|
|
241
|
+
Ok(format!("Basic {value}"))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// format authorization header by bearer token.
|
|
245
|
+
///
|
|
246
|
+
/// # Errors
|
|
247
|
+
///
|
|
248
|
+
/// If input token is empty, function will return an unexpected error.
|
|
249
|
+
pub fn format_authorization_by_bearer(token: &str) -> Result<String> {
|
|
250
|
+
if token.is_empty() {
|
|
251
|
+
return Err(Error::new(
|
|
252
|
+
ErrorKind::Unexpected,
|
|
253
|
+
"can't build authorization header with empty token",
|
|
254
|
+
));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
Ok(format!("Bearer {token}"))
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/// Build header value from given string.
|
|
261
|
+
pub fn build_header_value(v: &str) -> Result<HeaderValue> {
|
|
262
|
+
HeaderValue::from_str(v).map_err(|e| {
|
|
263
|
+
Error::new(
|
|
264
|
+
ErrorKind::ConfigInvalid,
|
|
265
|
+
"header value contains invalid characters",
|
|
266
|
+
)
|
|
267
|
+
.with_operation("http_util::build_header_value")
|
|
268
|
+
.set_source(e)
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
#[cfg(test)]
|
|
273
|
+
mod tests {
|
|
274
|
+
use super::*;
|
|
275
|
+
|
|
276
|
+
/// Test cases is from https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html
|
|
277
|
+
#[test]
|
|
278
|
+
fn test_format_content_md5() {
|
|
279
|
+
let cases = vec![(
|
|
280
|
+
r#"<Delete>
|
|
281
|
+
<Object>
|
|
282
|
+
<Key>sample1.txt</Key>
|
|
283
|
+
</Object>
|
|
284
|
+
<Object>
|
|
285
|
+
<Key>sample2.txt</Key>
|
|
286
|
+
</Object>
|
|
287
|
+
</Delete>"#,
|
|
288
|
+
"WOctCY1SS662e7ziElh4cw==",
|
|
289
|
+
)];
|
|
290
|
+
|
|
291
|
+
for (input, expected) in cases {
|
|
292
|
+
let actual = format_content_md5(input.as_bytes());
|
|
293
|
+
|
|
294
|
+
assert_eq!(actual, expected)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/// Test cases is borrowed from
|
|
299
|
+
///
|
|
300
|
+
/// - RFC2617: https://datatracker.ietf.org/doc/html/rfc2617#section-2
|
|
301
|
+
/// - MDN: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
|
|
302
|
+
#[test]
|
|
303
|
+
fn test_format_authorization_by_basic() {
|
|
304
|
+
let cases = vec![
|
|
305
|
+
("aladdin", "opensesame", "Basic YWxhZGRpbjpvcGVuc2VzYW1l"),
|
|
306
|
+
("aladdin", "", "Basic YWxhZGRpbjo="),
|
|
307
|
+
(
|
|
308
|
+
"Aladdin",
|
|
309
|
+
"open sesame",
|
|
310
|
+
"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
|
|
311
|
+
),
|
|
312
|
+
("Aladdin", "", "Basic QWxhZGRpbjo="),
|
|
313
|
+
];
|
|
314
|
+
|
|
315
|
+
for (username, password, expected) in cases {
|
|
316
|
+
let actual =
|
|
317
|
+
format_authorization_by_basic(username, password).expect("format must success");
|
|
318
|
+
|
|
319
|
+
assert_eq!(actual, expected)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/// Test cases is borrowed from
|
|
324
|
+
///
|
|
325
|
+
/// - RFC6750: https://datatracker.ietf.org/doc/html/rfc6750
|
|
326
|
+
#[test]
|
|
327
|
+
fn test_format_authorization_by_bearer() {
|
|
328
|
+
let cases = vec![("mF_9.B5f-4.1JqM", "Bearer mF_9.B5f-4.1JqM")];
|
|
329
|
+
|
|
330
|
+
for (token, expected) in cases {
|
|
331
|
+
let actual = format_authorization_by_bearer(token).expect("format must success");
|
|
332
|
+
|
|
333
|
+
assert_eq!(actual, expected)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#[test]
|
|
338
|
+
fn test_parse_multipart_boundary() {
|
|
339
|
+
let cases = vec![
|
|
340
|
+
(
|
|
341
|
+
"multipart/mixed; boundary=gc0p4Jq0M2Yt08jU534c0p",
|
|
342
|
+
Some("gc0p4Jq0M2Yt08jU534c0p"),
|
|
343
|
+
),
|
|
344
|
+
("multipart/mixed", None),
|
|
345
|
+
];
|
|
346
|
+
|
|
347
|
+
for (input, expected) in cases {
|
|
348
|
+
let mut headers = HeaderMap::new();
|
|
349
|
+
headers.insert(CONTENT_TYPE, HeaderValue::from_str(input).unwrap());
|
|
350
|
+
|
|
351
|
+
let actual = parse_multipart_boundary(&headers).expect("parse must success");
|
|
352
|
+
|
|
353
|
+
assert_eq!(actual, expected)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|