@@ -8,6 +8,7 @@ use std::{
88
99use axum:: {
1010 Json ,
11+ body:: Body ,
1112 extract:: { Path , State } ,
1213 response:: { IntoResponse , Response } ,
1314} ;
@@ -93,6 +94,11 @@ pub enum Error {
9394 source : cluster_group_manager:: Error ,
9495 } ,
9596
97+ #[ snafu( display( "Failed to send HEAD request to trino" ) ) ]
98+ SendHeadToTrino {
99+ source : cluster_group_manager:: Error ,
100+ } ,
101+
96102 #[ snafu( display(
97103 "Failed to decrement the query counter query trino cluster {trino_cluster:?}"
98104 ) ) ]
@@ -216,22 +222,45 @@ pub async fn get_trino_queued_statement(
216222/// Trino cluster and currently running.
217223///
218224/// In case the nextUri is null, the query will be stopped and removed from trino-lb.
225+ ///
226+ /// Please note that sometimes the Trino clients also HEAD this endpoint, in which case we need some
227+ /// special handling.
219228#[ instrument(
220- name = "GET /v1/statement/executing/{queryId}/{slug}/{token}" ,
229+ name = "GET (or HEAD) /v1/statement/executing/{queryId}/{slug}/{token}" ,
221230 skip( state, headers)
222231) ]
223232pub async fn get_trino_executing_statement (
233+ method : http:: Method ,
224234 headers : HeaderMap ,
225235 State ( state) : State < Arc < AppState > > ,
226236 Path ( ( query_id, _, _) ) : Path < ( TrinoQueryId , String , u64 ) > ,
227237 uri : Uri ,
228- ) -> Result < ( HeaderMap , Json < TrinoQueryApiResponse > ) , Error > {
238+ ) -> Result < Response , Error > {
239+ if method == http:: Method :: HEAD {
240+ state. metrics . http_counter . add (
241+ 1 ,
242+ & [ KeyValue :: new ( "resource" , "head_trino_executing_statement" ) ] ,
243+ ) ;
244+
245+ let headers = handle_head_request_to_trino ( & state, headers, query_id, uri. path ( ) ) . await ?;
246+
247+ // For a HEAD request we don't need (nor can) return a body.
248+ let mut response = Response :: new ( Body :: empty ( ) ) ;
249+ * response. status_mut ( ) = StatusCode :: OK ;
250+ * response. headers_mut ( ) = headers;
251+ return Ok ( response) ;
252+ }
229253 state. metrics . http_counter . add (
230254 1 ,
231255 & [ KeyValue :: new ( "resource" , "get_trino_executing_statement" ) ] ,
232256 ) ;
233257
234- handle_query_running_on_trino ( & state, headers, query_id, uri. path ( ) ) . await
258+ let ( headers, body) =
259+ handle_query_running_on_trino ( & state, headers, query_id, uri. path ( ) ) . await ?;
260+
261+ let mut response = body. into_response ( ) ;
262+ * response. headers_mut ( ) = headers;
263+ Ok ( response)
235264}
236265
237266#[ instrument( skip(
@@ -495,6 +524,38 @@ async fn handle_query_running_on_trino(
495524 Ok ( ( trino_headers, Json ( trino_query_api_response) ) )
496525}
497526
527+ async fn handle_head_request_to_trino (
528+ state : & Arc < AppState > ,
529+ headers : HeaderMap ,
530+ query_id : TrinoQueryId ,
531+ requested_path : & str ,
532+ ) -> Result < HeaderMap , Error > {
533+ let query =
534+ state
535+ . persistence
536+ . load_query ( & query_id)
537+ . await
538+ . context ( LoadQueryFromPersistenceSnafu {
539+ query_id : query_id. clone ( ) ,
540+ } ) ?;
541+
542+ let headers = state
543+ . cluster_group_manager
544+ . send_head_to_trino (
545+ query. trino_endpoint . join ( requested_path) . context (
546+ JoinRequestPathToTrinoEndpointSnafu {
547+ requested_path,
548+ trino_endpoint : query. trino_endpoint . clone ( ) ,
549+ } ,
550+ ) ?,
551+ headers,
552+ )
553+ . await
554+ . context ( SendHeadToTrinoSnafu ) ?;
555+
556+ Ok ( headers)
557+ }
558+
498559/// This function get's asked to delete the queued query.
499560/// IMPORTANT: It does not check that the user is authorized to delete the queued query. Instead we assume that the
500561/// random part of the queryId trino-lb generates provides sufficient protection, as other clients can not extract
0 commit comments