gatherer: use one shared http_client

This commit is contained in:
Astro 2023-08-09 00:05:26 +02:00
parent 50c6d29c71
commit db8874467e
6 changed files with 28 additions and 12 deletions

View File

@ -21,5 +21,5 @@ askama = "0.11"
metrics = "0.20" metrics = "0.20"
metrics-util = "0.14" metrics-util = "0.14"
metrics-exporter-prometheus = "0.11" metrics-exporter-prometheus = "0.11"
reqwest = "0.11" reqwest = { version = "0.11", features = ["json", "trust-dns"] }
urlencoding = "1" urlencoding = "1"

View File

@ -39,6 +39,7 @@ type Languages = Vec<String>;
pub struct ServerState { pub struct ServerState {
store: Store, store: Store,
db: Database, db: Database,
http_client: reqwest::Client,
} }
impl ServerState { impl ServerState {
@ -209,6 +210,7 @@ pub async fn start(
listen_port: u16, listen_port: u16,
store: Store, store: Store,
db: Database, db: Database,
http_client: reqwest::Client,
firehose_factory: FirehoseFactory, firehose_factory: FirehoseFactory,
recorder: PrometheusHandle, recorder: PrometheusHandle,
) { ) {
@ -222,7 +224,7 @@ pub async fn start(
.route("/token/donate", get(token_donate::get_token_donate).post(token_donate::post_token_donate)) .route("/token/donate", get(token_donate::get_token_donate).post(token_donate::post_token_donate))
.route("/token/collect/:host", get(token_collect::get_token_collect)) .route("/token/collect/:host", get(token_collect::get_token_collect))
.route("/token/thanks", get(token_collect::get_token_thanks)) .route("/token/thanks", get(token_collect::get_token_thanks))
.layer(Extension(ServerState { store, db })) .layer(Extension(ServerState { store, db, http_client }))
.layer(Extension(firehose_factory)) .layer(Extension(firehose_factory))
.route("/metrics", get(|| async move { .route("/metrics", get(|| async move {
recorder.render().into_response() recorder.render().into_response()

View File

@ -10,7 +10,12 @@ use crate::{
oauth, oauth,
}; };
async fn collect_token(db: Database, host: &str, code: String) -> Result<(), String> { async fn collect_token(
db: Database,
http_client: &reqwest::Client,
host: &str,
code: String,
) -> Result<(), String> {
// try a few registered apps until one works // try a few registered apps until one works
for (client_id, client_secret) in db.get_apps(&host).await for (client_id, client_secret) in db.get_apps(&host).await
.map_err(|e| format!("{}", e))? .map_err(|e| format!("{}", e))?
@ -19,7 +24,7 @@ async fn collect_token(db: Database, host: &str, code: String) -> Result<(), Str
client_id, client_id,
client_secret, client_secret,
}; };
match app.obtain_token(&host, code.clone()).await { match app.obtain_token(http_client, &host, code.clone()).await {
Ok(token) => { Ok(token) => {
db.add_token(&host, &app.client_id, &token).await db.add_token(&host, &app.client_id, &token).await
.expect("db.add_token"); .expect("db.add_token");
@ -43,11 +48,11 @@ pub struct OAuthCode {
} }
pub async fn get_token_collect( pub async fn get_token_collect(
Extension(ServerState { db, .. }): Extension<ServerState>, Extension(ServerState { db, http_client, .. }): Extension<ServerState>,
extract::Path(host): extract::Path<String>, extract::Path(host): extract::Path<String>,
extract::Query(OAuthCode { code }): extract::Query<OAuthCode>, extract::Query(OAuthCode { code }): extract::Query<OAuthCode>,
) -> impl IntoResponse { ) -> impl IntoResponse {
match collect_token(db, &host, code.clone()).await { match collect_token(db, &http_client, &host, code.clone()).await {
Ok(()) => Ok(()) =>
( (
StatusCode::SEE_OTHER, StatusCode::SEE_OTHER,

View File

@ -42,7 +42,7 @@ impl IntoResponse for PostTokenDonateResult {
} }
pub async fn post_token_donate( pub async fn post_token_donate(
Extension(ServerState { db, .. }): Extension<ServerState>, Extension(ServerState { db, http_client, .. }): Extension<ServerState>,
extract::Form(form): extract::Form<TokenDonateForm>, extract::Form(form): extract::Form<TokenDonateForm>,
) -> PostTokenDonateResult { ) -> PostTokenDonateResult {
let apps = db.get_apps(&form.instance).await let apps = db.get_apps(&form.instance).await
@ -57,7 +57,7 @@ pub async fn post_token_donate(
}; };
} else { } else {
// register a new app with this instance // register a new app with this instance
app = match oauth::Application::register(&form.instance).await { app = match oauth::Application::register(&http_client, &form.instance).await {
Ok(app) => app, Ok(app) => app,
Err(e) => { Err(e) => {
tracing::error!("Canont register OAuth app: {}", e); tracing::error!("Canont register OAuth app: {}", e);

View File

@ -26,6 +26,16 @@ async fn main() {
.install_recorder() .install_recorder()
.unwrap(); .unwrap();
let http_client = reqwest::Client::builder()
.timeout(Duration::from_secs(10))
.pool_max_idle_per_host(0)
.user_agent(
format!("{}/{} (+https://fedi.buzz/)", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"))
)
.trust_dns(true)
.build()
.expect("reqwest::Client");
cave::systemd::status("Connecting to database"); cave::systemd::status("Connecting to database");
let db = cave::db::Database::connect(&config.database).await; let db = cave::db::Database::connect(&config.database).await;
cave::systemd::status("Starting redis client"); cave::systemd::status("Starting redis client");
@ -37,6 +47,7 @@ async fn main() {
config.listen_port, config.listen_port,
store, store,
db, db,
http_client,
firehose_factory, firehose_factory,
recorder, recorder,
); );

View File

@ -31,7 +31,7 @@ pub struct Application {
const SCOPES: &str = "read:statuses"; const SCOPES: &str = "read:statuses";
impl Application { impl Application {
pub async fn register(host: &str) -> Result<Self, reqwest::Error> { pub async fn register(client: &reqwest::Client, host: &str) -> Result<Self, reqwest::Error> {
let url = format!("https://{}/api/v1/apps", host); let url = format!("https://{}/api/v1/apps", host);
let form = AppRegistration { let form = AppRegistration {
client_name: "#FediBuzz".to_string(), client_name: "#FediBuzz".to_string(),
@ -39,7 +39,6 @@ impl Application {
redirect_uris: Self::generate_redirect_url(host), redirect_uris: Self::generate_redirect_url(host),
scopes: SCOPES.to_string(), scopes: SCOPES.to_string(),
}; };
let client = reqwest::Client::new();
let res = client.post(url) let res = client.post(url)
.form(&form) .form(&form)
.send() .send()
@ -63,7 +62,7 @@ impl Application {
) )
} }
pub async fn obtain_token(&self, host: &str, code: String) -> Result<String, reqwest::Error> { pub async fn obtain_token(&self, client: &reqwest::Client, host: &str, code: String) -> Result<String, reqwest::Error> {
let url = format!("https://{}/oauth/token", host); let url = format!("https://{}/oauth/token", host);
let form = TokenRequest { let form = TokenRequest {
grant_type: "authorization_code".to_string(), grant_type: "authorization_code".to_string(),
@ -73,7 +72,6 @@ impl Application {
redirect_uri: Self::generate_redirect_url(host), redirect_uri: Self::generate_redirect_url(host),
code, code,
}; };
let client = reqwest::Client::new();
let res: TokenResult = client.post(url) let res: TokenResult = client.post(url)
.form(&form) .form(&form)
.send() .send()