geektutu/7days-golang · error

HTTPPool serving unexpected path: " + r.URL.Path

Error message

HTTPPool serving unexpected path: " + r.URL.Path

What it means

HTTPPool.ServeHTTP panics when the request path does not start with the pool's basePath (default "/_geecache/"). The handler is designed to serve only the internal peer-to-peer cache API at /<basePath>/<group>/<key>, so any foreign path is treated as a deployment/routing misconfiguration and panics immediately. Legitimate requests on the right prefix with a missing group/key get a 400 instead.

Source

Thrown at gee-cache/day3-http-server/geecache/http.go:35

}

// NewHTTPPool initializes an HTTP pool of peers.
func NewHTTPPool(self string) *HTTPPool {
	return &HTTPPool{
		self:     self,
		basePath: defaultBasePath,
	}
}

// Log info with server name
func (p *HTTPPool) Log(format string, v ...interface{}) {
	log.Printf("[Server %s] %s", p.self, fmt.Sprintf(format, v...))
}

// ServeHTTP handle all http requests
func (p *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !strings.HasPrefix(r.URL.Path, p.basePath) {
		panic("HTTPPool serving unexpected path: " + r.URL.Path)
	}
	p.Log("%s %s", r.Method, r.URL.Path)
	// /<basepath>/<groupname>/<key> required
	parts := strings.SplitN(r.URL.Path[len(p.basePath):], "/", 2)
	if len(parts) != 2 {
		http.Error(w, "bad request", http.StatusBadRequest)
		return
	}

	groupName := parts[0]
	key := parts[1]

	group := GetGroup(groupName)
	if group == nil {
		http.Error(w, "no such group: "+groupName, http.StatusNotFound)
		return
	}

View on GitHub (pinned to cf36443821)

Solutions

  1. Serve the pool only at its basePath: http.Handle("/_geecache/", pool)
  2. Point health checks/probes at a separate handler or a path under /_geecache/
  3. Fix proxy rewrite rules so the /_geecache/ prefix is preserved to ServeHTTP
  4. Ensure client-side HTTPPool uses the same base path as the server

Example fix

// before
http.Handle("/", pool) // any path like / or /health panics
// after
http.Handle("/_geecache/", pool)
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) })
Defensive patterns

Strategy: validation

Validate before calling

if !strings.HasPrefix(r.URL.Path, "/_geecache/") {
    http.NotFound(w, r)
    return
}
pool.ServeHTTP(w, r)

Try / catch

// Prefer not to route foreign paths to the pool. If you must wrap it:
func safeServe(p *geecache.HTTPPool, w http.ResponseWriter, r *http.Request) {
    defer func() {
        if rec := recover(); rec != nil {
            if s, ok := rec.(string); ok && strings.Contains(s, "unexpected path") {
                http.NotFound(w, r)
                return
            }
            panic(rec)
        }
    }()
    p.ServeHTTP(w, r)
}

Prevention

When it happens

Trigger: Registering the HTTPPool on a mux that receives requests outside p.basePath — e.g. http.Handle("/", pool), health checks hitting "/", a proxy stripping the /_geecache/ prefix before forwarding, or a client omitting the base path in its URL.

Common situations: Mounting the cache server behind a reverse proxy with a rewrite rule that drops the prefix; load balancer health probes on "/"; a client (NewHTTPPool on the fetch side) configured with a different basePath than the server.

Related errors


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/5838a1cde5d0a2c0. Report an issue: GitHub.