diff --git a/docs/src/main/sphinx/connector/pinot.rst b/docs/src/main/sphinx/connector/pinot.rst
index 2e3fe015dae0..f71e0b68f04c 100644
--- a/docs/src/main/sphinx/connector/pinot.rst
+++ b/docs/src/main/sphinx/connector/pinot.rst
@@ -74,6 +74,11 @@ Property name Required Description
``pinot.aggregation-pushdown.enabled`` No Push down aggregation queries, default is ``true``.
``pinot.count-distinct-pushdown.enabled`` No Push down count distinct queries to Pinot, default is ``true``.
``pinot.target-segment-page-size`` No Max allowed page size for segment query, default is ``1MB``.
+``pinot.extra-http-headers`` No Extra headers when sending HTTP based pinot requests to Pinot controller/broker.
+ Headers are comma-separated, and each header key value pair is colon-separated,
+ e.g. ``k1:v1,k2:v2,k3:v3 with space`` with space, default is an empty map. Note
+ that if controller/broker authentications is enabled and ``Authorization`` header
+ is set, an exception will raise.
========================================================= ========== ==============================================================================
If ``pinot.controller.authentication.type`` is set to ``PASSWORD`` then both ``pinot.controller.authentication.user`` and
diff --git a/plugin/trino-pinot/pom.xml b/plugin/trino-pinot/pom.xml
index d422ea4fcf69..3180f98ad34c 100755
--- a/plugin/trino-pinot/pom.xml
+++ b/plugin/trino-pinot/pom.xml
@@ -163,6 +163,12 @@
validation-api
+
+ org.apache.commons
+ commons-lang3
+ 3.8
+
+
org.apache.helix
helix-core
@@ -461,13 +467,6 @@
runtime
-
- org.apache.commons
- commons-lang3
- 3.8
- runtime
-
-
org.apache.httpcomponents
httpcore
diff --git a/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotConfig.java b/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotConfig.java
index 84b9096e07ed..040111092b0a 100755
--- a/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotConfig.java
+++ b/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotConfig.java
@@ -15,12 +15,14 @@
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import io.airlift.configuration.Config;
import io.airlift.configuration.ConfigDescription;
import io.airlift.configuration.DefunctConfig;
import io.airlift.units.DataSize;
import io.airlift.units.Duration;
import io.airlift.units.MinDuration;
+import org.apache.commons.lang3.StringUtils;
import javax.annotation.PostConstruct;
import javax.validation.constraints.AssertTrue;
@@ -29,6 +31,7 @@
import java.net.URI;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkArgument;
@@ -47,6 +50,7 @@
public class PinotConfig
{
private static final Splitter LIST_SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings();
+ private static final Splitter.MapSplitter MAP_SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings().withKeyValueSeparator(":");
private List controllerUrls = ImmutableList.of();
@@ -65,6 +69,7 @@ public class PinotConfig
private boolean countDistinctPushdownEnabled = true;
private boolean grpcEnabled = true;
private DataSize targetSegmentPageSize = DataSize.of(1, MEGABYTE);
+ private Map extraHttpHeaders = ImmutableMap.of();
@NotEmpty(message = "pinot.controller-urls cannot be empty")
public List getControllerUrls()
@@ -257,12 +262,29 @@ public PinotConfig setTargetSegmentPageSize(DataSize targetSegmentPageSize)
return this;
}
+ @NotNull
+ public Map getExtraHttpHeaders()
+ {
+ return extraHttpHeaders;
+ }
+
+ @Config("pinot.extra-http-headers")
+ public PinotConfig setExtraHttpHeaders(String headers)
+ {
+ extraHttpHeaders = ImmutableMap.copyOf(MAP_SPLITTER.split(headers));
+ return this;
+ }
+
@PostConstruct
public void validate()
{
checkState(
!countDistinctPushdownEnabled || aggregationPushdownEnabled,
"Invalid configuration: pinot.aggregation-pushdown.enabled must be enabled if pinot.count-distinct-pushdown.enabled");
+ extraHttpHeaders.forEach((k, v) -> {
+ checkState(!StringUtils.isNotEmpty(v), "Found null value in extraHttpHeaders for key: " + k);
+ checkState(!StringUtils.isNotEmpty(k), "Found empty key in extraHttpHeaders");
+ });
}
@AssertTrue(message = "All controller URLs must have the same scheme")
diff --git a/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/client/PinotClient.java b/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/client/PinotClient.java
index ae8a1001ac0d..41c5d7169d3f 100755
--- a/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/client/PinotClient.java
+++ b/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/client/PinotClient.java
@@ -46,6 +46,7 @@
import io.trino.plugin.pinot.PinotException;
import io.trino.plugin.pinot.PinotInsufficientServerResponseException;
import io.trino.plugin.pinot.PinotSessionProperties;
+import io.trino.plugin.pinot.auth.PinotAuthenticationProvider;
import io.trino.plugin.pinot.auth.PinotBrokerAuthenticationProvider;
import io.trino.plugin.pinot.auth.PinotControllerAuthenticationProvider;
import io.trino.plugin.pinot.query.PinotQueryInfo;
@@ -92,6 +93,7 @@
import static io.trino.collect.cache.SafeCaches.buildNonEvictableCache;
import static io.trino.plugin.pinot.PinotErrorCode.PINOT_AMBIGUOUS_TABLE_NAME;
import static io.trino.plugin.pinot.PinotErrorCode.PINOT_EXCEPTION;
+import static io.trino.plugin.pinot.PinotErrorCode.PINOT_HTTP_ERROR;
import static io.trino.plugin.pinot.PinotErrorCode.PINOT_UNABLE_TO_FIND_BROKER;
import static io.trino.plugin.pinot.PinotMetadata.SCHEMA_NAME;
import static java.lang.String.format;
@@ -122,6 +124,7 @@ public class PinotClient
private final HttpClient httpClient;
private final PinotHostMapper pinotHostMapper;
private final String scheme;
+ private final Map extraHttpHeaders;
private final NonEvictableLoadingCache> brokersForTableCache;
private final NonEvictableLoadingCache