Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
4e07ebf
Add some more meaningful names to distinct Bootstrap instances
ksobolew Nov 4, 2025
05f8a1a
Bump com.azure:azure-sdk-bom from 1.3.0 to 1.3.2
dependabot[bot] Nov 5, 2025
6942821
Bump org.checkerframework:checker-qual from 3.51.1 to 3.52.0
dependabot[bot] Nov 5, 2025
9901194
Support configurable ExchangeManager
yangshangqing95 Sep 12, 2025
34da7c9
Document exchange.max-page-storage-size config property
etolbakov Oct 20, 2025
3f97a0f
Update Jakarta rs-ws api to 4.0.0
wendigo Nov 5, 2025
e6cdeb5
Fail internal communication gracefully during intialization
losipiuk Nov 3, 2025
00da374
Do not modify iterated collections in MemoryMetadata#renameSchema
ksobolew Nov 4, 2025
836515d
Bump software.amazon.awssdk:bom from 2.37.3 to 2.37.5
dependabot[bot] Nov 5, 2025
55d7887
Add support for token exchange in Iceberg REST catalog
MonkeyCanCode Oct 31, 2025
800ff7c
Fix typo in FTE doc
hqbhoho Nov 5, 2025
13d3090
Fix TrinoInputStream.available implementations
findepi Nov 5, 2025
4501b99
Fix nullAllowed of Domain for identical operator in UtcConstraintExtr…
hqbhoho Nov 5, 2025
7f380c0
Document IDENTICAL_OPERATOR_FUNCTION_NAME in StandardFunctions
hqbhoho Nov 5, 2025
fdc061e
Update airlift to 375
wendigo Nov 5, 2025
11829af
Bump org.jdbi:jdbi3-bom from 3.49.6 to 3.50.0
dependabot[bot] Nov 6, 2025
6588e8c
Bump commons-codec:commons-codec from 1.19.0 to 1.20.0
dependabot[bot] Nov 6, 2025
215faac
Bump org.apache.hadoop.thirdparty:hadoop-shaded-guava
dependabot[bot] Nov 5, 2025
26c2ee6
feat:after RemoveTrivialFilters call RemoveEmptyUnionBranches to prun…
Max-Cheng Aug 6, 2025
9cbcdd2
Add support for passing arbitrary HTTP headers in the clients
Pluies Aug 11, 2023
0bb75f8
Fix failure when reading Redshift CHARACTER VARYING type
ebyhr Nov 6, 2025
4b12206
drop! Run Redshift CI with longer timeout
ebyhr Nov 6, 2025
8da330c
Revert "drop! Run Redshift CI with longer timeout"
ebyhr Nov 6, 2025
4236861
Randomize role name in BaseHiveConnectorTest
ebyhr Nov 6, 2025
ecb13fc
Isolate testBulkColumnListingOptions for SQL Server
ebyhr Nov 5, 2025
9b7f7bf
Add non-callback based entry builder for RowBlockBuilder
dain Nov 3, 2025
8c2a693
Add non-callback based entry builder for ArrayBlockBuilder
dain Nov 5, 2025
571fd67
Fix updating column statistics when inserting with overwrite mode
anton-kutuzov Aug 29, 2025
4718c29
Cleanup revapi exclusions after release
ebyhr Nov 7, 2025
4747d65
Bump dep.flyway.version from 11.15.0 to 11.16.0
dependabot[bot] Nov 7, 2025
5823493
Bump software.amazon.awssdk:bom from 2.37.5 to 2.38.1
dependabot[bot] Nov 7, 2025
6b14877
Fix log message grammar
findepi Nov 7, 2025
3ad45d3
Bump com.nimbusds:nimbus-jose-jwt from 10.5 to 10.6
dependabot[bot] Nov 7, 2025
e740ec5
Bump com.nimbusds:oauth2-oidc-sdk from 11.30 to 11.30.1
dependabot[bot] Nov 7, 2025
a3d5ea0
Document nullability of map type
ebyhr Nov 2, 2025
853f22a
Bump dep.nessie.version from 0.105.6 to 0.105.7
dependabot[bot] Nov 7, 2025
54e2910
Bump net.openhft:chronicle-core from 2.27ea8 to 2.27ea9
dependabot[bot] Nov 10, 2025
58b789a
Bump commons-io:commons-io from 2.20.0 to 2.21.0
dependabot[bot] Nov 10, 2025
9578339
Bump software.amazon.awssdk:bom from 2.38.1 to 2.38.2
dependabot[bot] Nov 10, 2025
e6e610d
Bump io.projectreactor:reactor-core from 3.7.12 to 3.8.0
dependabot[bot] Nov 10, 2025
0a13067
Bump com.adobe.testing:s3mock-testcontainers from 4.9.1 to 4.10.0
dependabot[bot] Nov 10, 2025
e13169d
Bump docker/setup-qemu-action from 3.6.0 to 3.7.0
dependabot[bot] Nov 10, 2025
434a852
Add missing @Inject to PartitionedFileSystemLayout
wendigo Nov 7, 2025
4c46ce2
Add test for IS NOT DISTINCT FROM pushdown in Iceberg
hqbhoho Nov 8, 2025
521f1aa
Add test for IS NOT DISTINCT FROM pushdown in DeltaLake
hqbhoho Nov 8, 2025
aecaa8c
Bump io.projectreactor.netty:reactor-netty-core from 1.2.11 to 1.3.0
dependabot[bot] Nov 10, 2025
04b5b29
Bump com.dylibso.chicory:bom from 1.5.3 to 1.6.0
dependabot[bot] Nov 10, 2025
ec2f71c
Add missing annotations to LongDecmialType operators
pettyjamesm Nov 3, 2025
dd24cc9
Add missing annotations to ShortDecimalType operators
pettyjamesm Nov 3, 2025
59b2689
Add missing annotations to LongTimeWithTimeZoneType
pettyjamesm Nov 3, 2025
4ed4f2b
Add missing annotations to LongTimestampWithTimeZoneType
pettyjamesm Nov 3, 2025
e9a06f5
Add missing annotations to LongTimestampType
pettyjamesm Nov 3, 2025
4c72170
Add missing annotations to ShortTimeWithTimeZoneType
pettyjamesm Nov 3, 2025
7dc1908
Add missing annotations to TimeType
pettyjamesm Nov 3, 2025
642810d
Add missing annotations to BooleanType
pettyjamesm Nov 3, 2025
661ed39
Add missing annotations to AbstractIntType
pettyjamesm Nov 3, 2025
170296c
Add missing annotations to AbstractLongType
pettyjamesm Nov 3, 2025
cef7d64
Add missing annotations to DoubleType
pettyjamesm Nov 3, 2025
7c57975
Add missing annnotations to IpAddressType
pettyjamesm Nov 3, 2025
c231f10
Add missing annotations to UuidType
pettyjamesm Nov 3, 2025
d14d4d6
Add missing annotations to RealType
pettyjamesm Nov 3, 2025
bddd211
Add missing annotations to ShortTimestampType
pettyjamesm Nov 3, 2025
8a5936b
Add missing annotations to AbstractVariableWidthType
pettyjamesm Nov 3, 2025
963a46e
Add flat equalsOperator implementations
pettyjamesm Nov 3, 2025
e961a63
Add flat xxhash64 operator implementations
pettyjamesm Nov 3, 2025
267f48f
Add flat hashcode implementation for LongTimeWithTimeZoneType
pettyjamesm Nov 3, 2025
8073611
Bump io.airlift:airbase from 325 to 326
dependabot[bot] Nov 10, 2025
bf69589
Test Databricks 17.3 LTS in Delta Lake connector
ebyhr Oct 27, 2025
1b0b0d6
Bump io.airlift:bom from 375 to 376
dependabot[bot] Nov 10, 2025
1e9a692
Bump software.amazon.awssdk:bom from 2.38.2 to 2.38.3
dependabot[bot] Nov 11, 2025
471434f
Fix regex for testRestartDuringQuery to handle header interruption
anusudarsan Nov 10, 2025
5e9998b
Harden the retry policy for running Redshift SQL queries
findinpath Nov 10, 2025
28d579d
Bump io.airlift:airbase from 326 to 327
dependabot[bot] Nov 11, 2025
38e8938
Bump dep.flyway.version from 11.16.0 to 11.17.0
dependabot[bot] Nov 11, 2025
6011487
Bump software.amazon.awssdk:bom from 2.38.3 to 2.38.4
dependabot[bot] Nov 12, 2025
3d8f764
Remove old implementation from BenchmarkArraySort
raunaqmorarka Nov 11, 2025
e23a5e8
Use Block copyPositions to avoid BlockBuilder#append per position
raunaqmorarka Nov 11, 2025
fdf2533
Bump com.google.auto.value:auto-value-annotations from 1.11.0 to 1.11.1
dependabot[bot] Nov 12, 2025
5fa18ec
Compile trino-server-main targeting Java 11
findepi Nov 10, 2025
21c5a6d
Cleanup DistinctWindowAccumulator
pettyjamesm Nov 12, 2025
4ca9208
Avoid Block#getSingleValueBlock copy in WindowAccumulators
pettyjamesm Nov 12, 2025
559e466
Bump io.airlift:airbase from 327 to 328
dependabot[bot] Nov 12, 2025
096e1c1
Remove redundant spaces from ci.yml
ebyhr Nov 11, 2025
2bbf5e7
Bump io.airlift:bom from 376 to 377
dependabot[bot] Nov 13, 2025
1d85a64
Bump com.github.docker-java:docker-java-api from 3.6.0 to 3.7.0
dependabot[bot] Nov 13, 2025
296afe9
Bump software.amazon.awssdk:bom from 2.38.4 to 2.38.5
dependabot[bot] Nov 13, 2025
3e22fca
Bump commons-cli:commons-cli from 1.10.0 to 1.11.0
dependabot[bot] Nov 13, 2025
588fb53
Add Teradata connector
sc250072 Nov 4, 2025
509e3c5
Move tests into teradata package
electrum Nov 4, 2025
89674a7
Move clearscape tests to separate profile
electrum Nov 4, 2025
907229c
Remove TeradataConstants class
electrum Nov 4, 2025
88d3e47
Fix dependency scopes
electrum Nov 4, 2025
c459b56
Use Guava HttpHeaders
electrum Nov 4, 2025
049fd1c
Always use provided clearscape region for tests
electrum Nov 4, 2025
b1fbed3
Remove unused LogonMechanism config
electrum Nov 4, 2025
df023f9
Fix typos in documentation
electrum Nov 4, 2025
2a56ba8
Generate unique environment name
electrum Nov 4, 2025
17a40e9
Require testing region to be set
electrum Nov 4, 2025
69495e5
Hack to run only Teradata tests
electrum Nov 4, 2025
cef89d9
Add retry and auto-reconnect handling for transient JDBC errors (3598…
sc250072 Nov 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
660 changes: 13 additions & 647 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions client/trino-cli/src/main/java/io/trino/cli/ClientOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import static com.google.common.base.Strings.nullToEmpty;
import static io.trino.cli.TerminalUtils.getTerminal;
import static io.trino.client.KerberosUtil.defaultCredentialCachePath;
import static io.trino.client.ProtocolHeaders.TRINO_HEADERS;
import static io.trino.client.uri.PropertyName.ACCESS_TOKEN;
import static io.trino.client.uri.PropertyName.CATALOG;
import static io.trino.client.uri.PropertyName.CLIENT_INFO;
Expand All @@ -56,6 +57,7 @@
import static io.trino.client.uri.PropertyName.EXTERNAL_AUTHENTICATION;
import static io.trino.client.uri.PropertyName.EXTERNAL_AUTHENTICATION_REDIRECT_HANDLERS;
import static io.trino.client.uri.PropertyName.EXTRA_CREDENTIALS;
import static io.trino.client.uri.PropertyName.EXTRA_HEADERS;
import static io.trino.client.uri.PropertyName.HTTP_LOGGING_LEVEL;
import static io.trino.client.uri.PropertyName.HTTP_PROXY;
import static io.trino.client.uri.PropertyName.KERBEROS_CONFIG_PATH;
Expand Down Expand Up @@ -204,6 +206,10 @@ public class ClientOptions
@Option(names = "--client-tags", paramLabel = "<tags>", description = "Client tags", converter = ClientTagsConverter.class)
public Optional<Set<String>> clientTags;

@PropertyMapping(EXTRA_HEADERS)
@Option(names = "--extra-header", paramLabel = "<header>", description = "Additional HTTP header to add to HTTP requests (property can be used multiple times; format is key=value)")
public final List<ExtraHeader> extraHeaders = new ArrayList<>();

@PropertyMapping(TRACE_TOKEN)
@Option(names = "--trace-token", paramLabel = "<token>", description = "Trace token")
public Optional<String> traceToken;
Expand Down Expand Up @@ -422,6 +428,9 @@ public TrinoUri getTrinoUri(Map<PropertyName, String> restrictedProperties)
if (!sessionProperties.isEmpty()) {
builder.setSessionProperties(toProperties(sessionProperties));
}
if (!extraHeaders.isEmpty()) {
builder.setExtraHeaders(toExtraHeaders(extraHeaders));
}
if (!resourceEstimates.isEmpty()) {
builder.setResourceEstimates(toResourceEstimates(resourceEstimates));
}
Expand Down Expand Up @@ -498,6 +507,15 @@ public static URI parseServer(String server)
}
}

