Fix OAuth token fetch failures from ad-hoc response persistence (#399)

This commit is contained in:
Gregory Schier
2026-02-19 14:04:34 -08:00
committed by GitHub
parent 7b73401dcf
commit 5a184c1b83
3 changed files with 93 additions and 76 deletions
+33 -24
View File
@@ -24,7 +24,7 @@ use yaak_models::models::{
HttpResponseEvent, HttpResponseHeader, HttpResponseState, ProxySetting, ProxySettingAuth, HttpResponseEvent, HttpResponseHeader, HttpResponseState, ProxySetting, ProxySettingAuth,
}; };
use yaak_models::query_manager::QueryManager; use yaak_models::query_manager::QueryManager;
use yaak_models::util::UpdateSource; use yaak_models::util::{UpdateSource, generate_prefixed_id};
use yaak_plugins::events::{ use yaak_plugins::events::{
CallHttpAuthenticationRequest, HttpHeader, PluginContext, RenderPurpose, CallHttpAuthenticationRequest, HttpHeader, PluginContext, RenderPurpose,
}; };
@@ -488,11 +488,16 @@ pub async fn send_http_request<T: TemplateCallback>(
response.elapsed = 0; response.elapsed = 0;
response.elapsed_headers = 0; response.elapsed_headers = 0;
response.elapsed_dns = 0; response.elapsed_dns = 0;
let persist_response = !response.request_id.is_empty();
if persist_response {
response = params response = params
.query_manager .query_manager
.connect() .connect()
.upsert_http_response(&response, &params.update_source, params.blob_manager) .upsert_http_response(&response, &params.update_source, params.blob_manager)
.map_err(SendHttpRequestError::PersistResponse)?; .map_err(SendHttpRequestError::PersistResponse)?;
} else if response.id.is_empty() {
response.id = generate_prefixed_id("rs");
}
let (event_tx, mut event_rx) = let (event_tx, mut event_rx) =
mpsc::channel::<SenderHttpResponseEvent>(HTTP_EVENT_CHANNEL_CAPACITY); mpsc::channel::<SenderHttpResponseEvent>(HTTP_EVENT_CHANNEL_CAPACITY);
@@ -503,6 +508,7 @@ pub async fn send_http_request<T: TemplateCallback>(
let emit_events_to = params.emit_events_to.clone(); let emit_events_to = params.emit_events_to.clone();
let event_handle = tokio::spawn(async move { let event_handle = tokio::spawn(async move {
while let Some(event) = event_rx.recv().await { while let Some(event) = event_rx.recv().await {
if persist_response {
let db_event = HttpResponseEvent::new( let db_event = HttpResponseEvent::new(
&event_response_id, &event_response_id,
&event_workspace_id, &event_workspace_id,
@@ -514,6 +520,7 @@ pub async fn send_http_request<T: TemplateCallback>(
{ {
warn!("Failed to persist HTTP response event: {}", err); warn!("Failed to persist HTTP response event: {}", err);
} }
}
if let Some(tx) = emit_events_to.as_ref() { if let Some(tx) = emit_events_to.as_ref() {
let _ = tx.try_send(event); let _ = tx.try_send(event);
@@ -531,6 +538,7 @@ pub async fn send_http_request<T: TemplateCallback>(
Ok(response) => response, Ok(response) => response,
Err(err) => { Err(err) => {
persist_cookie_jar(params.query_manager, cookie_jar.as_mut(), cookie_store.as_ref())?; persist_cookie_jar(params.query_manager, cookie_jar.as_mut(), cookie_store.as_ref())?;
if persist_response {
let _ = persist_response_error( let _ = persist_response_error(
params.query_manager, params.query_manager,
params.blob_manager, params.blob_manager,
@@ -540,6 +548,7 @@ pub async fn send_http_request<T: TemplateCallback>(
err.to_string(), err.to_string(),
request_started_url, request_started_url,
); );
}
if let Err(join_err) = event_handle.await { if let Err(join_err) = event_handle.await {
warn!("Failed to join response event task: {}", join_err); warn!("Failed to join response event task: {}", join_err);
} }
@@ -548,11 +557,7 @@ pub async fn send_http_request<T: TemplateCallback>(
}; };
let headers_elapsed = duration_to_i32(started_at.elapsed()); let headers_elapsed = duration_to_i32(started_at.elapsed());
response = params let connected_response = HttpResponse {
.query_manager
.connect()
.upsert_http_response(
&HttpResponse {
state: HttpResponseState::Connected, state: HttpResponseState::Connected,
elapsed_headers: headers_elapsed, elapsed_headers: headers_elapsed,
status: i32::from(http_response.status), status: i32::from(http_response.status),
@@ -563,25 +568,28 @@ pub async fn send_http_request<T: TemplateCallback>(
headers: http_response headers: http_response
.headers .headers
.iter() .iter()
.map(|(name, value)| HttpResponseHeader { .map(|(name, value)| HttpResponseHeader { name: name.clone(), value: value.clone() })
name: name.clone(),
value: value.clone(),
})
.collect(), .collect(),
request_headers: http_response request_headers: http_response
.request_headers .request_headers
.iter() .iter()
.map(|(name, value)| HttpResponseHeader { .map(|(name, value)| HttpResponseHeader { name: name.clone(), value: value.clone() })
name: name.clone(),
value: value.clone(),
})
.collect(), .collect(),
..response ..response
}, };
if persist_response {
response = params
.query_manager
.connect()
.upsert_http_response(
&connected_response,
&params.update_source, &params.update_source,
params.blob_manager, params.blob_manager,
) )
.map_err(SendHttpRequestError::PersistResponse)?; .map_err(SendHttpRequestError::PersistResponse)?;
} else {
response = connected_response;
}
let (response_body, body_stats) = let (response_body, body_stats) =
http_response.bytes().await.map_err(SendHttpRequestError::ReadResponseBody)?; http_response.bytes().await.map_err(SendHttpRequestError::ReadResponseBody)?;
@@ -598,11 +606,7 @@ pub async fn send_http_request<T: TemplateCallback>(
SendHttpRequestError::WriteResponseBody { path: body_path.clone(), source } SendHttpRequestError::WriteResponseBody { path: body_path.clone(), source }
})?; })?;
response = params let final_response = HttpResponse {
.query_manager
.connect()
.upsert_http_response(
&HttpResponse {
body_path: Some(body_path.to_string_lossy().to_string()), body_path: Some(body_path.to_string_lossy().to_string()),
content_length: Some(usize_to_i32(response_body.len())), content_length: Some(usize_to_i32(response_body.len())),
content_length_compressed: Some(u64_to_i32(body_stats.size_compressed)), content_length_compressed: Some(u64_to_i32(body_stats.size_compressed)),
@@ -610,11 +614,16 @@ pub async fn send_http_request<T: TemplateCallback>(
elapsed_headers: headers_elapsed, elapsed_headers: headers_elapsed,
state: HttpResponseState::Closed, state: HttpResponseState::Closed,
..response ..response
}, };
&params.update_source, if persist_response {
params.blob_manager, response = params
) .query_manager
.connect()
.upsert_http_response(&final_response, &params.update_source, params.blob_manager)
.map_err(SendHttpRequestError::PersistResponse)?; .map_err(SendHttpRequestError::PersistResponse)?;
} else {
response = final_response;
}
if let Err(join_err) = event_handle.await { if let Err(join_err) = event_handle.await {
warn!("Failed to join response event task: {}", join_err); warn!("Failed to join response event task: {}", join_err);
@@ -61,6 +61,10 @@ export async function fetchAccessToken(
console.log('[oauth2] Got access token response', resp.status); console.log('[oauth2] Got access token response', resp.status);
if (resp.error) {
throw new Error(`Failed to fetch access token: ${resp.error}`);
}
const body = resp.bodyPath ? readFileSync(resp.bodyPath, 'utf8') : ''; const body = resp.bodyPath ? readFileSync(resp.bodyPath, 'utf8') : '';
if (resp.status < 200 || resp.status >= 300) { if (resp.status < 200 || resp.status >= 300) {
@@ -71,6 +71,10 @@ export async function getOrRefreshAccessToken(
httpRequest.authenticationType = 'none'; // Don't inherit workspace auth httpRequest.authenticationType = 'none'; // Don't inherit workspace auth
const resp = await ctx.httpRequest.send({ httpRequest }); const resp = await ctx.httpRequest.send({ httpRequest });
if (resp.error) {
throw new Error(`Failed to refresh access token: ${resp.error}`);
}
if (resp.status >= 400 && resp.status < 500) { if (resp.status >= 400 && resp.status < 500) {
// Client errors (4xx) indicate the refresh token is invalid, expired, or revoked // Client errors (4xx) indicate the refresh token is invalid, expired, or revoked
// Delete the token and return null to trigger a fresh authorization flow // Delete the token and return null to trigger a fresh authorization flow