golang/go

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

Playground link

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.