mirror of
https://github.com/timvisee/ffsend.git
synced 2025-10-03 09:39:15 +02:00
Add exists API action to check file ability and protection
This commit is contained in:
parent
887e09ebd2
commit
349e62ed1c
3 changed files with 130 additions and 0 deletions
119
api/src/action/exists.rs
Normal file
119
api/src/action/exists.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
// TODO: define redirect policy
|
||||
|
||||
use reqwest::{Client, StatusCode};
|
||||
|
||||
use ext::status_code::StatusCodeExt;
|
||||
use file::remote_file::RemoteFile;
|
||||
|
||||
/// The HTTP status code that is returned for expired files.
|
||||
const FILE_EXPIRED_STATUS: StatusCode = StatusCode::NotFound;
|
||||
|
||||
/// An action to check whether a remote file exists.
|
||||
/// This aciton returns an `ExistsResponse`, that defines whether the file
|
||||
/// exists, and whether it is protected by a password.
|
||||
pub struct Exists<'a> {
|
||||
/// The remote file to check.
|
||||
file: &'a RemoteFile,
|
||||
}
|
||||
|
||||
impl<'a> Exists<'a> {
|
||||
/// Construct a new exists action.
|
||||
pub fn new(file: &'a RemoteFile) -> Self {
|
||||
Self {
|
||||
file,
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoke the exists action.
|
||||
pub fn invoke(self, client: &Client) -> Result<ExistsResponse, Error> {
|
||||
self.check_exists(&client)
|
||||
}
|
||||
|
||||
/// Send a request to check whether the file exists
|
||||
fn check_exists(&self, client: &Client) -> Result<ExistsResponse, Error> {
|
||||
// Get the download url, and parse the nonce
|
||||
let exists_url = self.file.api_exists_url();
|
||||
let mut response = client.get(exists_url)
|
||||
.send()
|
||||
.map_err(|_| Error::Request)?;
|
||||
|
||||
// Validate the status code
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
// Handle expired files
|
||||
if status == FILE_EXPIRED_STATUS {
|
||||
return Ok(ExistsResponse::new(false, false));
|
||||
} else {
|
||||
return Err(Error::RequestStatus(status, status.err_text()).into());
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
let response = response.json::<ExistsResponse>()
|
||||
.map_err(|_| Error::Malformed)?;
|
||||
|
||||
// TODO: fetch the metadata nonce from the response headers
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
}
|
||||
|
||||
/// The exists response.
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ExistsResponse {
|
||||
/// Whether the file exists.
|
||||
#[serde(skip)]
|
||||
exists: bool,
|
||||
|
||||
/// Whether this file requires a password.
|
||||
#[serde(rename = "password")]
|
||||
has_password: bool,
|
||||
}
|
||||
|
||||
impl ExistsResponse {
|
||||
/// Construct a new response.
|
||||
pub fn new(exists: bool, has_password: bool) -> Self {
|
||||
ExistsResponse {
|
||||
exists,
|
||||
has_password,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the remote file exists on the server.
|
||||
pub fn exists(&self) -> bool {
|
||||
self.exists
|
||||
}
|
||||
|
||||
/// Whether the remote file is protected by a password.
|
||||
pub fn has_password(&self) -> bool {
|
||||
self.has_password
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ExistsResponse {
|
||||
fn default() -> Self {
|
||||
ExistsResponse {
|
||||
exists: false,
|
||||
has_password: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Fail, Debug)]
|
||||
pub enum Error {
|
||||
/// Sending the request to check whether the file exists failed.
|
||||
#[fail(display = "Failed to send request whether the file exists")]
|
||||
Request,
|
||||
|
||||
/// The response for checking whether the file exists indicated an error
|
||||
/// and wasn't successful.
|
||||
#[fail(display = "Bad HTTP response '{}' while requesting whether the file exists", _1)]
|
||||
RequestStatus(StatusCode, String),
|
||||
|
||||
/// The response from the server when checking if the file exists was
|
||||
/// malformed.
|
||||
/// Maybe the server responded with a new format that isn't supported yet
|
||||
/// by this client.
|
||||
#[fail(display = "Received malformed authentication nonce")]
|
||||
Malformed,
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
pub mod download;
|
||||
pub mod exists;
|
||||
pub mod info;
|
||||
pub mod metadata;
|
||||
pub mod params;
|
||||
|
|
|
@ -229,6 +229,16 @@ impl RemoteFile {
|
|||
|
||||
url
|
||||
}
|
||||
|
||||
/// Get the API exists URL of the file.
|
||||
pub fn api_exists_url(&self) -> Url {
|
||||
// Get the share URL, and add the secret fragment
|
||||
let mut url = self.url.clone();
|
||||
url.set_path(format!("/api/exists/{}", self.id).as_str());
|
||||
url.set_fragment(None);
|
||||
|
||||
url
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue