defmodule Waffle.Storage.Google.Util do
@moduledoc """
A collection of utility functions.
"""
alias GoogleApi.Gax.{Request, Response}
alias GoogleApi.Storage.V1.Connection
alias GoogleApi.Storage.V1.Model.Object
@library_version Mix.Project.config() |> Keyword.get(:version, "")
@doc """
Accepts four forms of variables:
1. The tuple `{:system, key}`, which uses `System.get_env/1`.
2. The tuple `{:app, key}`, which uses `Application.get_env/2`.
3. The tuple `{:app, app, key}`, which usees `Application.get_env/2`.
4. Anything else which is returned as-is.
In the second form (`{:app, key}`), the application is assumed to be `:waffle`
although this can be overriden using the third form (`{:app, app, key}`).
"""
@spec var(any) :: any
def var({:system, key}), do: System.get_env(key)
def var({:app, app, key}), do: Application.get_env(app, key)
def var({:app, key}), do: var({:app, :waffle, key})
def var(value), do: value
@doc """
Attempts to return a value from a given options list, using the application
configs as a back-up. The application (used in `Application.get_env/3`) is
assumed to be `:waffle`.
This assumes that the application environment is set using `waffle` as the
application name.
If the value is not found in any of those location, an optional default value
can be returned.
"""
@spec option(Keyword.t, any, any) :: any
def option(opts, key, default \\ nil) do
case Keyword.get(opts, key) do
nil -> Application.get_env(:waffle, key, default)
val -> val
end
end
@doc """
If the given string does not already start with a forward slash, this function
will prepend one and return the result.
## Examples
> prepend_slash("some/path")
"/some/path"
> prepend_slash("/im/good")
"/im/good"
"""
@spec prepend_slash(String.t) :: String.t
def prepend_slash("/" <> _rest = path), do: path
def prepend_slash(path), do: "/#{path}"
@doc """
The function `Objects.storage_objects_insert/4` has the wrong URL and will
always fail to perform an upload. Because these clients are automatically
generated, there needs to be an investigation as to why this URL is being
incorrectly set before a solution can be applied. This version of the function
is an exact copy/paste of the official function except that it uses the
correct upload URL.
"""
@spec storage_objects_insert(
Tesla.Env.client,
String.t,
Keyword.t,
Keyword.t
) :: Waffle.Storage.Google.CloudStorage.object_or_error
def storage_objects_insert(connection, bucket, optional_params \\ [], opts \\ []) do
optional_params_config = %{
:alt => :query,
:fields => :query,
:key => :query,
:oauth_token => :query,
:prettyPrint => :query,
:quotaUser => :query,
:userIp => :query,
:contentEncoding => :query,
:ifGenerationMatch => :query,
:ifGenerationNotMatch => :query,
:ifMetagenerationMatch => :query,
:ifMetagenerationNotMatch => :query,
:kmsKeyName => :query,
:name => :query,
:predefinedAcl => :query,
:projection => :query,
:provisionalUserProject => :query,
:userProject => :query,
:body => :body
}
request =
Request.new()
|> Request.method(:post)
|> Request.url("/upload/storage/v1/b/{bucket}/o", %{
"bucket" => URI.encode(bucket, &URI.char_unreserved?/1)
})
|> Request.add_optional_params(optional_params_config, optional_params)
|> Request.library_version(@library_version)
connection
|> Connection.execute(request)
|> Response.decode(opts ++ [struct: %Object{}])
end
end