public static Map<String, String> toExtraHeaders(List<ExtraHeader> extraHeaders)
{
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
for (ExtraHeader extraHeader : extraHeaders) {
builder.put(extraHeader.getHeader(), extraHeader.getValue());
}
return builder.buildOrThrow();
}

private static Map<String, String> toProperties(List<ClientSessionProperty> sessionProperties)
{
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
Expand Down Expand Up @@ -605,6 +623,59 @@ public int hashCode()
}
}

public static final class ExtraHeader
{
private final String header;
private final String value;

public ExtraHeader(String headerAndValue)
{
List<String> nameValue = NAME_VALUE_SPLITTER.splitToList(headerAndValue);
checkArgument(nameValue.size() == 2, "Header and value: %s", headerAndValue);
this.header = nameValue.get(0);
this.value = nameValue.get(1);

checkArgument(!TRINO_HEADERS.isProtocolHeader(header), "Header '%s' is a protocol header and cannot be set as an extra header", header);
checkArgument(!header.isEmpty(), "Header name is empty");
checkArgument(!value.isEmpty(), "Header value is empty");
}

public ExtraHeader(String header, String value)
{
this.header = header;
this.value = value;
}

public String getHeader()
{
return header;
}

public String getValue()
{
return value;
}

@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ExtraHeader other = (ExtraHeader) o;
return Objects.equals(header, other.header) && Objects.equals(value, other.value);
}

