{"record":{"id":"56f79ed82fd11cf1","repo":"geektutu/7days-golang","slug":"bad-request-56f79e","errorCode":null,"errorMessage":"bad request","messagePattern":"bad request","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"gee-cache/day4-consistent-hash/geecache/http.go","lineNumber":41,"sourceCode":"\t\tbasePath: defaultBasePath,\n\t}\n}\n\n// Log info with server name\nfunc (p *HTTPPool) Log(format string, v ...interface{}) {\n\tlog.Printf(\"[Server %s] %s\", p.self, fmt.Sprintf(format, v...))\n}\n\n// ServeHTTP handle all http requests\nfunc (p *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tif !strings.HasPrefix(r.URL.Path, p.basePath) {\n\t\tpanic(\"HTTPPool serving unexpected path: \" + r.URL.Path)\n\t}\n\tp.Log(\"%s %s\", r.Method, r.URL.Path)\n\t// /<basepath>/<groupname>/<key> required\n\tparts := strings.SplitN(r.URL.Path[len(p.basePath):], \"/\", 2)\n\tif len(parts) != 2 {\n\t\thttp.Error(w, \"bad request\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tgroupName := parts[0]\n\tkey := parts[1]\n\n\tgroup := GetGroup(groupName)\n\tif group == nil {\n\t\thttp.Error(w, \"no such group: \"+groupName, http.StatusNotFound)\n\t\treturn\n\t}\n\n\tview, err := group.Get(key)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-cache/day4-consistent-hash/geecache/http.go#L23-L59","documentation":"Same as the day3 'bad request': HTTPPool.ServeHTTP (day4-consistent-hash version) requires /<basePath>/<groupName>/<key>. When SplitN yields fewer than 2 parts after basePath, it replies 400 'bad request'.","triggerScenarios":"Request path such as /_geecache/ or /_geecache/mygroup — after basePath there aren't two '/'-separated segments.","commonSituations":"Load-balancer health probes hitting the cache endpoint; client omitting the key; proxy path rewriting dropping a segment; manual curl tests with an incomplete URL.","solutions":["Use the full path /<basePath>/<group>/<key> in requests.","Point health checks at a separate route/handler, not the geecache HTTPPool.","Check ingress/proxy rewrite rules for stripped path segments.","If keys may contain '/', percent-encode them so the split yields exactly group and key."],"exampleFix":"// before\nGET /_geecache/groups\n// after\nGET /_geecache/groups/mykey","handlingStrategy":"validation","validationCode":"// validate path shape before requesting (day4 node)\nfunc validCacheURL(base, group, key string) bool {\n    return group != \"\" && key != \"\" && !strings.ContainsAny(key, \"/?#\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Construct URLs strictly as basePath/group/key with url.PathEscape on the key.","Keep health probes off the geecache HTTPPool route.","Review proxy rewrite rules after day3→day4 upgrades so paths aren't mangled.","Test with a curl smoke check of one full /group/key path in CI."],"tags":["http","cache","bad-request","url-parsing"],"backgroundTag":"malformed-request-path","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}