This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 0e41a17e0 refactor: Supabase is now an S3-compatible servcices (#5663)
0e41a17e0 is described below
commit 0e41a17e0b5535a67d7e89bca7d6cba142c1fffe
Author: Xuanwo <[email protected]>
AuthorDate: Wed Feb 26 15:26:23 2025 +0800
refactor: Supabase is now an S3-compatible servcices (#5663)
* refactor: Supabase is now an S3-compatible servcices
Signed-off-by: Xuanwo <[email protected]>
* Remove supabase
Signed-off-by: Xuanwo <[email protected]>
---------
Signed-off-by: Xuanwo <[email protected]>
---
.env.example | 4 -
.github/workflows/ci_core.yml | 1 -
bindings/c/include/opendal.h | 2 +-
bindings/c/src/operator.rs | 2 +-
bindings/java/Cargo.toml | 2 -
.../java/org/apache/opendal/ServiceConfig.java | 46 ----
bindings/lua/src/operator_doc.lua | 10 +-
bindings/nodejs/Cargo.toml | 2 -
bindings/python/Cargo.toml | 2 -
bindings/python/python/opendal/__base.pyi | 12 -
core/Cargo.toml | 1 -
core/fuzz/Cargo.toml | 1 -
core/src/services/mod.rs | 3 -
core/src/services/supabase/backend.rs | 219 ------------------
core/src/services/supabase/config.rs | 50 -----
core/src/services/supabase/core.rs | 244 ---------------------
core/src/services/supabase/docs.md | 51 -----
core/src/services/supabase/error.rs | 82 -------
core/src/services/supabase/mod.rs | 31 ---
core/src/services/supabase/writer.rs | 62 ------
core/src/types/operator/builder.rs | 2 -
core/src/types/scheme.rs | 6 -
core/tests/behavior/async_delete.rs | 5 -
core/tests/behavior/async_read.rs | 5 -
core/tests/behavior/async_stat.rs | 5 -
core/tests/behavior/async_write.rs | 5 -
core/tests/behavior/blocking_stat.rs | 5 -
core/tests/behavior/blocking_write.rs | 5 -
28 files changed, 7 insertions(+), 858 deletions(-)
diff --git a/.env.example b/.env.example
index 934c0f061..814ab27a3 100644
--- a/.env.example
+++ b/.env.example
@@ -79,10 +79,6 @@ OPENDAL_WEBHDFS_ENDPOINT=http://127.0.0.1:9870
OPENDAL_WEBHDFS_DELEGATION=<delegation>
OPENDAL_WEBHDFS_ATOMIC_WRITE_DIR=.opendal_tmp/
OPENDAL_WEBHDFS_DISABLE_LIST_BATCH=false
-# supbase
-OPENDAL_SUPABASE_BUCKET=<bucket>
-OPENDAL_SUPABASE_ENDPOINT=<endpoint>
-OPENDAL_SUPABASE_KEY=<service_key>
# vercel artifacts
OPENDAL_VERCEL_ARTIFACTS_ACCESS_TOKEN=<token>
# onedrive
diff --git a/.github/workflows/ci_core.yml b/.github/workflows/ci_core.yml
index 0d0137309..323dcc246 100644
--- a/.github/workflows/ci_core.yml
+++ b/.github/workflows/ci_core.yml
@@ -207,7 +207,6 @@ jobs:
# services-sftp
services-sled
services-swift
- services-supabase
services-tikv
services-vercel-artifacts
services-webdav
diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h
index 2597edbdb..53bc1b0e7 100644
--- a/bindings/c/include/opendal.h
+++ b/bindings/c/include/opendal.h
@@ -735,7 +735,7 @@ void opendal_operator_free(const struct opendal_operator
*ptr);
* reference the
[documentation](https://opendal.apache.org/docs/category/services/) for
* each service, especially for the **Configuration Part**.
*
- * @param scheme the service scheme you want to specify, e.g. "fs", "s3",
"supabase"
+ * @param scheme the service scheme you want to specify, e.g. "fs", "s3"
* @param options the pointer to the options for this operator, it could be
NULL, which means no
* option is set
* @see opendal_operator_options
diff --git a/bindings/c/src/operator.rs b/bindings/c/src/operator.rs
index 3aa8b2e2a..c2fb30b2d 100644
--- a/bindings/c/src/operator.rs
+++ b/bindings/c/src/operator.rs
@@ -108,7 +108,7 @@ fn build_operator(
/// reference the
[documentation](https://opendal.apache.org/docs/category/services/) for
/// each service, especially for the **Configuration Part**.
///
-/// @param scheme the service scheme you want to specify, e.g. "fs", "s3",
"supabase"
+/// @param scheme the service scheme you want to specify, e.g. "fs", "s3"
/// @param options the pointer to the options for this operator, it could be
NULL, which means no
/// option is set
/// @see opendal_operator_options
diff --git a/bindings/java/Cargo.toml b/bindings/java/Cargo.toml
index 817ddc18c..0f2d6b7ce 100644
--- a/bindings/java/Cargo.toml
+++ b/bindings/java/Cargo.toml
@@ -78,7 +78,6 @@ services-all = [
# FIXME: rocksdb will lead to "cannot allocate memory in static TLS block"
while linking.
# "services-rocksdb",
"services-sled",
- "services-supabase",
"services-tikv",
"services-vercel-artifacts",
"services-mongodb",
@@ -143,7 +142,6 @@ services-seafile = ["opendal/services-seafile"]
services-sftp = ["opendal/services-sftp"]
services-sled = ["opendal/services-sled"]
services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
services-swift = ["opendal/services-swift"]
services-tikv = ["opendal/services-tikv"]
services-upyun = ["opendal/services-upyun"]
diff --git a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
index d609e3778..e1f092105 100644
--- a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
+++ b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
@@ -3192,52 +3192,6 @@ public interface ServiceConfig {
}
}
- /**
- * Configuration for service supabase.
- */
- @Builder
- @Data
- @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
- class Supabase implements ServiceConfig {
- /**
- * <p>The bucket for supabase service.</p>
- */
- public final @NonNull String bucket;
- /**
- * <p>The root for supabase service.</p>
- */
- public final String root;
- /**
- * <p>The endpoint for supabase service.</p>
- */
- public final String endpoint;
- /**
- * <p>The key for supabase service.</p>
- */
- public final String key;
-
- @Override
- public String scheme() {
- return "supabase";
- }
-
- @Override
- public Map<String, String> configMap() {
- final HashMap<String, String> map = new HashMap<>();
- map.put("bucket", bucket);
- if (root != null) {
- map.put("root", root);
- }
- if (endpoint != null) {
- map.put("endpoint", endpoint);
- }
- if (key != null) {
- map.put("key", key);
- }
- return map;
- }
- }
-
/**
* Configuration for service surrealdb.
*/
diff --git a/bindings/lua/src/operator_doc.lua
b/bindings/lua/src/operator_doc.lua
index d3ee1413f..01bd90894 100644
--- a/bindings/lua/src/operator_doc.lua
+++ b/bindings/lua/src/operator_doc.lua
@@ -25,24 +25,24 @@
local _M = {}
---- Construct an operator based on scheme and option. Uses an table of
key-value pairs to initialize
---- the operator based on provided scheme and options. For each scheme, i.e.
Backend,
+--- Construct an operator based on scheme and option. Uses an table of
key-value pairs to initialize
+--- the operator based on provided scheme and options. For each scheme, i.e.
Backend,
--- different options could be set, you may reference the
https://opendal.apache.org/docs/category/services/
--- for each service, especially for the **Configuration Part**.
--- @param string scheme the service scheme you want to specify, e.g. "fs",
"s3", "supabase"
+-- @param string scheme the service scheme you want to specify, e.g. "fs", "s3"
-- @param table options the table to the options for this operators
-- @return table, error opendal operator table which contain opendal operator
instance, error nil if success, others otherwise
-- @function new
---- Blockingly write raw bytes to path.
+--- Blockingly write raw bytes to path.
--- Write the bytes into the path blockingly, returns nil if success, others
otherwise
-- @param string path the designated path you want to write your bytes in
-- @param string bytes the bytes to be written
-- @return error nil if success, otherwise error message
-- @function write
---- Blockingly read raw bytes from path.
+--- Blockingly read raw bytes from path.
--- Read the data out from `path` blockingly by operator, returns the string
if success, others otherwise
-- @param string path the designated path you want to write your bytes in
-- @return string, error read data, error nil if success, otherwise error
message
diff --git a/bindings/nodejs/Cargo.toml b/bindings/nodejs/Cargo.toml
index 46557e33b..0b0482dfb 100644
--- a/bindings/nodejs/Cargo.toml
+++ b/bindings/nodejs/Cargo.toml
@@ -75,7 +75,6 @@ services-all = [
# FIXME how to support rocksdb services in bindings?
# "services-rocksdb",
"services-sled",
- "services-supabase",
"services-swift",
# FIXME this service need protoc
# "services-tikv",
@@ -141,7 +140,6 @@ services-seafile = ["opendal/services-seafile"]
services-sftp = ["opendal/services-sftp"]
services-sled = ["opendal/services-sled"]
services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
services-swift = ["opendal/services-swift"]
services-tikv = ["opendal/services-tikv"]
services-upyun = ["opendal/services-upyun"]
diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml
index b0afb08ee..3d73acf50 100644
--- a/bindings/python/Cargo.toml
+++ b/bindings/python/Cargo.toml
@@ -78,7 +78,6 @@ services-all = [
# FIXME how to support rocksdb services in bindings?
# "services-rocksdb",
"services-sled",
- "services-supabase",
"services-swift",
# FIXME this service need protoc
# "services-tikv",
@@ -144,7 +143,6 @@ services-seafile = ["opendal/services-seafile"]
services-sftp = ["opendal/services-sftp"]
services-sled = ["opendal/services-sled"]
services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
services-swift = ["opendal/services-swift"]
services-tikv = ["opendal/services-tikv"]
services-upyun = ["opendal/services-upyun"]
diff --git a/bindings/python/python/opendal/__base.pyi
b/bindings/python/python/opendal/__base.pyi
index 680420f68..5bce6711c 100644
--- a/bindings/python/python/opendal/__base.pyi
+++ b/bindings/python/python/opendal/__base.pyi
@@ -717,18 +717,6 @@ class _Base:
root: str = ...,
) -> None: ...
- @overload
- def __init__(
- self,
- scheme: Literal["supabase"],
- /,
- *,
- bucket: str,
- root: str = ...,
- endpoint: str = ...,
- key: str = ...,
- ) -> None: ...
-
@overload
def __init__(
self,
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 0c7cf270d..5e279d58e 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -196,7 +196,6 @@ services-seafile = []
services-sftp = ["dep:openssh", "dep:openssh-sftp-client", "dep:bb8"]
services-sled = ["dep:sled", "internal-tokio-rt"]
services-sqlite = ["dep:sqlx", "sqlx?/sqlite", "dep:ouroboros"]
-services-supabase = []
services-surrealdb = ["dep:surrealdb"]
services-swift = []
services-tikv = ["tikv-client"]
diff --git a/core/fuzz/Cargo.toml b/core/fuzz/Cargo.toml
index 2600c0ba4..b5f342cc4 100644
--- a/core/fuzz/Cargo.toml
+++ b/core/fuzz/Cargo.toml
@@ -68,7 +68,6 @@ services-seafile = ["opendal/services-seafile"]
services-sftp = ["opendal/services-sftp"]
services-sled = ["opendal/services-sled"]
services-sqlite = ["opendal/services-sqlite"]
-services-supabase = ["opendal/services-supabase"]
services-swift = ["opendal/services-swift"]
services-tikv = ["opendal/services-tikv"]
services-upyun = ["opendal/services-upyun"]
diff --git a/core/src/services/mod.rs b/core/src/services/mod.rs
index a84bb2097..c9a98ea4f 100644
--- a/core/src/services/mod.rs
+++ b/core/src/services/mod.rs
@@ -187,9 +187,6 @@ pub use self::sled::*;
mod sqlite;
pub use self::sqlite::*;
-mod supabase;
-pub use supabase::*;
-
mod surrealdb;
pub use surrealdb::*;
diff --git a/core/src/services/supabase/backend.rs
b/core/src/services/supabase/backend.rs
deleted file mode 100644
index a9c13fdd0..000000000
--- a/core/src/services/supabase/backend.rs
+++ /dev/null
@@ -1,219 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::fmt::Debug;
-use std::fmt::Formatter;
-use std::sync::Arc;
-
-use http::Response;
-use http::StatusCode;
-use log::debug;
-
-use super::core::*;
-use super::error::parse_error;
-use super::writer::*;
-use crate::raw::*;
-use crate::services::SupabaseConfig;
-use crate::*;
-
-impl Configurator for SupabaseConfig {
- type Builder = SupabaseBuilder;
- fn into_builder(self) -> Self::Builder {
- SupabaseBuilder {
- config: self,
- http_client: None,
- }
- }
-}
-
-/// [Supabase](https://supabase.com/) service support
-#[doc = include_str!("docs.md")]
-#[derive(Default)]
-pub struct SupabaseBuilder {
- config: SupabaseConfig,
- http_client: Option<HttpClient>,
-}
-
-impl Debug for SupabaseBuilder {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- let mut d = f.debug_struct("SupabaseBuilder");
- d.field("config", &self.config);
- d.finish_non_exhaustive()
- }
-}
-
-impl SupabaseBuilder {
- /// Set root of this backend.
- ///
- /// All operations will happen under this root.
- pub fn root(mut self, root: &str) -> Self {
- self.config.root = if root.is_empty() {
- None
- } else {
- Some(root.to_string())
- };
-
- self
- }
-
- /// Set bucket name of this backend.
- pub fn bucket(mut self, bucket: &str) -> Self {
- self.config.bucket = bucket.to_string();
- self
- }
-
- /// Set endpoint of this backend.
- ///
- /// Endpoint must be full uri
- pub fn endpoint(mut self, endpoint: &str) -> Self {
- self.config.endpoint = if endpoint.is_empty() {
- None
- } else {
- Some(endpoint.trim_end_matches('/').to_string())
- };
-
- self
- }
-
- /// Set the authorization key for this backend
- /// Do not set this key if you want to read public bucket
- pub fn key(mut self, key: &str) -> Self {
- self.config.key = Some(key.to_string());
- self
- }
-
- /// Specify the http client that used by this service.
- ///
- /// # Notes
- ///
- /// This API is part of OpenDAL's Raw API. `HttpClient` could be changed
- /// during minor updates.
- pub fn http_client(mut self, client: HttpClient) -> Self {
- self.http_client = Some(client);
- self
- }
-}
-
-impl Builder for SupabaseBuilder {
- const SCHEME: Scheme = Scheme::Supabase;
- type Config = SupabaseConfig;
-
- fn build(self) -> Result<impl Access> {
- let root = normalize_root(&self.config.root.unwrap_or_default());
- debug!("backend use root {}", &root);
-
- let bucket = &self.config.bucket;
-
- let endpoint = self.config.endpoint.unwrap_or_default();
-
- let http_client = if let Some(client) = self.http_client {
- client
- } else {
- HttpClient::new().map_err(|err| {
- err.with_operation("Builder::build")
- .with_context("service", Scheme::Supabase)
- })?
- };
-
- let key = self.config.key.as_ref().map(|k| k.to_owned());
-
- let core = SupabaseCore::new(&root, bucket, &endpoint, key,
http_client);
-
- let core = Arc::new(core);
-
- Ok(SupabaseBackend { core })
- }
-}
-
-#[derive(Debug)]
-pub struct SupabaseBackend {
- core: Arc<SupabaseCore>,
-}
-
-impl Access for SupabaseBackend {
- type Reader = HttpBody;
- type Writer = oio::OneShotWriter<SupabaseWriter>;
- // todo: implement Lister to support list
- type Lister = ();
- type Deleter = ();
- type BlockingReader = ();
- type BlockingWriter = ();
- type BlockingLister = ();
- type BlockingDeleter = ();
-
- fn info(&self) -> Arc<AccessorInfo> {
- let am = AccessorInfo::default();
- am.set_scheme(Scheme::Supabase)
- .set_root(&self.core.root)
- .set_name(&self.core.bucket)
- .set_native_capability(Capability {
- stat: true,
-
- read: true,
-
- write: true,
-
- shared: true,
-
- ..Default::default()
- });
-
- am.into()
- }
-
- async fn stat(&self, path: &str, _args: OpStat) -> Result<RpStat> {
- // The get_object_info does not contain the file size. Therefore
- // we first try the get the metadata through head, if we fail,
- // we then use get_object_info to get the actual error info
- let mut resp = self.core.supabase_head_object(path).await?;
-
- match resp.status() {
- StatusCode::OK => parse_into_metadata(path,
resp.headers()).map(RpStat::new),
- _ => {
- resp = self.core.supabase_get_object_info(path).await?;
- match resp.status() {
- StatusCode::NOT_FOUND if path.ends_with('/') => {
- Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
- }
- _ => Err(parse_error(resp)),
- }
- }
- }
- }
-
- async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead,
Self::Reader)> {
- let resp = self.core.supabase_get_object(path, args.range()).await?;
-
- let status = resp.status();
-
- match status {
- StatusCode::OK | StatusCode::PARTIAL_CONTENT => Ok((RpRead::new(),
resp.into_body())),
- _ => {
- let (part, mut body) = resp.into_parts();
- let buf = body.to_buffer().await?;
- Err(parse_error(Response::from_parts(part, buf)))
- }
- }
- }
-
- async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite,
Self::Writer)> {
- Ok((
- RpWrite::default(),
- oio::OneShotWriter::new(SupabaseWriter::new(self.core.clone(),
path, args)),
- ))
- }
-}
diff --git a/core/src/services/supabase/config.rs
b/core/src/services/supabase/config.rs
deleted file mode 100644
index 83c26cd7a..000000000
--- a/core/src/services/supabase/config.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::fmt::Debug;
-use std::fmt::Formatter;
-
-use serde::Deserialize;
-use serde::Serialize;
-
-/// Config for supabase service support.
-#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
-#[serde(default)]
-#[non_exhaustive]
-pub struct SupabaseConfig {
- /// The root for supabase service.
- pub root: Option<String>,
- /// The bucket for supabase service.
- pub bucket: String,
- /// The endpoint for supabase service.
- pub endpoint: Option<String>,
- /// The key for supabase service.
- pub key: Option<String>,
- // TODO(1) optional public, currently true always
- // TODO(2) optional file_size_limit, currently 0
- // TODO(3) optional allowed_mime_types, currently only string
-}
-
-impl Debug for SupabaseConfig {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("SupabaseConfig")
- .field("root", &self.root)
- .field("bucket", &self.bucket)
- .field("endpoint", &self.endpoint)
- .finish_non_exhaustive()
- }
-}
diff --git a/core/src/services/supabase/core.rs
b/core/src/services/supabase/core.rs
deleted file mode 100644
index 578a8b5f3..000000000
--- a/core/src/services/supabase/core.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::fmt::Debug;
-
-use http::header::CONTENT_LENGTH;
-use http::header::CONTENT_TYPE;
-use http::HeaderValue;
-use http::Request;
-use http::Response;
-
-use crate::raw::*;
-use crate::*;
-
-pub struct SupabaseCore {
- pub root: String,
- pub bucket: String,
- pub endpoint: String,
-
- /// The key used for authorization
- /// If loaded, the read operation will always access the nonpublic
resources.
- /// If you want to read the public resources, please do not set the key.
- pub key: Option<String>,
-
- pub http_client: HttpClient,
-}
-
-impl Debug for SupabaseCore {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("SupabaseCore")
- .field("root", &self.root)
- .field("bucket", &self.bucket)
- .field("endpoint", &self.endpoint)
- .finish_non_exhaustive()
- }
-}
-
-impl SupabaseCore {
- pub fn new(
- root: &str,
- bucket: &str,
- endpoint: &str,
- key: Option<String>,
- client: HttpClient,
- ) -> Self {
- Self {
- root: root.to_string(),
- bucket: bucket.to_string(),
- endpoint: endpoint.to_string(),
- key,
- http_client: client,
- }
- }
-
- /// Add authorization header to the request if the key is set. Otherwise
leave
- /// the request as-is.
- pub fn sign<T>(&self, req: &mut Request<T>) -> Result<()> {
- if let Some(k) = &self.key {
- let v = HeaderValue::from_str(&format!("Bearer {}", k)).unwrap();
- req.headers_mut().insert(http::header::AUTHORIZATION, v);
- }
- Ok(())
- }
-}
-
-// requests
-impl SupabaseCore {
- pub fn supabase_upload_object_request(
- &self,
- path: &str,
- size: Option<usize>,
- content_type: Option<&str>,
- body: Buffer,
- ) -> Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- let mut req = Request::post(&url);
-
- if let Some(size) = size {
- req = req.header(CONTENT_LENGTH, size)
- }
-
- if let Some(mime) = content_type {
- req = req.header(CONTENT_TYPE, mime)
- }
-
- let req = req.body(body).map_err(new_request_build_error)?;
-
- Ok(req)
- }
-
- pub fn supabase_get_object_public_request(
- &self,
- path: &str,
- _: BytesRange,
- ) -> Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/public/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- let req = Request::get(&url);
-
- req.body(Buffer::new()).map_err(new_request_build_error)
- }
-
- pub fn supabase_get_object_auth_request(
- &self,
- path: &str,
- _: BytesRange,
- ) -> Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/authenticated/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- let req = Request::get(&url);
-
- req.body(Buffer::new()).map_err(new_request_build_error)
- }
-
- pub fn supabase_head_object_public_request(&self, path: &str) ->
Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/public/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- Request::head(&url)
- .body(Buffer::new())
- .map_err(new_request_build_error)
- }
-
- pub fn supabase_head_object_auth_request(&self, path: &str) ->
Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/authenticated/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- Request::head(&url)
- .body(Buffer::new())
- .map_err(new_request_build_error)
- }
-
- pub fn supabase_get_object_info_public_request(&self, path: &str) ->
Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/info/public/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- Request::get(&url)
- .body(Buffer::new())
- .map_err(new_request_build_error)
- }
-
- pub fn supabase_get_object_info_auth_request(&self, path: &str) ->
Result<Request<Buffer>> {
- let p = build_abs_path(&self.root, path);
- let url = format!(
- "{}/storage/v1/object/info/authenticated/{}/{}",
- self.endpoint,
- self.bucket,
- percent_encode_path(&p)
- );
-
- Request::get(&url)
- .body(Buffer::new())
- .map_err(new_request_build_error)
- }
-}
-
-// core utils
-impl SupabaseCore {
- pub async fn send(&self, req: Request<Buffer>) -> Result<Response<Buffer>>
{
- self.http_client.send(req).await
- }
-
- pub async fn supabase_get_object(
- &self,
- path: &str,
- range: BytesRange,
- ) -> Result<Response<HttpBody>> {
- let mut req = if self.key.is_some() {
- self.supabase_get_object_auth_request(path, range)?
- } else {
- self.supabase_get_object_public_request(path, range)?
- };
- self.sign(&mut req)?;
- self.http_client.fetch(req).await
- }
-
- pub async fn supabase_head_object(&self, path: &str) ->
Result<Response<Buffer>> {
- let mut req = if self.key.is_some() {
- self.supabase_head_object_auth_request(path)?
- } else {
- self.supabase_head_object_public_request(path)?
- };
- self.sign(&mut req)?;
- self.send(req).await
- }
-
- pub async fn supabase_get_object_info(&self, path: &str) ->
Result<Response<Buffer>> {
- let mut req = if self.key.is_some() {
- self.supabase_get_object_info_auth_request(path)?
- } else {
- self.supabase_get_object_info_public_request(path)?
- };
- self.sign(&mut req)?;
- self.send(req).await
- }
-}
diff --git a/core/src/services/supabase/docs.md
b/core/src/services/supabase/docs.md
deleted file mode 100644
index 629d28a77..000000000
--- a/core/src/services/supabase/docs.md
+++ /dev/null
@@ -1,51 +0,0 @@
-## Capabilities
-
-- [x] stat
-- [x] read
-- [x] write
-- [x] create_dir
-- [x] delete
-- [ ] copy
-- [ ] rename
-- [ ] list
-- [ ] presign
-- [ ] blocking
-
-## Configuration
-
-- `root`: Set the work dir for backend.
-- `bucket`: Set the container name for backend.
-- `endpoint`: Set the endpoint for backend.
-- `key`: Set the authorization key for the backend, do not set if you want to
read public bucket
-
-### Authorization keys
-
-There are two types of key in the Supabase, one is anon_key(Client key),
another one is
-service_role_key(Secret key). The former one can only write public resources
while the latter one
-can access all resources. Note that if you want to read public resources, do
not set the key.
-
-## Example
-
-### Via Builder
-
-```rust,no_run
-use anyhow::Result;
-use opendal::services::Supabase;
-use opendal::Operator;
-
-#[tokio::main]
-async fn main() -> Result<()> {
- let mut builder = Supabase::default()
- .root("/")
- .bucket("test_bucket")
- .endpoint("http://127.0.0.1:54321")
- // this sets up the anon_key, which means this operator can only write
public resource
- .key("some_anon_key");
-
- let op: Operator = Operator::new(builder)?.finish();
-
- Ok(())
-}
-```
-
-
diff --git a/core/src/services/supabase/error.rs
b/core/src/services/supabase/error.rs
deleted file mode 100644
index 273addb90..000000000
--- a/core/src/services/supabase/error.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use http::Response;
-use http::StatusCode;
-use serde::Deserialize;
-use serde_json::from_slice;
-
-use crate::raw::*;
-use crate::*;
-
-#[derive(Default, Debug, Deserialize)]
-#[serde(default, rename_all = "camelCase")]
-/// The error returned by Supabase
-struct SupabaseError {
- status_code: String,
- error: String,
- message: String,
-}
-
-/// Parse the supabase error type to the OpenDAL error type
-pub(super) fn parse_error(resp: Response<Buffer>) -> Error {
- let (parts, body) = resp.into_parts();
- let bs = body.to_bytes();
-
- // Check HTTP status code first/
- let (mut kind, mut retryable) = match parts.status.as_u16() {
- 500 | 502 | 503 | 504 => (ErrorKind::Unexpected, true),
- _ => (ErrorKind::Unexpected, false),
- };
-
- // Than extrace the error message.
- let (message, _) = from_slice::<SupabaseError>(&bs)
- .map(|sb_err| {
- (kind, retryable) = parse_supabase_error(&sb_err);
- (format!("{sb_err:?}"), Some(sb_err))
- })
- .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
-
- let mut err = Error::new(kind, message);
-
- err = with_error_response_context(err, parts);
-
- if retryable {
- err = err.set_temporary();
- }
-
- err
-}
-
-// Return the error kind and whether it is retryable
-fn parse_supabase_error(err: &SupabaseError) -> (ErrorKind, bool) {
- let code = err.status_code.parse::<u16>().unwrap();
- let status_code = StatusCode::from_u16(code).unwrap();
- match status_code {
- StatusCode::CONFLICT => (ErrorKind::AlreadyExists, false),
- StatusCode::NOT_FOUND => (ErrorKind::NotFound, false),
- StatusCode::FORBIDDEN => (ErrorKind::PermissionDenied, false),
- StatusCode::PRECONDITION_FAILED | StatusCode::NOT_MODIFIED => {
- (ErrorKind::ConditionNotMatch, false)
- }
- StatusCode::INTERNAL_SERVER_ERROR
- | StatusCode::BAD_GATEWAY
- | StatusCode::SERVICE_UNAVAILABLE
- | StatusCode::GATEWAY_TIMEOUT => (ErrorKind::Unexpected, true),
- _ => (ErrorKind::Unexpected, false),
- }
-}
diff --git a/core/src/services/supabase/mod.rs
b/core/src/services/supabase/mod.rs
deleted file mode 100644
index 4b485a2f1..000000000
--- a/core/src/services/supabase/mod.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#[cfg(feature = "services-supabase")]
-mod core;
-#[cfg(feature = "services-supabase")]
-mod error;
-#[cfg(feature = "services-supabase")]
-mod writer;
-
-#[cfg(feature = "services-supabase")]
-mod backend;
-#[cfg(feature = "services-supabase")]
-pub use backend::SupabaseBuilder as Supabase;
-
-mod config;
-pub use config::SupabaseConfig;
diff --git a/core/src/services/supabase/writer.rs
b/core/src/services/supabase/writer.rs
deleted file mode 100644
index fd31acd77..000000000
--- a/core/src/services/supabase/writer.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::sync::Arc;
-
-use http::StatusCode;
-
-use super::core::*;
-use super::error::parse_error;
-use crate::raw::*;
-use crate::*;
-
-pub struct SupabaseWriter {
- core: Arc<SupabaseCore>,
-
- op: OpWrite,
- path: String,
-}
-
-impl SupabaseWriter {
- pub fn new(core: Arc<SupabaseCore>, path: &str, op: OpWrite) -> Self {
- SupabaseWriter {
- core,
- op,
- path: path.to_string(),
- }
- }
-}
-
-impl oio::OneShotWrite for SupabaseWriter {
- async fn write_once(&self, bs: Buffer) -> Result<Metadata> {
- let mut req = self.core.supabase_upload_object_request(
- &self.path,
- Some(bs.len()),
- self.op.content_type(),
- bs,
- )?;
-
- self.core.sign(&mut req)?;
-
- let resp = self.core.send(req).await?;
-
- match resp.status() {
- StatusCode::OK => Ok(Metadata::default()),
- _ => Err(parse_error(resp)),
- }
- }
-}
diff --git a/core/src/types/operator/builder.rs
b/core/src/types/operator/builder.rs
index 7c393649b..f739b5fbf 100644
--- a/core/src/types/operator/builder.rs
+++ b/core/src/types/operator/builder.rs
@@ -268,8 +268,6 @@ impl Operator {
Scheme::Sled => Self::from_iter::<services::Sled>(iter)?.finish(),
#[cfg(feature = "services-sqlite")]
Scheme::Sqlite =>
Self::from_iter::<services::Sqlite>(iter)?.finish(),
- #[cfg(feature = "services-supabase")]
- Scheme::Supabase =>
Self::from_iter::<services::Supabase>(iter)?.finish(),
#[cfg(feature = "services-swift")]
Scheme::Swift =>
Self::from_iter::<services::Swift>(iter)?.finish(),
#[cfg(feature = "services-tikv")]
diff --git a/core/src/types/scheme.rs b/core/src/types/scheme.rs
index ad34feddd..dfa22d8b6 100644
--- a/core/src/types/scheme.rs
+++ b/core/src/types/scheme.rs
@@ -135,8 +135,6 @@ pub enum Scheme {
Sftp,
/// [sled][crate::services::Sled]: Sled services
Sled,
- /// [Supabase][crate::services::Supabase]: Supabase storage service
- Supabase,
/// [swift][crate::services::Swift]: Swift backend support.
Swift,
/// [Vercel Artifacts][crate::services::VercelArtifacts]: Vercel Artifacts
service, as known as Vercel Remote Caching.
@@ -289,8 +287,6 @@ impl Scheme {
Scheme::Sled,
#[cfg(feature = "services-sqlite")]
Scheme::Sqlite,
- #[cfg(feature = "services-supabase")]
- Scheme::Supabase,
#[cfg(feature = "services-swift")]
Scheme::Swift,
#[cfg(feature = "services-tikv")]
@@ -392,7 +388,6 @@ impl FromStr for Scheme {
"pcloud" => Ok(Scheme::Pcloud),
"sftp" => Ok(Scheme::Sftp),
"sled" => Ok(Scheme::Sled),
- "supabase" => Ok(Scheme::Supabase),
"swift" => Ok(Scheme::Swift),
"oss" => Ok(Scheme::Oss),
"vercel_artifacts" => Ok(Scheme::VercelArtifacts),
@@ -460,7 +455,6 @@ impl From<Scheme> for &'static str {
Scheme::Seafile => "seafile",
Scheme::Sftp => "sftp",
Scheme::Sled => "sled",
- Scheme::Supabase => "supabase",
Scheme::Swift => "swift",
Scheme::VercelArtifacts => "vercel_artifacts",
Scheme::VercelBlob => "vercel_blob",
diff --git a/core/tests/behavior/async_delete.rs
b/core/tests/behavior/async_delete.rs
index 199d8965b..c860ab638 100644
--- a/core/tests/behavior/async_delete.rs
+++ b/core/tests/behavior/async_delete.rs
@@ -76,11 +76,6 @@ pub async fn test_delete_empty_dir(op: Operator) ->
Result<()> {
/// Delete file with special chars should succeed.
pub async fn test_delete_with_special_chars(op: Operator) -> Result<()> {
- // Ignore test for supabase until
https://github.com/apache/opendal/issues/2194 addressed.
- if op.info().scheme() == opendal::Scheme::Supabase {
- warn!("ignore test for supabase until
https://github.com/apache/opendal/issues/2194 is resolved");
- return Ok(());
- }
// Ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
if op.info().scheme() == opendal::Scheme::Atomicserver {
warn!("ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/async_read.rs
b/core/tests/behavior/async_read.rs
index d643851a1..e3afeb534 100644
--- a/core/tests/behavior/async_read.rs
+++ b/core/tests/behavior/async_read.rs
@@ -383,11 +383,6 @@ pub async fn test_read_with_dir_path(op: Operator) ->
anyhow::Result<()> {
/// Read file with special chars should succeed.
pub async fn test_read_with_special_chars(op: Operator) -> anyhow::Result<()> {
- // Ignore test for supabase until
https://github.com/apache/opendal/issues/2194 addressed.
- if op.info().scheme() == opendal::Scheme::Supabase {
- warn!("ignore test for supabase until
https://github.com/apache/opendal/issues/2194 is resolved");
- return Ok(());
- }
// Ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
if op.info().scheme() == opendal::Scheme::Atomicserver {
warn!("ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/async_stat.rs
b/core/tests/behavior/async_stat.rs
index b4b004a7d..ac9a8a551 100644
--- a/core/tests/behavior/async_stat.rs
+++ b/core/tests/behavior/async_stat.rs
@@ -130,11 +130,6 @@ pub async fn test_stat_nested_parent_dir(op: Operator) ->
Result<()> {
/// Stat existing file with special chars should return metadata
pub async fn test_stat_with_special_chars(op: Operator) -> Result<()> {
- // Ignore test for supabase until
https://github.com/apache/opendal/issues/2194 addressed.
- if op.info().scheme() == opendal::Scheme::Supabase {
- warn!("ignore test for supabase until
https://github.com/apache/opendal/issues/2194 is resolved");
- return Ok(());
- }
// Ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
if op.info().scheme() == opendal::Scheme::Atomicserver {
warn!("ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/async_write.rs
b/core/tests/behavior/async_write.rs
index 3ed3bf00f..817c5bf72 100644
--- a/core/tests/behavior/async_write.rs
+++ b/core/tests/behavior/async_write.rs
@@ -114,11 +114,6 @@ pub async fn test_write_with_dir_path(op: Operator) ->
Result<()> {
/// Write a single file with special chars should succeed.
pub async fn test_write_with_special_chars(op: Operator) -> Result<()> {
- // Ignore test for supabase until
https://github.com/apache/opendal/issues/2194 addressed.
- if op.info().scheme() == opendal::Scheme::Supabase {
- warn!("ignore test for supabase until
https://github.com/apache/opendal/issues/2194 is resolved");
- return Ok(());
- }
// Ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
if op.info().scheme() == opendal::Scheme::Atomicserver {
warn!("ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/blocking_stat.rs
b/core/tests/behavior/blocking_stat.rs
index fac31481f..b6c17e41c 100644
--- a/core/tests/behavior/blocking_stat.rs
+++ b/core/tests/behavior/blocking_stat.rs
@@ -64,11 +64,6 @@ pub fn test_blocking_stat_dir(op: BlockingOperator) ->
Result<()> {
/// Stat existing file with special chars should return metadata
pub fn test_blocking_stat_with_special_chars(op: BlockingOperator) ->
Result<()> {
- // Ignore test for supabase until
https://github.com/apache/opendal/issues/2194 addressed.
- if op.info().scheme() == opendal::Scheme::Supabase {
- warn!("ignore test for supabase until
https://github.com/apache/opendal/issues/2194 is resolved");
- return Ok(());
- }
// Ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
if op.info().scheme() == opendal::Scheme::Atomicserver {
warn!("ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
diff --git a/core/tests/behavior/blocking_write.rs
b/core/tests/behavior/blocking_write.rs
index f6b4b2c1a..b3fc3d208 100644
--- a/core/tests/behavior/blocking_write.rs
+++ b/core/tests/behavior/blocking_write.rs
@@ -74,11 +74,6 @@ pub fn test_blocking_write_with_dir_path(op:
BlockingOperator) -> Result<()> {
/// Write a single file with special chars should succeed.
pub fn test_blocking_write_with_special_chars(op: BlockingOperator) ->
Result<()> {
- // Ignore test for supabase until
https://github.com/apache/opendal/issues/2194 addressed.
- if op.info().scheme() == opendal::Scheme::Supabase {
- warn!("ignore test for supabase until
https://github.com/apache/opendal/issues/2194 is resolved");
- return Ok(());
- }
// Ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
if op.info().scheme() == opendal::Scheme::Atomicserver {
warn!("ignore test for atomicserver until
https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");