Commit 4d4c1f02 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Don't use ServerMux due to URI normalization: we do it our own way

parent 3be3f01d
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"syscall" "syscall"
"path"
) )
func fail500(w http.ResponseWriter, err error) { func fail500(w http.ResponseWriter, err error) {
...@@ -23,6 +24,13 @@ func logError(err error) { ...@@ -23,6 +24,13 @@ func logError(err error) {
log.Printf("error: %v", err) log.Printf("error: %v", err)
} }
func httpError(w http.ResponseWriter, r *http.Request, error string, code int) {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
http.Error(w, error, code)
}
// Git subprocess helpers // Git subprocess helpers
func gitCommand(gl_id string, name string, args ...string) *exec.Cmd { func gitCommand(gl_id string, name string, args ...string) *exec.Cmd {
cmd := exec.Command(name, args...) cmd := exec.Command(name, args...)
...@@ -90,3 +98,21 @@ func openFile(path string) (file *os.File, fi os.FileInfo, err error) { ...@@ -90,3 +98,21 @@ func openFile(path string) (file *os.File, fi os.FileInfo, err error) {
return return
} }
// Borrowed from: net/http/server.go
// Return the canonical path for p, eliminating . and .. elements.
func cleanURIPath(p string) string {
if p == "" {
return "/"
}
if p[0] != '/' {
p = "/" + p
}
np := path.Clean(p)
// path.Clean removes trailing slash except for root;
// put the trailing slash back if necessary.
if p[len(p)-1] == '/' && np != "/" {
np += "/"
}
return np
}
...@@ -171,10 +171,5 @@ func main() { ...@@ -171,10 +171,5 @@ func main() {
upstream := newUpstream(*authBackend, proxyTransport) upstream := newUpstream(*authBackend, proxyTransport)
upstream.SetRelativeURLRoot(*relativeURLRoot) upstream.SetRelativeURLRoot(*relativeURLRoot)
log.Fatal(http.Serve(listener, upstream))
// Because net/http/pprof installs itself in the DefaultServeMux
// we create a fresh one for the Git server.
serveMux := http.NewServeMux()
serveMux.Handle(upstream.relativeURLRoot, upstream)
log.Fatal(http.Serve(listener, serveMux))
} }
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"strings" "strings"
"fmt"
) )
type serviceHandleFunc func(w http.ResponseWriter, r *gitRequest) type serviceHandleFunc func(w http.ResponseWriter, r *gitRequest)
...@@ -92,10 +93,29 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) { ...@@ -92,10 +93,29 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
w := newLoggingResponseWriter(ow) w := newLoggingResponseWriter(ow)
defer w.Log(r) defer w.Log(r)
// Drop WebSocket connection and CONNECT method
if r.RequestURI == "*" {
httpError(&w, r, "Connection upgrade not allowed", http.StatusBadRequest)
return
}
// Disallow connect
if r.Method == "CONNECT" {
httpError(&w, r, "CONNECT not allowed", http.StatusBadRequest)
return
}
// Check URL Root
URIPath := cleanURIPath(r.URL.Path)
if !strings.HasPrefix(URIPath, u.relativeURLRoot) {
httpError(&w, r, fmt.Sprintf("Not found %q", URIPath), http.StatusNotFound)
return
}
// Strip prefix and add "/" // Strip prefix and add "/"
// To match against non-relative URL // To match against non-relative URL
// Making it simpler for our matcher // Making it simpler for our matcher
relativeURIPath := "/" + strings.TrimPrefix(r.URL.Path, u.relativeURLRoot) relativeURIPath := cleanURIPath(strings.TrimPrefix(URIPath, u.relativeURLRoot))
// Look for a matching Git service // Look for a matching Git service
foundService := false foundService := false
...@@ -112,7 +132,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) { ...@@ -112,7 +132,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
if !foundService { if !foundService {
// The protocol spec in git/Documentation/technical/http-protocol.txt // The protocol spec in git/Documentation/technical/http-protocol.txt
// says we must return 403 if no matching service is found. // says we must return 403 if no matching service is found.
http.Error(&w, "Forbidden", 403) httpError(&w, r, "Forbidden", http.StatusForbidden)
return return
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment