Implement cURL API #15

Merged
blek merged 7 commits from curlapi into 0.2-dev 2023-11-02 15:17:00 +01:00
4 changed files with 144 additions and 8 deletions
Showing only changes of commit 79ef0634f9 - Show all commits

View File

@ -1,8 +1,18 @@
use warp::{Filter, reply::Reply, reject::Rejection}; use askama::Template;
use warp::{Filter, reply::{Reply, html}, reject::Rejection};
use crate::web::state::SharedState; use crate::web::{state::SharedState, pages::CurlHelpPage, rejection::HttpReject};
pub async fn help(state: SharedState) -> Result<String, Rejection> { pub async fn help(state: SharedState, ua: String) -> Result<Box<dyn Reply>, Rejection> {
if ! ua.starts_with("curl/") {
let page = CurlHelpPage { conf: state.config.clone(), env: state.env.clone() };
return Ok(
Box::new(
html(page.render().map_err(|x| HttpReject::AskamaError(x))?)
)
)
}
let brand = format!( let brand = format!(
"{} \x1b[1m{}\x1b[0m {}", "{} \x1b[1m{}\x1b[0m {}",
@ -45,19 +55,20 @@ 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! \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 . The ToS can be found here: \x1b[34m{instance}/tos\x1b[0m .
{warns} {warns}"
"
); );
Ok(format!(" Ok(
Box::new(
format!("
\x1b[31m \x1b[0m \x1b[35m \x1b[0m \x1b[31m \x1b[0m \x1b[35m \x1b[0m
\x1b[32m\x1b[0m \x1b[95m \x1b[0m \x1b[32m\x1b[0m \x1b[95m \x1b[0m
\x1b[34m\x1b[0m \x1b[35m \x1b[0m \x1b[34m\x1b[0m \x1b[35m \x1b[0m
{brand} {brand}
{help} {help}
").into()) ").to_string())
)
} }
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 {
@ -67,5 +78,8 @@ pub fn get_routes(state: SharedState) -> impl Filter<Extract = impl Reply, Error
warp::any() warp::any()
.map(move || state.clone()) .map(move || state.clone())
) )
.and(
warp::header::<String>("user-agent")
)
.and_then(help) .and_then(help)
} }

View File

@ -88,6 +88,14 @@ pub struct ErrorPage {
pub link_text: Option<String> pub link_text: Option<String>
} }
#[derive(Template)]
#[template( path = "curlapi_help.html" )]
#[allow(dead_code)]
pub struct CurlHelpPage {
pub env: Env,
pub conf: Config
}
pub async fn uploaded(query: HashMap<String, String>, state: SharedState) -> Result<Html<String>, Rejection> { pub async fn uploaded(query: HashMap<String, String>, state: SharedState) -> Result<Html<String>, Rejection> {
if ! query.contains_key("file") { if ! query.contains_key("file") {

View File

@ -0,0 +1,13 @@
.code {
display: block;
padding: 1em;
border: 1px solid var(--header-sec-color);
border-radius: 12px;
font-family: monospace;
}
.code-inline {
display: inline;
font-family: monospace;
background: #00000010;
padding: 2px 4px;
}

View File

@ -0,0 +1,101 @@
{% extends "base.html" %}
{% block head %}
<link rel='stylesheet' href="/code.css" />
<link rel='stylesheet' href="/alert.css" />
<link rel='stylesheet' href="/js-only.css" />
<style>
.copy-btn { font-size: 70%; transform: translateY(-25%); display: inline-block }
</style>
{% endblock %}
{% block body %}
<div style="max-width:95vw;width:fit-content;margin:0 auto">
<h1 style="text-align:center">Curl API</h1>
<p>
blek! File has an API for uploading files via cURL.
To upload a file via cURL, follow these instructions:
</p>
<p>
To upload a file, POST it like this:
<a href="#" class="copy-btn" data-clipboard-text="curl -X POST {{env.instanceurl}}/curlapi/upload -F'file=@file.txt' -F'tos_consent=on'">
Copy!
</a>
</p>
<div class='code'>
curl -X POST {{env.instanceurl}}/curlapi/upload -F'file=@file.txt' -F'tos_consent=on'
</div>
<p>
To add a password, do it like this:
<a href="#" class="copy-btn" data-clipboard-text="curl -X POST {{env.instanceurl}}/curlapi/upload -F'file=@file.txt' -F'filename=uwu' -F'tos_consent=on' -F'named=on'">
Copy!
</a>
</p>
<div class='code'>
curl -X POST {{env.instanceurl}}/curlapi/upload -F'file=@file.txt' -F'filename=uwu' -F'tos_consent=on' -F'named=on'
</div>
<p>
Note that the
<span class='code-inline'>named=on</span>
switch is required.
Its needed because the curl API is basically a wrapper of
<a href="/">this</a>
HTML form.
</p>
<div class="alert danger">
<h1 class="alert-title">
Important
</h1>
<p class="alert-text">
Read the
<a href="/tos">Terms of Service</a>
<b>before</b>
uploading a file.
<br/>
You agree to them by adding the
<span class="code-inline">tos_consent=on</span>
switch.
</p>
</div>
<div class='alert blue'>
<h1 class='alert-title'>Web UI</h1>
<div class='alert-text'>
<p>
Hey, it looks like you are viewing this page from a browser!<br/>
You can use the Web UI as well to upload a file!
</p>
<p style='margin:32px 0'>
<a href='/' role='button' class='btn'>
Go to the web UI
</a>
</p>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="https://unpkg.com/clipboard@2/dist/clipboard.min.js"></script>
<script>
new ClipboardJS('.copy-btn');
{#- -#}
( {#- -#}
() => { {#- -#}
let btns = document.getElementsByClassName('copy-btn') {#- -#}
for (const button of btns) { {#- -#}
button.onclick = () => { {#- -#}
let old = button.innerHTML; {#- -#}
button.innerHTML = 'Copied!'; {#- -#}
setTimeout(() => { button.innerHTML = old }, 500); {#- -#}
} {#- -#}
} {#- -#}
} {#- -#}
)() {#- -#}
</script>
<script src='/js-only.js'></script>
{% endblock %}