9 unstable releases (3 breaking)
0.6.1 | Feb 23, 2024 |
---|---|
0.6.0 | Feb 19, 2024 |
0.5.2 | Feb 11, 2024 |
0.5.1 | Jan 27, 2024 |
0.3.1 | Jan 20, 2024 |
#297 in Authentication
Used in drive-v3-macros
420KB
5.5K
SLoC
drive-v3
A Rust library to send request to the Google Drive API v3.
This library includes functions to call all Google Drive API v3 present in Google's documentation as of the date of the latest release.
Usage
Setup
Before using Google Drive's API you need to enable it on a Google Cloud project.
This is free and you can follow these steps to enable the API.
After you complete the Authorize credentials for a desktop application section, you can us the saved client_secrets.json
file to authorize this library.
Getting credentials
Before you start making calls to Google's API, you first need to get some valid Credentials
.
For this you will need your client_secrets.json
file and the scopes that you plan on using. For help on selecting scopes you can read Google's choose scopes guide.
With these elements you can call Credentials::from_client_secrets_file
to prompt you to authorize your app via the browser:
use drive_v3::Credentials;
// This is the file downloaded in the Setup section
let client_secrets_path = "my_client_secrets.json";
// The OAuth scopes you need
let scopes: [&'static str; 2] = [
"https://www.googleapis.com/auth/drive.metadata.readonly",
"https://www.googleapis.com/auth/drive.file",
];
let credentials = Credentials::from_client_secrets_file(&client_secrets_path, &scopes)?;
Great! now you have valid credentials to make requests to Google's API, however these credentials will expire after some time, at which point you will have to request them again.
To avoid having to authorize using the browser every time they expire, you should save them to your system:
credentials.store("very/secure/path/to/my/credentials.json")?;
Now you don't need to worry about requesting new credentials every time, instead you can simply check if they have expired and refresh them if necessary:
use drive_v3::Credentials;
// Path where the credentials were stored
let credentials_storage_path = "very/secure/path/to/my/credentials.json";
// The OAuth scopes you need
let scopes: [&'static str; 2] = [
"https://www.googleapis.com/auth/drive.metadata.readonly",
"https://www.googleapis.com/auth/drive.file",
];
let mut stored_credentials = Credentials::from_file(&credentials_storage_path, &scopes)?;
// Refresh the credentials if they have expired
if !stored_credentials.are_valid() {
stored_credentials.refresh()?;
// Save them so we don't have to refresh them every time
stored_credentials.store(&credentials_storage_path)?;
}
Making requests
Now that we have valid Credentials
, we can start making requests. For this we need to create a Drive
.
A Drive
is the representation of the API itself, with it we can make request to any endpoint in Google's API.
To create it we simply need to pass it the Credentials
:
use drive_v3::Drive;
let drive = Drive::new(&credentials);
And then make the requests you want, for example list the files in a Drive:
let file_list = drive.files.list()
.fields("files(name, id, mimeType)") // Set what fields will be returned
.q("name = 'file_im_looking_for' and not trashed") // search for specific files
.execute()?;
if let Some(files) = file_list.files {
for file in &files {
println!("{}", file);
}
}
As you can see the files.list
function uses the builder pattern, this allows you to specify the query parameters that you need in your request.
Thanks to this pattern you can search the documentation of a specific resource in Google's reference and use any of its query parameters which will have corresponding functions with the same name (the only difference being that the functions will use snake_case
instead of camelCase
).
Request responses
As seen in the previous section to get a response from one of the Drive
's resources you have to call .execute()
this will return a Result
which will either be an Error
or the response from Google's API.
The type of the response will depend on the request, it could return nothing, an object like a File
or a Comment
or a vector of bytes. You can check the return types in each request's documentation.
Objects
Some request will either return an object
or need one for the request, an object
is a representation of the types in Google's API.
All objects
in drive-v3
have the same structure, a struct with fields that are all an Option<T>
. The reason for this is that not all of the fields of an object
will be populated by a request or needed to make one.
For example the File
object has 60 different fields, it would be impractical to have to specify all fields when you want to create a new file. So instead you can just populate the fields that you actually want to set and leave the rest as None
. This is easy since all objects implement the default
trait:
use drive_v3::objects::File;
let file = File {
name: Some( "my-file.txt".to_string() ),
mime_type: Some( "text/plain".to_string() ),
description: Some( "this is a text file".to_string() )
..Default::default()
};
And when it comes to responses, all requests have the function fields()
which you can set to return the exact fields you need, improving performance in your method call. Check Google's documentation for more info on the fields parameter.
More examples
Upload a new file to a Drive:
use drive_v3::objects::{File, UploadType};
// Set what information the uploaded file wil have
let metadata = File {
name: Some( "my-new-file.txt".to_string() ),
mime_type: Some( "text/plain".to_string() ),
..Default::default()
};
// You can set a callback that will be called when a resumable upload progresses
fn progress_callback( total_bytes: usize, uploaded_bytes: usize ) {
println!("Uploaded {} bytes, out of a total of {}.", uploaded_bytes, total_bytes);
}
let my_new_file = drive.files.create()
.upload_type(UploadType::Resumable)
.callback(progress_callback)
.metadata(&metadata)
.content_source("path/to/file.txt")
.execute()?;
assert_eq!(my_new_file.name, metadata.name);
assert_eq!(my_new_file.mime_type, metadata.mime_type);
Download a file from Drive:
let file_id = "some-file-id";
let file_bytes = drive.files.get_media(&file_id)
// .save_to("my_downloaded_file.txt") // Save the contents to a path
.execute()?;
let content = String::from_utf8_lossy(&file_bytes);
println!("file content: {}", content);
Get information about a Drive:
let information = drive.about.get()
.fields("storageQuota, canCreateDrives, appInstalled")
.execute()?;
println!("look at all this information:\n{}", information);
Contributing
Pull requests are welcome. For major changes, please open an issue first.
License
MIT
Dependencies
~9–22MB
~321K SLoC