@Override
public int hashCode()
{
return Objects.hash(header, value);
}
}

public static final class ClientSessionProperty
{
private static final Splitter NAME_SPLITTER = Splitter.on('.');
Expand Down
2 changes: 2 additions & 0 deletions client/trino-cli/src/main/java/io/trino/cli/Trino.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.trino.cli.ClientOptions.ClientExtraCredential;
import io.trino.cli.ClientOptions.ClientResourceEstimate;
import io.trino.cli.ClientOptions.ClientSessionProperty;
import io.trino.cli.ClientOptions.ExtraHeader;
import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.AttributedStyle;
import picocli.CommandLine;
Expand Down Expand Up @@ -62,6 +63,7 @@ public static CommandLine createCommandLine(Object command)
.registerConverter(ClientResourceEstimate.class, ClientResourceEstimate::new)
.registerConverter(ClientSessionProperty.class, ClientSessionProperty::new)
.registerConverter(ClientExtraCredential.class, ClientExtraCredential::new)
.registerConverter(ExtraHeader.class, ExtraHeader::new)
.registerConverter(HostAndPort.class, HostAndPort::fromString)
.registerConverter(Duration.class, Duration::valueOf)
.setResourceBundle(new TrinoResourceBundle())
Expand Down
14 changes: 14 additions & 0 deletions client/trino-cli/src/test/java/io/trino/cli/TestClientOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,20 @@ public void testExtraCredentials()
new ClientOptions.ClientExtraCredential("test.token.bar", "bar")));
}

