Implement cURL API #15
|
@ -84,3 +84,7 @@ sudo_delete=false
|
||||||
# Whether /api/upload is enabled
|
# Whether /api/upload is enabled
|
||||||
# It is not recommended to enable it if API key auth is not enabled
|
# It is not recommended to enable it if API key auth is not enabled
|
||||||
upload=false
|
upload=false
|
||||||
|
|
||||||
|
# Whether curlapi is enabled
|
||||||
|
# curl {url}/curlapi/help for more info
|
||||||
|
curlapi=true
|
||||||
|
|
|
@ -112,6 +112,10 @@ pub struct APISettings {
|
||||||
/// Whether /api/upload is enabled
|
/// Whether /api/upload is enabled
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub upload: bool,
|
pub upload: bool,
|
||||||
|
|
||||||
|
/// Whether curlapi is enabled
|
||||||
|
#[serde(default)]
|
||||||
|
pub curlapi: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for APISettings {
|
impl Default for APISettings {
|
||||||
|
@ -123,7 +127,8 @@ impl Default for APISettings {
|
||||||
get_all_own_only: true,
|
get_all_own_only: true,
|
||||||
delete: false,
|
delete: false,
|
||||||
sudo_delete: false,
|
sudo_delete: false,
|
||||||
upload: false
|
upload: false,
|
||||||
|
curlapi: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@ use warp::{Filter, reply::Reply, reject::Rejection};
|
||||||
use super::state::SharedState;
|
use super::state::SharedState;
|
||||||
|
|
||||||
mod upload;
|
mod upload;
|
||||||
|
mod help;
|
||||||
|
|
||||||
pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||||
upload::get_routes(state)
|
upload::get_routes(state.clone())
|
||||||
|
.or(help::get_routes(state))
|
||||||
}
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
use warp::{Filter, reply::Reply, reject::Rejection};
|
||||||
|
|
||||||
|
use crate::web::state::SharedState;
|
||||||
|
|
||||||
|
pub async fn help(state: SharedState) -> Result<String, Rejection> {
|
||||||
|
|
||||||
|
let brand = format!(
|
||||||
|
"{} \x1b[1m{}\x1b[0m {}",
|
||||||
|
state.config.brand.instance_emoji,
|
||||||
|
state.config.brand.instance_name,
|
||||||
|
{
|
||||||
|
if state.config.brand.instance_name != "blek! File" {
|
||||||
|
"\n\x1b[90mPowered by blek! File\x1b[0m"
|
||||||
|
} else { "" }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut warns: String = String::new();
|
||||||
|
if ! state.config.api.curlapi {
|
||||||
|
warns += "\x1b[1;31mWarning: curl API is disabled on this instance.\nYou can use the web UI to upload files.\x1b[0m\n\n"
|
||||||
|
}
|
||||||
|
if ! state.config.files.allow_uploads {
|
||||||
|
warns += {
|
||||||
|
format!(
|
||||||
|
"\x1b[1;31mWarning: all uploads are disabled on this instance{}\x1b[0m",
|
||||||
|
{
|
||||||
|
if let Some(reason) = state.config.files.upload_disable_reason {
|
||||||
|
format!(" for this reason:\n\"{}\"", reason)
|
||||||
|
} else { ".".to_string() }
|
||||||
|
}
|
||||||
|
).as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let instance = state.env.instanceurl;
|
||||||
|
let help =
|
||||||
|
format!(
|
||||||
|
"To upload a new file, you can POST it like this:
|
||||||
|
\x1b[32mcurl\x1b[0m \x1b[33m-X POST\x1b[0m \x1b[34m{instance}/curlapi/upload\x1b[0m \x1b[33m-F'file=@file.txt'\x1b[0m \x1b[33m-F'tos_consent=on'\x1b[0m
|
||||||
|
You can also add a password:
|
||||||
|
\x1b[32mcurl\x1b[0m \x1b[33m-X POST\x1b[0m \x1b[34m{instance}/curlapi/upload\x1b[0m \x1b[33m-F'file=@file.txt'\x1b[0m \x1b[33m-F'filename=uwu'\x1b[0m \x1b[33m-F'tos_consent=on'\x1b[0m \x1b[33m-F'named=on'\x1b[0m
|
||||||
|
The `named=on` switch is neede because this API is basically
|
||||||
|
the HTML used at the regular web UI form wrapped into this URL
|
||||||
|
|
||||||
|
\x1b[1;32mIMPORTANT:\x1b[0m Read the terms of service \x1b[1mbefore\x1b[0m uploading the file!
|
||||||
|
The ToS can be found here: \x1b[34m{instance}/tos\x1b[0m .
|
||||||
|
|
||||||
|
{warns}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(format!("
|
||||||
|
\x1b[31m┓ ╻\x1b[0m \x1b[35m┏┓•┓ \x1b[0m
|
||||||
|
\x1b[32m┣┓┃\x1b[0m \x1b[95m┣ ┓┃┏┓\x1b[0m
|
||||||
|
\x1b[34m┗┛•\x1b[0m \x1b[35m┻ ┗┗┗━\x1b[0m
|
||||||
|
|
||||||
|
{brand}
|
||||||
|
|
||||||
|
{help}
|
||||||
|
").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||||
|
warp::any()
|
||||||
|
.and(warp::path!("curlapi" / "help"))
|
||||||
|
.and(
|
||||||
|
warp::any()
|
||||||
|
.map(move || state.clone())
|
||||||
|
)
|
||||||
|
.and_then(help)
|
||||||
|
}
|
|
@ -111,7 +111,7 @@ pub async fn upload(form: FormData, ip: Option<IpAddr>, state: SharedState) -> R
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||||
warp::any()
|
warp::post()
|
||||||
.and(warp::path!("curlapi" / "upload"))
|
.and(warp::path!("curlapi" / "upload"))
|
||||||
.and(warp::multipart::form())
|
.and(warp::multipart::form())
|
||||||
.and(real_ip(vec![state.env.proxy_addr]))
|
.and(real_ip(vec![state.env.proxy_addr]))
|
||||||
|
|
Loading…
Reference in New Issue