diff --git a/backend/windmill-api/src/jobs.rs b/backend/windmill-api/src/jobs.rs index 76886cd824..bb03ad6b50 100644 --- a/backend/windmill-api/src/jobs.rs +++ b/backend/windmill-api/src/jobs.rs @@ -17,11 +17,11 @@ use axum::{ extract::{FromRequest, Json, Path, Query}, response::{IntoResponse, Response}, routing::{get, post}, - Extension, Router, + Extension, Form, RequestExt, Router, }; use base64::Engine; use hmac::Mac; -use hyper::{http, HeaderMap, Request, StatusCode}; +use hyper::{header::CONTENT_TYPE, http, HeaderMap, Request, StatusCode}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sql_builder::{prelude::*, quote, SqlBuilder}; use sqlx::{query_scalar, types::Uuid, FromRow, Postgres, Transaction}; @@ -1217,6 +1217,40 @@ struct PreviewFlow { args: Option>, } +pub struct JsonOrForm(T); + +#[axum::async_trait] +impl FromRequest for JsonOrForm +where + S: Send + Sync, + Json: FromRequest<(), axum::body::Body>, + Form: FromRequest<(), axum::body::Body>, + T: 'static, +{ + type Rejection = Response; + + async fn from_request( + req: Request, + _state: &S, + ) -> Result { + let content_type_header = req.headers().get(CONTENT_TYPE); + let content_type = content_type_header.and_then(|value| value.to_str().ok()); + + if let Some(content_type) = content_type { + if content_type.starts_with("application/json") { + let Json(payload) = req.extract().await.map_err(IntoResponse::into_response)?; + return Ok(Self(payload)); + } + + if content_type.starts_with("application/x-www-form-urlencoded") { + let Form(payload) = req.extract().await.map_err(IntoResponse::into_response)?; + return Ok(Self(payload)); + } + } + + Err(StatusCode::UNSUPPORTED_MEDIA_TYPE.into_response()) + } +} pub struct QueryOrBody(pub Option); #[axum::async_trait] @@ -1270,7 +1304,7 @@ pub async fn run_flow_by_path( Path((w_id, flow_path)): Path<(String, StripPath)>, Query(run_query): Query, headers: HeaderMap, - Json(args): Json>>, + JsonOrForm(args): JsonOrForm>>, ) -> error::Result<(StatusCode, String)> { let flow_path = flow_path.to_path(); let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); @@ -1306,7 +1340,7 @@ pub async fn run_job_by_path( Path((w_id, script_path)): Path<(String, StripPath)>, Query(run_query): Query, headers: HeaderMap, - Json(args): Json>>, + JsonOrForm(args): JsonOrForm>>, ) -> error::Result<(StatusCode, String)> { let script_path = script_path.to_path(); let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); @@ -1551,7 +1585,7 @@ pub async fn run_wait_result_job_by_path( Path((w_id, script_path)): Path<(String, StripPath)>, Query(run_query): Query, headers: HeaderMap, - Json(args): Json>>, + JsonOrForm(args): JsonOrForm>>, ) -> error::JsonResult { check_queue_too_long(db, QUEUE_LIMIT_WAIT_RESULT.or(run_query.queue_limit)).await?; let script_path = script_path.to_path(); @@ -1600,7 +1634,7 @@ pub async fn run_wait_result_job_by_hash( Path((w_id, script_hash)): Path<(String, ScriptHash)>, Query(run_query): Query, headers: HeaderMap, - Json(args): Json>>, + JsonOrForm(args): JsonOrForm>>, ) -> error::JsonResult { check_queue_too_long(db, run_query.queue_limit).await?; @@ -1649,7 +1683,7 @@ pub async fn run_wait_result_flow_by_path( Path((w_id, flow_path)): Path<(String, StripPath)>, Query(run_query): Query, headers: HeaderMap, - Json(args): Json>>, + JsonOrForm(args): JsonOrForm>>, ) -> error::JsonResult { check_queue_too_long(db, run_query.queue_limit).await?; @@ -1775,7 +1809,7 @@ pub async fn run_job_by_hash( Path((w_id, script_hash)): Path<(String, ScriptHash)>, Query(run_query): Query, headers: HeaderMap, - Json(args): Json>>, + JsonOrForm(args): JsonOrForm>>, ) -> error::Result<(StatusCode, String)> { let hash = script_hash.0; let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); diff --git a/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte index 67c4985590..3fd65ab3ec 100644 --- a/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte @@ -316,7 +316,8 @@

Webhoosk Pass the input as a json payload, the token as a Bearer token or as query arg - `?token=XXX` and pass as header: 'Content-Type: application/json See docs