zbchi opened a new pull request, #3301:
URL: https://github.com/apache/dubbo-go/pull/3301
## Description
#2847.
Add a minimal, transport-scoped way to host an existing root
`http.Handler` on the Triple listener.
This change does not try to turn plain HTTP into a first-class dubbo-go
service model in one step. It focuses on the transport-layer integration needed
to make incremental HTTP-to-Triple migration possible.
With this change:
- an existing HTTP service can be hosted on the same listener as Triple
- both `mount-first` and `export-first` flows are supported
- HTTP-only startup on a Triple listener is supported
- Triple routes still take priority over mounted HTTP traffic
- mounted HTTP traffic acts as a transport-level fallback after Triple
route lookup
## Design
### 1. Add an optional protocol capability
Mounting an existing HTTP handler is not a generic server configuration
concern.
It is only meaningful for protocols that are actually implemented on top
of `net/http`.
For that reason, this PR introduces an optional protocol capability
instead of pushing an `http.Handler` into generic config structs:
```go
type HTTPHandlerMountable interface {
MountHTTPHandler(url *common.URL, handler http.Handler) error
}
```
This keeps HTTP mounting scoped to protocols that can actually host HTTP
traffic, rather than leaking transport-specific runtime state into generic
server configuration.
### 2. Model mounting as a single root handler
Mounting is intentionally modeled as a single root http.Handler.
That decision is deliberate. dubbo-go owns one shared listener, while
plain HTTP route composition should remain in user space. If a caller needs to
expose multiple HTTP services, they can compose them behind their own
http.ServeMux
or router and mount that mux once.
This keeps the boundary clear:
dubbo-go owns listener lifecycle and Triple routing
user code owns plain HTTP route composition
### 3. Reuse Triple as the transport host
This pr makes mount-first and export-first converge on the same shared
listener lifecycle.
This allows:
1. mounting an HTTP handler first, then exporting Triple services later
2. exporting Triple services first, then mounting an HTTP fallback later
3. running a mounted HTTP service on a Triple listener even when no Triple
service is exported yet
This avoids introducing a separate startup model just for mounted HTTP
traffic.
### 4. Preserve Triple route priority
Mounted HTTP traffic is intentionally implemented as a transport-level
fallback,
not as a competing routing layer.
The route mux resolves requests in this order:
1. exact Triple procedure match
2. method-name case-adapted Triple fallback
3. mounted HTTP fallback
A simplified version of the serving logic is:
```go
func (m *methodRouteMux) ServeHTTP(w http.ResponseWriter, r *http.Request)
{
handler, pattern := m.Handler(r)
if pattern != "" {
handler.ServeHTTP(w, r)
return
}
if fallback := m.fallback; fallback != nil {
fallback.ServeHTTP(w, r)
return
}
http.NotFound(w, r)
}
```
This ordering is important: mounting an existing HTTP service must not
preempt
registered Triple procedures on the same listener.
### 5. Validate listener-fixed transport settings
When the same Triple listener is reused, transport-level settings must
remain
consistent.
This pr validates and rejects conflicts for listener-fixed settings such
as:
HTTP/2 vs HTTP/3 transport mode
TLS configuration
Handler-level Triple options may still vary per exported service.
## Usage
```go
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request)
{
_, _ = w.Write([]byte("ok"))
})
mux.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("ready"))
})
srv, err := server.NewServer(
server.WithServerProtocol(
protocol.WithPort(20000),
protocol.WithTriple(),
),
)
if err != nil {
panic(err)
}
if err := srv.MountHTTPHandler(mux); err != nil {
panic(err)
}
// Triple services can still be registered as usual before Serve.
if err := srv.Serve(); err != nil {
panic(err)
}
```
## Checklist
- [x] I confirm the target branch is develop
- [x] Code has passed local testing
- [x] I have added tests that prove my fix is effective or that my feature
works
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]