-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(bigquery-jdbc): parse endpoint overrides and proxy settings from URL authority #13377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
2cddb44
32109aa
4b02ee5
830200c
f5f461d
f50ea05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| import com.google.common.base.Splitter; | ||
| import com.google.common.collect.ImmutableList; | ||
| import com.google.common.net.UrlEscapers; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
|
|
@@ -711,8 +712,10 @@ private static Map<String, String> parseUrlInternal(String url) { | |
| } | ||
|
|
||
| String[] urlParts = url.split(";", 2); | ||
| parseAuthority(urlParts[0], map); | ||
|
|
||
| if (urlParts.length < 2) { | ||
| return map; | ||
| return Collections.unmodifiableMap(map); | ||
| } | ||
|
|
||
| String urlToParse = urlParts[1]; | ||
|
|
@@ -754,7 +757,17 @@ private static Map<String, String> parseUrlInternal(String url) { | |
| } | ||
| String propertyName = PROPERTY_NAME_MAP.get(key); | ||
| String value = CharEscapers.decodeUriPath(kv[1].replace("+", "%2B")); | ||
| map.put(propertyName, value); | ||
| if (propertyName.equals(ENDPOINT_OVERRIDES_PROPERTY_NAME)) { | ||
| String normalizedValue = normalizeEndpointOverrides(value); | ||
| if (map.containsKey(ENDPOINT_OVERRIDES_PROPERTY_NAME)) { | ||
| String existing = map.get(ENDPOINT_OVERRIDES_PROPERTY_NAME); | ||
| map.put(propertyName, mergeEndpointOverrides(existing, normalizedValue)); | ||
| } else { | ||
| map.put(propertyName, normalizedValue); | ||
| } | ||
| } else { | ||
| map.put(propertyName, value); | ||
| } | ||
| } | ||
| return Collections.unmodifiableMap(map); | ||
| } | ||
|
|
@@ -866,4 +879,112 @@ static Map<String, String> parsePropertiesMapFromValue( | |
| } | ||
| return propertiesMap; | ||
| } | ||
|
|
||
| private static void parseAuthority(String urlPart, Map<String, String> map) { | ||
| String authority = urlPart.trim(); | ||
| if (authority.startsWith("jdbc:")) { | ||
| authority = authority.substring(5); | ||
| } | ||
| if (authority.startsWith("bigquery://")) { | ||
| authority = authority.substring(11); | ||
| } else if (authority.startsWith("bigquery:")) { | ||
| authority = authority.substring(9); | ||
| } | ||
| authority = authority.trim(); | ||
| if (authority.isEmpty()) { | ||
| return; | ||
| } | ||
|
|
||
| if (authority.startsWith("http://") || authority.startsWith("https://")) { | ||
| map.put( | ||
| ENDPOINT_OVERRIDES_PROPERTY_NAME, | ||
| BIGQUERY_ENDPOINT_OVERRIDE_PROPERTY_NAME + "=" + normalizeEndpoint(authority)); | ||
| return; | ||
| } | ||
|
|
||
| if (authority.startsWith("[")) { | ||
| int closingBracketIndex = authority.indexOf(']'); | ||
| if (closingBracketIndex != -1) { | ||
| String host = authority.substring(0, closingBracketIndex + 1).trim(); | ||
| String rest = authority.substring(closingBracketIndex + 1).trim(); | ||
| map.put(PROXY_HOST_PROPERTY_NAME, host); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the spec saying about this? Unless spec prescribes it to be proxy, it's not obvious behavior.. e.g.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The official JDBC spec is agnostic and leaves the URL structure after |
||
| if (rest.startsWith(":")) { | ||
| String port = rest.substring(1).trim(); | ||
| if (!port.isEmpty()) { | ||
| map.put(PROXY_PORT_PROPERTY_NAME, port); | ||
| } | ||
| } | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| int colonIndex = authority.indexOf(':'); | ||
| if (colonIndex == -1) { | ||
| map.put(PROXY_HOST_PROPERTY_NAME, authority); | ||
| return; | ||
| } | ||
|
|
||
| String host = authority.substring(0, colonIndex).trim(); | ||
| String port = authority.substring(colonIndex + 1).trim(); | ||
| if (!host.isEmpty()) { | ||
| map.put(PROXY_HOST_PROPERTY_NAME, host); | ||
| } | ||
| if (!port.isEmpty()) { | ||
| map.put(PROXY_PORT_PROPERTY_NAME, port); | ||
| } | ||
|
keshavdandeva marked this conversation as resolved.
|
||
| } | ||
|
|
||
| private static String mergeEndpointOverrides(String existing, String newValue) { | ||
| Map<String, String> merged = new LinkedHashMap<>(); | ||
| parseOverridesIntoMap(existing, merged); | ||
| parseOverridesIntoMap(newValue, merged); | ||
| List<String> parts = new ArrayList<>(); | ||
| for (Map.Entry<String, String> entry : merged.entrySet()) { | ||
| parts.add(entry.getKey() + "=" + entry.getValue()); | ||
| } | ||
| return String.join(",", parts); | ||
|
keshavdandeva marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| private static void parseOverridesIntoMap(String overrides, Map<String, String> targetMap) { | ||
| if (overrides == null || overrides.isEmpty()) { | ||
| return; | ||
| } | ||
| for (String part : overrides.split(",")) { | ||
| String[] kv = part.split("=", 2); | ||
| if (kv.length == 2) { | ||
| targetMap.put(kv[0].trim(), normalizeEndpoint(kv[1].trim())); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static String normalizeEndpoint(String endpoint) { | ||
| if (endpoint == null) { | ||
| return null; | ||
| } | ||
| String normalized = endpoint.trim(); | ||
| Pattern pattern = Pattern.compile("^(https?://[^/]+)(/bigquery/v2)?(:\\d+)?$"); | ||
| Matcher matcher = pattern.matcher(normalized); | ||
|
keshavdandeva marked this conversation as resolved.
Outdated
|
||
| if (matcher.matches()) { | ||
| String base = matcher.group(1); | ||
| String port = matcher.group(3); | ||
| if (port != null) { | ||
| return base + port; | ||
| } | ||
| return base; | ||
| } | ||
| return normalized; | ||
| } | ||
|
|
||
| private static String normalizeEndpointOverrides(String overrides) { | ||
| if (overrides == null || overrides.isEmpty()) { | ||
| return overrides; | ||
| } | ||
| Map<String, String> map = new LinkedHashMap<>(); | ||
| parseOverridesIntoMap(overrides, map); | ||
| List<String> parts = new ArrayList<>(); | ||
| for (Map.Entry<String, String> entry : map.entrySet()) { | ||
| parts.add(entry.getKey() + "=" + entry.getValue()); | ||
| } | ||
| return String.join(",", parts); | ||
|
keshavdandeva marked this conversation as resolved.
|
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.