@Test
public void testExtraHeaders()
{
Console console = createConsole("--extra-header", "X-Trino-Routing-Group=foo", "--extra-header", "x-foo=bar");
ClientOptions options = console.clientOptions;
assertThat(options.extraHeaders).isEqualTo(ImmutableList.of(
new ClientOptions.ExtraHeader("X-Trino-Routing-Group", "foo"),
new ClientOptions.ExtraHeader("x-foo", "bar")));

assertThatThrownBy(() -> createConsole("--extra-header", "X-Trino-User=Forbidden"))
.hasCauseInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Header 'X-Trino-User' is a protocol header and cannot be set as an extra header");
}

@Test
public void testSessionProperties()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class ClientSession
private final ZoneId timeZone;
private final Locale locale;
private final Map<String, String> resourceEstimates;
private final Map<String, String> extraHeaders;
private final Map<String, String> properties;
private final Map<String, String> preparedStatements;
private final Map<String, ClientSelectedRole> roles;
Expand Down Expand Up @@ -87,6 +88,7 @@ private ClientSession(
String source,
Optional<String> traceToken,
Set<String> clientTags,
Map<String, String> extraHeaders,
String clientInfo,
Optional<String> catalog,
Optional<String> schema,
Expand All @@ -112,6 +114,7 @@ private ClientSession(
this.source = requireNonNull(source, "source is null");
this.traceToken = requireNonNull(traceToken, "traceToken is null");
this.clientTags = ImmutableSet.copyOf(requireNonNull(clientTags, "clientTags is null"));
this.extraHeaders = ImmutableMap.copyOf(requireNonNull(extraHeaders, "extraHeaders is null"));
this.clientInfo = clientInfo;
this.catalog = catalog;
this.schema = schema;
Expand Down Expand Up @@ -198,6 +201,11 @@ public Set<String> getClientTags()
return clientTags;
}

public Map<String, String> getExtraHeaders()
{
return extraHeaders;
}

public String getClientInfo()
{
return clientInfo;
Expand Down Expand Up @@ -295,6 +303,7 @@ public String toString()
.add("sessionUser", sessionUser)
.add("authorizationUser", authorizationUser)
.add("clientTags", clientTags)
.add("extraHeaders", extraHeaders)
.add("clientInfo", clientInfo)
.add("catalog", catalog)
.add("schema", schema)
Expand Down Expand Up @@ -324,6 +333,7 @@ public static final class Builder
private String source;
private Optional<String> traceToken = Optional.empty();
private Set<String> clientTags = ImmutableSet.of();
private Map<String, String> extraHeaders = ImmutableMap.of();
private String clientInfo;
private String catalog;
private String schema;
Expand Down Expand Up @@ -354,6 +364,7 @@ private Builder(ClientSession clientSession)
source = clientSession.getSource();
traceToken = clientSession.getTraceToken();
clientTags = clientSession.getClientTags();
extraHeaders = clientSession.getExtraHeaders();
clientInfo = clientSession.getClientInfo();
catalog = clientSession.getCatalog().orElse(null);
schema = clientSession.getSchema().orElse(null);
Expand Down Expand Up @@ -419,6 +430,12 @@ public Builder clientTags(Set<String> clientTags)
return this;
}

public Builder extraHeaders(Map<String, String> extraHeaders)
{
this.extraHeaders = extraHeaders;
return this;
}

public Builder clientInfo(String clientInfo)
{
this.clientInfo = clientInfo;
Expand Down Expand Up @@ -526,6 +543,7 @@ public ClientSession build()
source,
traceToken,
clientTags,
extraHeaders,
clientInfo,
Optional.ofNullable(catalog),
Optional.ofNullable(schema),
Expand Down
12 changes: 12 additions & 0 deletions client/trino-client/src/main/java/io/trino/client/OkHttpUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -109,6 +110,17 @@ public static Interceptor tokenAuth(String accessToken)
.build());
}

