Skip to main content

tame_gcs/v1/objects/
insert.rs

1use crate::{
2    common::{Conditionals, PredefinedAcl, Projection, StandardQueryParameters},
3    error::{self, Error},
4    response::ApiResponse,
5    types::ObjectIdentifier,
6};
7
8mod multipart;
9mod resumable;
10
11pub use multipart::*;
12pub use resumable::*;
13
14/// Optional parameters when inserting an object.
15/// See [here](https://cloud.google.com/storage/docs/json_api/v1/objects/insert#parameters)
16#[derive(Default, Serialize)]
17#[serde(rename_all = "camelCase")]
18pub struct InsertObjectOptional<'a> {
19    #[serde(flatten)]
20    pub standard_params: StandardQueryParameters<'a>,
21    /// The Content-Type of the object, defaults to `application/octet-stream`.
22    #[serde(skip)]
23    pub content_type: Option<&'a str>,
24    /// If set, sets the contentEncoding property of the final object to
25    /// this value. Setting this parameter is equivalent to setting the
26    /// `contentEncoding` metadata property. This can be useful when
27    /// uploading an object with uploadType=media to indicate the
28    /// encoding of the content being uploaded.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub content_encoding: Option<&'a str>,
31    #[serde(flatten)]
32    pub conditionals: Conditionals,
33    /// Resource name of the Cloud KMS key that will be used to encrypt
34    /// the object. Overrides the object metadata's `kms_key_name` value, if any.
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub kms_key_name: Option<&'a str>,
37    /// Apply a predefined set of access controls to this object.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub predefined_acl: Option<PredefinedAcl>,
40    /// Set of properties to return. Defaults to `noAcl`, unless the object
41    /// resource specifies the acl property, when it defaults to full.
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub projection: Option<Projection>,
44    /// The project to be billed for this request. Required for Requester Pays buckets.
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub user_project: Option<&'a str>,
47}
48
49/// The response from an [`insert`](#method.insert) request is the object [metadata](https://cloud.google.com/storage/docs/json_api/v1/objects#resource)
50/// for the newly inserted object.
51pub struct InsertResponse {
52    pub metadata: super::Metadata,
53}
54
55impl ApiResponse<&[u8]> for InsertResponse {}
56impl ApiResponse<bytes::Bytes> for InsertResponse {}
57
58impl<B> TryFrom<http::Response<B>> for InsertResponse
59where
60    B: AsRef<[u8]>,
61{
62    type Error = Error;
63
64    fn try_from(response: http::Response<B>) -> Result<Self, Self::Error> {
65        let (_parts, body) = response.into_parts();
66        let metadata: super::Metadata = serde_json::from_slice(body.as_ref())?;
67        Ok(Self { metadata })
68    }
69}
70
71impl super::Object {
72    /// Stores a new object and metadata.
73    ///
74    /// * Maximum file size: `5TB`
75    /// * Accepted Media MIME types: `*/*`
76    ///
77    /// Required IAM Permissions: `storage.objects.create`, `storage.objects.delete`
78    ///
79    /// Note: `storage.objects.delete` is only needed if an object with the same
80    /// name already exists.
81    ///
82    /// [Complete API Documentation](https://cloud.google.com/storage/docs/json_api/v1/objects/insert)
83    pub fn insert_simple<'a, OID, B>(
84        &self,
85        id: &OID,
86        content: B,
87        length: u64,
88        optional: Option<InsertObjectOptional<'_>>,
89    ) -> Result<http::Request<B>, Error>
90    where
91        OID: ObjectIdentifier<'a> + ?Sized,
92    {
93        let mut uri = format!(
94            "https://{}/upload/storage/v1/b/{}/o?name={}&uploadType=media",
95            self.authority.as_str(),
96            percent_encoding::percent_encode(id.bucket().as_ref(), crate::util::PATH_ENCODE_SET,),
97            percent_encoding::percent_encode(id.object().as_ref(), crate::util::QUERY_ENCODE_SET,),
98        );
99
100        let query = optional.unwrap_or_default();
101
102        let req_builder = http::Request::builder()
103            .header(
104                http::header::CONTENT_TYPE,
105                http::header::HeaderValue::from_str(
106                    query.content_type.unwrap_or("application/octet-stream"),
107                )
108                .map_err(http::Error::from)?,
109            )
110            .header(http::header::CONTENT_LENGTH, length);
111
112        let query_params = serde_urlencoded::to_string(query)?;
113        if !query_params.is_empty() {
114            uri.push('&');
115            uri.push_str(&query_params);
116        }
117
118        Ok(req_builder.method("POST").uri(uri).body(content)?)
119    }
120}