{"record":{"id":"655590e0667f01c3","repo":"geektutu/7days-golang","slug":"bad-request-655590","errorCode":null,"errorMessage":"bad request","messagePattern":"bad request","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"gee-cache/day5-multi-nodes/geecache/http.go","lineNumber":51,"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":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-cache/day5-multi-nodes/geecache/http.go#L33-L69","documentation":"HTTP 400 response in HTTPPool.ServeHTTP: the URL path after basePath does not split into exactly two parts \"<groupname>/<key>\", meaning the request path is malformed for the peer protocol. It fires on requests missing the key segment or containing extra slashes.","triggerScenarios":"Requests like GET /_geecache/ or GET /_geecache/group without a key segment.","commonSituations":"Health probes against the cache route; clients forgetting the key; proxies stripping part of the URL; ad-hoc curl testing with incomplete paths.","solutions":["Request the full /<basePath>/<group>/<key> URL.","Use a dedicated health endpoint instead of the geecache pool for probes.","Audit proxy/ingress rewrite rules.","Encode '/' inside keys so SplitN produces exactly two parts."],"exampleFix":"// before\nGET /_geecache/users\n// after\nGET /_geecache/users/42","handlingStrategy":"validation","validationCode":"// day5: enforce URL shape client-side\nfunc buildCacheURL(base, group, key string) (string, error) {\n    if group == \"\" || key == \"\" || strings.Contains(key, \"/\") {\n        return \"\", fmt.Errorf(\"invalid cache path: group=%q key=%q\", group, key)\n    }\n    return base + \"/\" + group + \"/\" + url.PathEscape(key), nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always send /basePath/group/key — never bare group paths.","Route health probes to a non-cache endpoint.","Escape keys; reject empty group/key before building the URL.","Add a smoke test hitting one full cache path in deployment pipelines."],"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"}