public static Interceptor extraHeaders(Map<String, String> extraHeaders)
{
requireNonNull(extraHeaders, "extraHeaders is null");

return chain -> {
okhttp3.Request.Builder builder = chain.request().newBuilder();
extraHeaders.forEach(builder::addHeader);
return chain.proceed(builder.build());
};
}

public static void setupTimeouts(OkHttpClient.Builder clientBuilder, int timeout, TimeUnit unit)
{
clientBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,16 @@ private ProtocolHeaders(String name)
responseOriginalRole = RESPONSE_SET_ORIGINAL_ROLES.withProtocolName(name);
}

public boolean isProtocolHeader(String headerName)
{
for (Headers header : Headers.values()) {
if (header.withProtocolName(name).equalsIgnoreCase(headerName)) {
return true;
}
}
return false;
}

public String getProtocolName()
{
return name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.HostAndPort;
import io.airlift.units.Duration;
Expand Down Expand Up @@ -44,6 +45,7 @@
import static com.google.common.collect.Streams.stream;
import static io.trino.client.ClientSelectedRole.Type.ALL;
import static io.trino.client.ClientSelectedRole.Type.NONE;
import static io.trino.client.ProtocolHeaders.TRINO_HEADERS;
import static io.trino.client.uri.AbstractConnectionProperty.Validator;
import static io.trino.client.uri.AbstractConnectionProperty.validator;
import static io.trino.client.uri.ConnectionProperties.SslVerificationMode.FULL;
Expand Down Expand Up @@ -99,6 +101,7 @@ enum SslVerificationMode
public static final ConnectionProperty<String, Map<String, String>> EXTRA_CREDENTIALS = new ExtraCredentials();
public static final ConnectionProperty<String, String> CLIENT_INFO = new ClientInfo();
public static final ConnectionProperty<String, Set<String>> CLIENT_TAGS = new ClientTags();
public static final ConnectionProperty<String, Map<String, String>> EXTRA_HEADERS = new ExtraHeaders();
public static final ConnectionProperty<String, String> TRACE_TOKEN = new TraceToken();
public static final ConnectionProperty<String, Map<String, String>> SESSION_PROPERTIES = new SessionProperties();
public static final ConnectionProperty<String, String> SOURCE = new Source();
Expand Down Expand Up @@ -139,6 +142,7 @@ enum SslVerificationMode
.add(EXTERNAL_AUTHENTICATION_TIMEOUT)
.add(EXTERNAL_AUTHENTICATION_TOKEN_CACHE)
.add(EXTRA_CREDENTIALS)
.add(EXTRA_HEADERS)
.add(HOSTNAME_IN_CERTIFICATE)
.add(HTTP_LOGGING_LEVEL)
.add(HTTP_PROXY)
Expand Down Expand Up @@ -789,6 +793,42 @@ public static String toString(Map<String, String> values)
}
}

