@@ -42,8 +42,10 @@ public class QueryIdCachingProxyHandler extends ProxyHandler {
42
42
public static final String SOURCE_HEADER = "X-Trino-Source" ;
43
43
public static final String ALTERNATE_SOURCE_HEADER = "X-Presto-Source" ;
44
44
public static final String HOST_HEADER = "Host" ;
45
+ public static final String REFERER_STRING = "Referer" ;
45
46
private static final int QUERY_TEXT_LENGTH_FOR_HISTORY = 200 ;
46
- private static final Pattern QUERY_ID_PATTERN = Pattern .compile (".*[/=?](\\ d+_\\ d+_\\ d+_\\ w+).*" );
47
+ private static final Pattern QUERY_ID_PATTERN =
48
+ Pattern .compile ("(.*[/=?])?(\\ d+_\\ d+_\\ d+_\\ w+).*" );
47
49
48
50
private static final Pattern EXTRACT_BETWEEN_SINGLE_QUOTES = Pattern .compile ("'([^\\ s']+)'" );
49
51
@@ -115,22 +117,23 @@ public String rewriteTarget(HttpServletRequest request) {
115
117
116
118
// Only load balance presto query APIs.
117
119
if (isPathWhiteListed (request .getRequestURI ())) {
118
- String queryId = extractQueryIdIfPresent (request );
120
+ Optional < String > queryId = extractQueryIdIfPresent (request );
119
121
122
+ backendAddress = queryId
120
123
// Find query id and get url from cache
121
- if (!Strings .isNullOrEmpty (queryId )) {
122
- backendAddress = routingManager .findBackendForQueryId (queryId );
123
- } else {
124
+ .map (routingManager ::findBackendForQueryId )
125
+ .orElseGet (() -> {
124
126
String routingGroup = routingGroupSelector .findRoutingGroup (request );
125
127
String user = Optional .ofNullable (request .getHeader (USER_HEADER ))
126
128
.orElse (request .getHeader (ALTERNATE_USER_HEADER ));
127
129
if (!Strings .isNullOrEmpty (routingGroup )) {
128
130
// This falls back on adhoc backend if there are no cluster found for the routing group.
129
- backendAddress = routingManager .provideBackendForRoutingGroup (routingGroup , user );
131
+ return routingManager .provideBackendForRoutingGroup (routingGroup , user );
130
132
} else {
131
- backendAddress = routingManager .provideAdhocBackend (user );
133
+ return routingManager .provideAdhocBackend (user );
132
134
}
133
- }
135
+ });
136
+
134
137
// set target backend so that we could save queryId to backend mapping later.
135
138
((MultiReadHttpServletRequest ) request ).addHeader (PROXY_TARGET_HEADER , backendAddress );
136
139
}
@@ -159,7 +162,7 @@ public String rewriteTarget(HttpServletRequest request) {
159
162
return targetLocation ;
160
163
}
161
164
162
- protected String extractQueryIdIfPresent (HttpServletRequest request ) {
165
+ protected Optional < String > extractQueryIdIfPresent (HttpServletRequest request ) {
163
166
String path = request .getRequestURI ();
164
167
String queryParams = request .getQueryString ();
165
168
try {
@@ -174,7 +177,8 @@ protected String extractQueryIdIfPresent(HttpServletRequest request) {
174
177
if (m .find ()) {
175
178
String queryQuoted = m .group ();
176
179
if (!Strings .isNullOrEmpty (queryQuoted ) && queryQuoted .length () > 0 ) {
177
- return queryQuoted .substring (1 , queryQuoted .length () - 1 );
180
+ String res = queryQuoted .substring (1 , queryQuoted .length () - 1 );
181
+ return Optional .of (res ).filter (s -> !s .isEmpty ());
178
182
}
179
183
}
180
184
}
@@ -183,37 +187,58 @@ protected String extractQueryIdIfPresent(HttpServletRequest request) {
183
187
} catch (Exception e ) {
184
188
log .error ("Error extracting query payload from request" , e );
185
189
}
186
-
187
- return extractQueryIdIfPresent (path , queryParams );
190
+
191
+ return extractQueryIdIfPresent (path , queryParams ).or (() -> {
192
+ return Optional .ofNullable (request .getHeader (REFERER_STRING ))
193
+ .flatMap (referer -> {
194
+ try {
195
+ URI uri = URI .create (referer );
196
+ return extractQueryIdIfPresent (uri .getPath (), uri .getQuery ());
197
+ } catch (Exception e ) {
198
+ log .error ("Error extracting query id from Referer header" , e );
199
+ }
200
+ return Optional .empty ();
201
+ });
202
+ }).filter (s -> !s .isEmpty ());
188
203
}
189
204
190
- protected static String extractQueryIdIfPresent (String path , String queryParams ) {
205
+ protected static Optional < String > extractQueryIdIfPresent (String path , String queryParams ) {
191
206
if (path == null ) {
192
- return null ;
207
+ return Optional . empty () ;
193
208
}
194
- String queryId = null ;
195
209
196
210
log .debug ("trying to extract query id from path [{}] or queryString [{}]" , path , queryParams );
197
211
if (path .startsWith (V1_STATEMENT_PATH ) || path .startsWith (V1_QUERY_PATH )) {
198
212
String [] tokens = path .split ("/" );
199
- if (tokens .length >= 4 ) {
200
- if (path .contains ("queued" )
201
- || path .contains ("scheduled" )
202
- || path .contains ("executing" )
203
- || path .contains ("partialCancel" )) {
204
- queryId = tokens [4 ];
205
- } else {
206
- queryId = tokens [3 ];
207
- }
213
+ if (tokens .length < 4 ) {
214
+ return Optional .empty ();
208
215
}
209
- } else if (path .startsWith (PRESTO_UI_PATH )) {
216
+
217
+ if (path .contains ("queued" )
218
+ || path .contains ("scheduled" )
219
+ || path .contains ("executing" )
220
+ || path .contains ("partialCancel" )) {
221
+ return Optional .of (tokens [4 ]);
222
+ }
223
+
224
+ return Optional .of (tokens [3 ]);
225
+ }
226
+
227
+ if (path .startsWith (PRESTO_UI_PATH )) {
210
228
Matcher matcher = QUERY_ID_PATTERN .matcher (path );
211
229
if (matcher .matches ()) {
212
- queryId = matcher .group (1 );
230
+ return Optional .of (matcher .group (2 ));
231
+ }
232
+ }
233
+
234
+ if (queryParams != null ) {
235
+ Matcher matcher = QUERY_ID_PATTERN .matcher (queryParams );
236
+ if (matcher .matches ()) {
237
+ return Optional .of (matcher .group (2 ));
213
238
}
214
239
}
215
- log . debug ( "query id in url [{}]" , queryId );
216
- return queryId ;
240
+
241
+ return Optional . empty () ;
217
242
}
218
243
219
244
protected void postConnectionHook (
0 commit comments