Add endpoint to purge file from cache

This commit is contained in:
Valentin Brandl 2019-07-28 14:45:39 +02:00
parent 209ccb7093
commit 2c8e999f3f
No known key found for this signature in database
GPG Key ID: 30D341DD34118D7D
5 changed files with 104 additions and 1 deletions

60
backend/src/cdn.rs Normal file
View File

@ -0,0 +1,60 @@
use crate::statics::{self, CF_ZONE_IDENT};
use actix_web::{http::header, Error};
use awc::Client;
use futures::Future;
pub(crate) struct Cloudflare;
impl Cloudflare {
fn identifier() -> &'static str {
&CF_ZONE_IDENT
}
pub(crate) fn purge_cache(
client: &Client,
file: &str,
) -> impl Future<Item = bool, Error = Error> {
client
.post(format!(
"https://api.cloudflare.com/client/v4/zones/{}/purge_cache",
Self::identifier()
))
.header(header::USER_AGENT, statics::USER_AGENT.as_str())
.header("X-Auth-Email", Self::auth_email())
.header("X-Auth-Key", Self::auth_key())
.content_type("application/json")
.send_json(&CfPurgeRequest::singleton(file))
.from_err()
.and_then(|mut response| {
response
.json::<CfPurgeResponse>()
.map(|resp| resp.success)
.from_err()
})
}
fn auth_key() -> &'static str {
&statics::CF_AUTH_KEY
}
fn auth_email() -> &'static str {
&statics::CF_AUTH_USER
}
}
#[derive(Serialize)]
struct CfPurgeRequest {
files: Vec<String>,
}
impl CfPurgeRequest {
fn singleton(file: &str) -> Self {
let url = format!("https://{}/{}", statics::HOSTNAME.as_str(), file);
Self { files: vec![url] }
}
}
#[derive(Deserialize)]
struct CfPurgeResponse {
success: bool,
}

View File

@ -17,4 +17,16 @@ pub(crate) struct Opt {
#[structopt(long = "gh-secret")] #[structopt(long = "gh-secret")]
/// GitHub OAuth client secret /// GitHub OAuth client secret
pub(crate) github_secret: Option<String>, pub(crate) github_secret: Option<String>,
#[structopt(long = "cf-zone")]
/// Cloudflare zone identifier
pub(crate) cf_zone: Option<String>,
#[structopt(long = "cf-auth-key")]
/// Cloudflare auth key
pub(crate) cf_auth_key: Option<String>,
#[structopt(long = "cf-auth-user")]
/// Cloudflare auth user
pub(crate) cf_auth_user: Option<String>,
#[structopt(long = "hostname")]
/// Hostname
pub(crate) hostname: Option<String>,
} }

View File

@ -7,6 +7,7 @@ extern crate serde_derive;
#[macro_use] #[macro_use]
extern crate structopt; extern crate structopt;
mod cdn;
mod config; mod config;
mod data; mod data;
mod error; mod error;
@ -14,6 +15,7 @@ mod service;
mod statics; mod statics;
use crate::{ use crate::{
cdn::Cloudflare,
data::FilePath, data::FilePath,
error::Result, error::Result,
service::{Bitbucket, GitLab, Github, Service}, service::{Bitbucket, GitLab, Github, Service},
@ -94,6 +96,14 @@ fn favicon32() -> HttpResponse {
.body(FAVICON) .body(FAVICON)
} }
fn purge_cache(
client: web::Data<Client>,
data: web::Path<String>,
) -> impl Future<Item = HttpResponse, Error = Error> {
Cloudflare::purge_cache(&client, &data)
.map(|success| HttpResponse::Ok().body(success.to_string()))
}
fn main() -> Result<()> { fn main() -> Result<()> {
std::env::set_var("RUST_LOG", "actix_server=info,actix_web=trace"); std::env::set_var("RUST_LOG", "actix_server=info,actix_web=trace");
pretty_env_logger::init(); pretty_env_logger::init();
@ -116,6 +126,7 @@ fn main() -> Result<()> {
"/gitlab/{user}/{repo}/{commit}/{file:.*}", "/gitlab/{user}/{repo}/{commit}/{file:.*}",
web::get().to_async(handle_request::<GitLab>), web::get().to_async(handle_request::<GitLab>),
) )
.route("/purge/{path:.*}", web::delete().to_async(purge_cache))
.service(actix_files::Files::new("/", "public").index_file("index.html")) .service(actix_files::Files::new("/", "public").index_file("index.html"))
}) })
.workers(OPT.workers) .workers(OPT.workers)

View File

@ -204,7 +204,6 @@ impl Service for GitLab {
where where
S: 'static + Stream<Item = Bytes, Error = PayloadError>, S: 'static + Stream<Item = Bytes, Error = PayloadError>,
{ {
// "https://gitlab.com/api/v4/projects/{}/repository/branches/{}",
Box::new(match response.status() { Box::new(match response.status() {
StatusCode::OK => Box::new( StatusCode::OK => Box::new(
response response

View File

@ -1,4 +1,5 @@
use crate::{config::Opt, service::Github}; use crate::{config::Opt, service::Github};
use std::env;
use structopt::StructOpt; use structopt::StructOpt;
const VERSION: &str = env!("CARGO_PKG_VERSION"); const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -7,4 +8,24 @@ lazy_static! {
pub(crate) static ref USER_AGENT: String = format!("gitache/{}", VERSION); pub(crate) static ref USER_AGENT: String = format!("gitache/{}", VERSION);
pub(crate) static ref OPT: Opt = Opt::from_args(); pub(crate) static ref OPT: Opt = Opt::from_args();
pub(crate) static ref GITHUB_AUTH_QUERY: String = Github::auth_query().unwrap_or_default(); pub(crate) static ref GITHUB_AUTH_QUERY: String = Github::auth_query().unwrap_or_default();
pub(crate) static ref CF_ZONE_IDENT: String = OPT
.cf_zone
.clone()
.or_else(|| env::var("CF_ZONE_IDENT").ok())
.expect("Cloudflare zone identifier not set");
pub(crate) static ref CF_AUTH_KEY: String = OPT
.cf_auth_key
.clone()
.or_else(|| env::var("CF_AUTH_KEY").ok())
.expect("Cloudflare auth key not set");
pub(crate) static ref CF_AUTH_USER: String = OPT
.cf_auth_user
.clone()
.or_else(|| env::var("CF_AUTH_USER").ok())
.expect("Cloudflare auth user not set");
pub(crate) static ref HOSTNAME: String = OPT
.hostname
.clone()
.or_else(|| env::var("GITACHE_HOSTNAME").ok())
.unwrap_or_else(|| "gitcdn.tk".to_string());
} }