Skip to content

improve: service URL parsing compatible with Go 1.26#1468

Merged
nodece merged 7 commits into
apache:masterfrom
nodece:improve-service-url-parsing
Mar 21, 2026
Merged

improve: service URL parsing compatible with Go 1.26#1468
nodece merged 7 commits into
apache:masterfrom
nodece:improve-service-url-parsing

Conversation

@nodece

@nodece nodece commented Mar 2, 2026

Copy link
Copy Markdown
Member

Fixes #1466

Motivation

Go 1.26 introduces stricter URL parsing via url.Parse, rejecting malformed URLs with multiple colons in the host, such as http://::1/ or http://localhost:80:80/. Bracketed IPv6 addresses, e.g. http://[::1]/, remain valid. The old behavior can be restored with GODEBUG=urlstrictcolons=0.

This change exposed redundancy and limitations in the Pulsar client's URL handling, especially for multi-host configurations and internal service resolution.

Modifications

  • The existing ServiceNameResolver is now fully leveraged. Previously, both a url.URL object and a ServiceNameResolver (which already contains the parsed URL and related info) were passed around, causing redundancy. After this refactor, only the ServiceNameResolver is passed, which is sufficient for internal processing.
  • PulsarServiceURI parsing is updated so multi-host service URLs can still be handled under Go 1.26 strict parsing. The parser splits host lists before url.Parse, validates the remaining hosts separately, and adds stricter validation around malformed hosts and bracketed IPv6 usage.
  • Service URL handling across the client and internal services (newClient, NewLookupService, NewHTTPLookupService) is streamlined. Some internal method signatures and interfaces have changed; these updates are confined to the internal package and do not affect end users.
  • Tests are updated to cover the stricter parsing behavior, including delimiter handling in path/query/fragment, invalid bracketed hosts, IsHTTP() behavior, and resolver regressions.
  • Go 1.26 is added to the CI matrix, and stricter URL parsing is enforced using GODEBUG=urlstrictcolons=1.
  • Remove Go 1.23 to align with go.mod requirements. Using Go 1.23 currently triggers an auto-download of Go 1.24 during go mod download.

@nodece nodece force-pushed the improve-service-url-parsing branch 2 times, most recently from e6359cf to 611b799 Compare March 3, 2026 09:37
@nodece nodece force-pushed the improve-service-url-parsing branch from 2bf5bb4 to 5df25c5 Compare March 4, 2026 02:24
@nodece nodece added this to the v0.19.0 milestone Mar 4, 2026
@nodece nodece self-assigned this Mar 4, 2026
@nodece nodece requested a review from crossoverJie March 4, 2026 04:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors Pulsar service URL handling to stay compatible with stricter net/url.Parse behavior (Go 1.26), especially for multi-host service URLs, by centralizing parsing/validation in PulsarServiceURI / ServiceNameResolver and updating internal call sites accordingly.

Changes:

  • Reworked PulsarServiceURI parsing to parse a single-host URL via url.Parse and validate remaining hosts separately (avoiding strict-colon failures on multi-host URLs).
  • Refactored internal APIs to pass ServiceNameResolver/service URL strings instead of *url.URL, updating RPC/lookup/HTTP client wiring and tests.
  • Updated build/test tooling and CI to default to Go 1.24 and add Go 1.26 with GODEBUG=urlstrictcolons=1.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pulsar/internal/service_uri.go New parsing/validation approach; adds helpers for TLS/HTTP detection and primary hostname extraction.
pulsar/internal/service_uri_test.go Updates/extends negative test cases to match stricter parsing expectations.
pulsar/internal/service_name_resolver.go Resolver API now takes a service URL string and returns an error; removes stored *url.URL.
pulsar/internal/service_name_resolver_test.go Adjusts resolver tests for new constructor/update signature.
pulsar/internal/rpc_client.go NewRPCClient now takes a service URL string; lookup service creation routed through new parsing flow.
pulsar/internal/rpc_client_test.go Updates RPC client tests to pass URL strings.
pulsar/internal/lookup_service.go Lookup service constructors no longer take *url.URL; logging now uses resolver’s parsed URI.
pulsar/internal/lookup_service_test.go Updates lookup service tests for new constructor signatures.
pulsar/internal/http_client.go HTTP client constructor no longer takes *url.URL; logging derives from resolver.
pulsar/client_impl.go Client creation now uses PulsarServiceURI for scheme/TLS decisions and passes URL string into internal RPC client.
README.md Raises documented minimum Go version to 1.24 and updates example make test invocation.
Makefile Updates default GO_VERSION to 1.24.
Dockerfile Updates default GO_VERSION build arg to 1.24.
.github/workflows/ci.yml CI matrix moves to Go 1.24 + 1.26 and enforces strict URL colon parsing via GODEBUG.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pulsar/internal/service_name_resolver.go Outdated
Comment thread pulsar/internal/service_uri.go
Comment thread pulsar/internal/service_uri.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

pulsar/internal/rpc_client.go:116

  • NewRPCClient() now initializes the base lookup service via c.LookupService(serviceURL), which caches the returned lookup service in urlLookupServiceMap. Close() then calls c.lookupService.Close() and also iterates urlLookupServiceMap closing each entry, causing the base lookup service to be closed twice. Consider creating the initial lookup service via c.newLookupService(serviceURL) (or otherwise ensure the base instance is not stored/closed twice).
	lookupService, err := c.LookupService(serviceURL)
	if err != nil {
		return nil, fmt.Errorf("failed to create lookup service: %w", err)
	}
	c.lookupService = lookupService

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pulsar/internal/service_uri.go Outdated
Comment thread pulsar/internal/service_uri.go Outdated
Comment thread pulsar/internal/service_name_resolver_test.go Outdated
Comment thread pulsar/client_impl.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pulsar/internal/service_uri.go Outdated
Comment thread pulsar/internal/rpc_client.go
Comment thread pulsar/internal/service_uri.go
nodece and others added 2 commits March 20, 2026 11:21
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nodece nodece merged commit d0db340 into apache:master Mar 21, 2026
7 checks passed
@nodece nodece deleted the improve-service-url-parsing branch March 21, 2026 04:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

service url parse broken since Go1.26

3 participants