From 873cba3e7cdecf33937e7bc28c966d81b8d97c78 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sat, 15 Feb 2025 10:19:44 +0800 Subject: {http_server,url}.go: Fix redirects r.URL.Path contains URL segments already decoded which makes it impossible to distinguish from an encoded %2F and a path separator /. We introduce redirect_with_slash which checks it properly. There is still an occurence of r.URL.Path in the commit handler, but that's going to get a major revamp anyway so I'm not bothering to fix that for now. :/ --- http_server.go | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'http_server.go') diff --git a/http_server.go b/http_server.go index 346ace3..e830fb1 100644 --- a/http_server.go +++ b/http_server.go @@ -32,8 +32,7 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) { if len(segments) < 2 { http.Error(w, "Blank system endpoint", http.StatusNotFound) return - } else if len(segments) == 2 && !trailing_slash { - http.Redirect(w, r, r.URL.Path+"/", http.StatusSeeOther) + } else if len(segments) == 2 && redirect_with_slash(w, r) { return } @@ -94,8 +93,7 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) { case non_empty_last_segments_len == separator_index+1: http.Error(w, "Group root hasn't been implemented yet", http.StatusNotImplemented) case non_empty_last_segments_len == separator_index+2: - if !trailing_slash { - http.Redirect(w, r, r.URL.Path+"/", http.StatusSeeOther) + if redirect_with_slash(w, r) { return } module_type := segments[separator_index+1] @@ -124,10 +122,9 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // TODO: subgroups if non_empty_last_segments_len == separator_index+3 { - if !trailing_slash { - http.Redirect(w, r, r.URL.Path+"/", http.StatusSeeOther) - return - } + if redirect_with_slash(w, r) { + return + } handle_repo_index(w, r, params) return } @@ -137,15 +134,13 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) { handle_repo_info(w, r, params) case "tree": params["rest"] = strings.Join(segments[separator_index+4:], "/") - if len(segments) < separator_index+5 { - http.Redirect(w, r, r.URL.Path+"/", http.StatusSeeOther) - return + if len(segments) < separator_index+5 && redirect_with_slash(w, r) { + return } handle_repo_tree(w, r, params) case "raw": params["rest"] = strings.Join(segments[separator_index+4:], "/") - if len(segments) < separator_index+5 { - http.Redirect(w, r, r.URL.Path+"/", http.StatusSeeOther) + if len(segments) < separator_index+5 && redirect_with_slash(w, r) { return } handle_repo_raw(w, r, params) @@ -154,14 +149,14 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, "Too many parameters", http.StatusBadRequest) return } - if !trailing_slash { - http.Redirect(w, r, r.URL.Path+"/", http.StatusSeeOther) + if redirect_with_slash(w, r) { return } handle_repo_log(w, r, params) case "commit": if trailing_slash { http.Redirect(w, r, strings.TrimSuffix(r.URL.Path, "/"), http.StatusSeeOther) + // TODO return } params["commit_id"] = segments[separator_index+4] -- cgit v1.2.3