net/rpc: Server.ServeHTTP assumes default http mux
mbertschler opened this issue · 4 comments
rpc.Server.ServeHTTP()
calls http.Handle(rpcPath, server)
and registers with http.DefaultServeMux
. The second call to ServeHTTP() with the default names normally results in panic: http: multiple registrations for /_goRPC_
. This means that if I want to start two different RPC endpoints on different ports I have to work around this library.
Solution with workaround
package main
import (
"fmt"
"net"
"net/http"
"net/rpc"
)
func main() {
Serve("one", ":2001")
Serve("two", ":2002")
Call(":2001")
Call(":2002")
}
func Call(port string) {
client, err := rpc.DialHTTP("tcp", port)
if err != nil {
fmt.Println(err)
}
var name string
err = client.Call("Server.Name", struct{}{}, &name)
if err != nil {
fmt.Println(err)
}
fmt.Println("Server name on port", port, "is", name)
}
func Serve(name, port string) {
serv := rpc.NewServer()
s := Server{name}
serv.Register(&s)
// ===== workaround ==========
oldMux := http.DefaultServeMux
mux := http.NewServeMux()
http.DefaultServeMux = mux
// ===========================
serv.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)
// ===== workaround ==========
http.DefaultServeMux = oldMux
// ===========================
l, err := net.Listen("tcp", port)
if err != nil {
panic(err)
}
go http.Serve(l, mux)
}
// RPC Server
type Server struct {
name string
}
func (s *Server) Name(arg struct{}, ret *string) error {
*ret = s.name
return nil
}
Maybe the API could be improved for a future version to support that use case without a workaround.
Like a ServeHTTPMux()
that additionally takes a http.ServeMux
Go is go version go1.5.1 darwin/amd64
+1 this saved my ass, thanks
CL https://golang.org/cl/20020 mentions this issue.
I think the net/rpc package is frozen. I don't think we'll be making any API additions to it. Sorry.
@bradfitz hmm okay, I understand. At least there is a pretty straightforward workaround, and it is probably not something a lot of people need.