private static class ExtraHeaders
extends AbstractConnectionProperty<String, Map<String, String>>
{
private static final Validator<Properties> VALIDATE_EXTRA_HEADER = validator(
ExtraHeaders::isNotReservedHeader,
format("Connection property %s cannot override any of the Trino protocol headers", PropertyName.EXTRA_HEADERS));

public ExtraHeaders()
{
super(PropertyName.EXTRA_HEADERS, NOT_REQUIRED, VALIDATE_EXTRA_HEADER, converter(ExtraHeaders::parseExtraHeaders, ExtraHeaders::toString));
}

// Extra headers consists of a list of header name value pairs.
// E.g., `jdbc:trino://example.net:8080/?extraHeaders=X-Trino-Route:foo;X-Trino-Custom:bar` will send
// HTTP headers `X-Trino-Route=foo` and `X-Trino-Custom=bar`.
// These headers must not conflict with Trino protocol headers.
public static Map<String, String> parseExtraHeaders(String extraHeadersString)
{
return new MapPropertyParser(PropertyName.EXTRA_HEADERS.toString()).parse(extraHeadersString);
}

public static String toString(Map<String, String> values)
{
return values.entrySet().stream()
.map(entry -> entry.getKey() + ":" + entry.getValue())
.collect(Collectors.joining(";"));
}

private static boolean isNotReservedHeader(Properties properties)
{
Map<String, String> extraHeaders = EXTRA_HEADERS.getValueOrDefault(properties, ImmutableMap.of());
return extraHeaders.keySet().stream()
.noneMatch(TRINO_HEADERS::isProtocolHeader);
}
}

private static class SessionProperties
extends AbstractConnectionProperty<String, Map<String, String>>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import static io.trino.client.KerberosUtil.defaultCredentialCachePath;
import static io.trino.client.OkHttpUtil.basicAuth;
import static io.trino.client.OkHttpUtil.extraHeaders;
import static io.trino.client.OkHttpUtil.setupAlternateHostnameVerification;
import static io.trino.client.OkHttpUtil.setupCookieJar;
import static io.trino.client.OkHttpUtil.setupHttpLogging;
Expand Down Expand Up @@ -87,6 +88,10 @@ public static OkHttpClient.Builder toHttpClientBuilder(TrinoUri uri, String user
builder.addNetworkInterceptor(tokenAuth(uri.getAccessToken().get()));
}

if (!uri.getExtraHeaders().isEmpty()) {
builder.addNetworkInterceptor(extraHeaders(uri.getExtraHeaders()));
}

if (uri.isExternalAuthenticationEnabled()) {
if (!uri.isUseSecureConnection()) {
throw new RuntimeException("TLS/SSL required for authentication using external authorization");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public enum PropertyName
CLIENT_INFO("clientInfo"),
CLIENT_TAGS("clientTags"),
DISABLE_COMPRESSION("disableCompression"),
EXTRA_HEADERS("extraHeaders"),
DNS_RESOLVER("dnsResolver"),
DNS_RESOLVER_CONTEXT("dnsResolverContext"),
ENCODING("encoding"),
Expand Down
Loading
Loading