Bug Report: spring.cloud.gcp.storage.host Drops Port Number
Describe the bug
When configuring spring.cloud.gcp.storage.host with a custom port
(e.g. for a local emulator), the port number is silently removed by
GcpStorageAutoConfiguration.
Specifically, the verifyAndFetchHost() method reconstructs the host
using URL.getHost(), which strips the port portion of the URL.
This makes it impossible to connect to a GCS emulator running on a
non-default port.
Affected Code
File: GcpStorageAutoConfiguration.java
Module: spring-cloud-gcp-autoconfigure
Relevant lines: 94, 103--118
// line 94
storageOptionsBuilder.setHost(verifyAndFetchHost(this.host));
// line 103-118
private String verifyAndFetchHost(String host) {
URL url;
try {
url = new URL(host);
} catch (MalformedURLException e) {
throw new IllegalArgumentException(
"Invalid host format: " + host
+ ". Please verify that the specified host follows the "
+ "'https://${service}.${universeDomain}/' format");
}
return url.getProtocol() + "://" + url.getHost() + "/"; // <-- BUG: port is lost
}
Problem
URL.getHost() returns only the hostname without the port.
As a result:
Input Expected Actual
http://localhost:54321 http://localhost:54321/ http://localhost/
The port is removed, leading to connection failures when using a local
emulator.
Impact
This directly affects integration testing scenarios using
fake-gcs-server + Testcontainers, where the container port is
dynamically mapped.
Example:
val endpoint = "http://${gcsContainer.host}:${gcsContainer.getMappedPort(4443)}"
// e.g. "http://localhost:54321"
After passing through verifyAndFetchHost(), the endpoint becomes:
This results in:
Proposed Fix
Replace url.getHost() with url.getAuthority() to preserve the port:
Before (current behavior -- buggy)
return url.getProtocol() + "://" + url.getHost() + "/";
After (proposed fix)
return url.getProtocol() + "://" + url.getAuthority() + "/";
URL.getAuthority() correctly returns:
host:port when a port is present
host when no port is specified
This preserves compatibility in both cases.
How to Reproduce
A minimal reproducible example is available here:
👉 https://github.com/sejoung/GCSTestContainter.git
Steps:
- Clone the repository
- Run:
What happens:
-
TestGcsContainterConfiguration starts a fake-gcs-server
container on a random mapped port.
-
The application sets:
spring.cloud.gcp.storage.host=http://localhost:<random-port>
-
GcpStorageAutoConfiguration processes the host and removes the
port.
-
The Storage client attempts to connect to:
-
The test fails with Connection refused.
Environment
- Spring Cloud GCP: 7.4.5
- Spring Boot: 3.5.6
- Testcontainers: 1.21.3
- fake-gcs-server: latest
- Java: 24
Please let me know if you would like me to submit a PR once this issue
is reviewed and labeled as Accepting Contributions.
Bug Report:
spring.cloud.gcp.storage.hostDrops Port NumberDescribe the bug
When configuring
spring.cloud.gcp.storage.hostwith a custom port(e.g. for a local emulator), the port number is silently removed by
GcpStorageAutoConfiguration.Specifically, the
verifyAndFetchHost()method reconstructs the hostusing
URL.getHost(), which strips the port portion of the URL.This makes it impossible to connect to a GCS emulator running on a
non-default port.
Affected Code
File:
GcpStorageAutoConfiguration.javaModule:
spring-cloud-gcp-autoconfigureRelevant lines: 94, 103--118
Problem
URL.getHost()returns only the hostname without the port.As a result:
Input Expected Actual
http://localhost:54321http://localhost:54321/http://localhost/The port is removed, leading to connection failures when using a local
emulator.
Impact
This directly affects integration testing scenarios using
fake-gcs-server + Testcontainers, where the container port is
dynamically mapped.
Example:
After passing through
verifyAndFetchHost(), the endpoint becomes:This results in:
Proposed Fix
Replace
url.getHost()withurl.getAuthority()to preserve the port:Before (current behavior -- buggy)
After (proposed fix)
URL.getAuthority()correctly returns:host:portwhen a port is presenthostwhen no port is specifiedThis preserves compatibility in both cases.
How to Reproduce
A minimal reproducible example is available here:
👉 https://github.com/sejoung/GCSTestContainter.git
Steps:
What happens:
TestGcsContainterConfigurationstarts afake-gcs-servercontainer on a random mapped port.
The application sets:
GcpStorageAutoConfigurationprocesses the host and removes theport.
The
Storageclient attempts to connect to:The test fails with
Connection refused.Environment
Please let me know if you would like me to submit a PR once this issue
is reviewed and labeled as Accepting Contributions.