Commit 4194124c authored by Jacob Vosmaer's avatar Jacob Vosmaer

Move routes into upstream

parent 9e17fc4c
...@@ -14,8 +14,6 @@ In this file we start the web server and hand off to the upstream type. ...@@ -14,8 +14,6 @@ In this file we start the web server and hand off to the upstream type.
package main package main
import ( import (
"./internal/errorpage"
"./internal/git"
"flag" "flag"
"fmt" "fmt"
"log" "log"
...@@ -23,7 +21,6 @@ import ( ...@@ -23,7 +21,6 @@ import (
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
"regexp"
"syscall" "syscall"
"time" "time"
) )
...@@ -42,82 +39,6 @@ var documentRoot = flag.String("documentRoot", "public", "Path to static files c ...@@ -42,82 +39,6 @@ var documentRoot = flag.String("documentRoot", "public", "Path to static files c
var responseHeadersTimeout = flag.Duration("proxyHeadersTimeout", time.Minute, "How long to wait for response headers when proxying the request") var responseHeadersTimeout = flag.Duration("proxyHeadersTimeout", time.Minute, "How long to wait for response headers when proxying the request")
var developmentMode = flag.Bool("developmentMode", false, "Allow to serve assets from Rails app") var developmentMode = flag.Bool("developmentMode", false, "Allow to serve assets from Rails app")
type httpRoute struct {
method string
regex *regexp.Regexp
handler http.Handler
}
const projectPattern = `^/[^/]+/[^/]+/`
const gitProjectPattern = `^/[^/]+/[^/]+\.git/`
const apiPattern = `^/api/`
const projectsAPIPattern = `^/api/v3/projects/[^/]+/`
const ciAPIPattern = `^/ci/api/`
// Routing table
// We match against URI not containing the relativeUrlRoot:
// see upstream.ServeHTTP
var httpRoutes []httpRoute
func compileRoutes(u *upstream) {
api := u.API
proxy := u.Proxy
httpRoutes = []httpRoute{
// Git Clone
httpRoute{"GET", regexp.MustCompile(gitProjectPattern + `info/refs\z`), git.GetInfoRefs(api)},
httpRoute{"POST", regexp.MustCompile(gitProjectPattern + `git-upload-pack\z`), contentEncodingHandler(git.PostRPC(api))},
httpRoute{"POST", regexp.MustCompile(gitProjectPattern + `git-receive-pack\z`), contentEncodingHandler(git.PostRPC(api))},
httpRoute{"PUT", regexp.MustCompile(gitProjectPattern + `gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`), lfsAuthorizeHandler(api, handleStoreLfsObject(proxy))},
// Repository Archive
httpRoute{"GET", regexp.MustCompile(projectPattern + `repository/archive\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectPattern + `repository/archive.zip\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectPattern + `repository/archive.tar\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectPattern + `repository/archive.tar.gz\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectPattern + `repository/archive.tar.bz2\z`), git.GetArchive(api)},
// Repository Archive API
httpRoute{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.zip\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar.gz\z`), git.GetArchive(api)},
httpRoute{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar.bz2\z`), git.GetArchive(api)},
// CI Artifacts API
httpRoute{"POST", regexp.MustCompile(ciAPIPattern + `v1/builds/[0-9]+/artifacts\z`), contentEncodingHandler(artifactsAuthorizeHandler(api, handleFileUploads(proxy)))},
// Explicitly proxy API requests
httpRoute{"", regexp.MustCompile(apiPattern), proxy},
httpRoute{"", regexp.MustCompile(ciAPIPattern), proxy},
// Serve assets
httpRoute{"", regexp.MustCompile(`^/assets/`),
u.handleServeFile(documentRoot, CacheExpireMax,
handleDevelopmentMode(developmentMode,
handleDeployPage(documentRoot,
errorpage.Inject(*documentRoot,
proxy,
),
),
),
),
},
// Serve static files or forward the requests
httpRoute{"", nil,
u.handleServeFile(documentRoot, CacheDisabled,
handleDeployPage(documentRoot,
errorpage.Inject(*documentRoot,
proxy,
),
),
),
},
}
}
func main() { func main() {
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
...@@ -159,7 +80,5 @@ func main() { ...@@ -159,7 +80,5 @@ func main() {
}() }()
} }
upstream := newUpstream(*authBackend, *authSocket) log.Fatal(http.Serve(listener, newUpstream(*authBackend, *authSocket)))
compileRoutes(upstream)
log.Fatal(http.Serve(listener, upstream))
} }
...@@ -328,7 +328,6 @@ func testAuthServer(url *regexp.Regexp, code int, body interface{}) *httptest.Se ...@@ -328,7 +328,6 @@ func testAuthServer(url *regexp.Regexp, code int, body interface{}) *httptest.Se
func startWorkhorseServer(authBackend string) *httptest.Server { func startWorkhorseServer(authBackend string) *httptest.Server {
u := newUpstream(authBackend, "") u := newUpstream(authBackend, "")
compileRoutes(u)
return httptest.NewServer(u) return httptest.NewServer(u)
} }
......
...@@ -8,12 +8,15 @@ package main ...@@ -8,12 +8,15 @@ package main
import ( import (
"./internal/api" "./internal/api"
"./internal/errorpage"
"./internal/git"
"./internal/proxy" "./internal/proxy"
"fmt" "fmt"
"log" "log"
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"regexp"
"strings" "strings"
"time" "time"
) )
...@@ -23,6 +26,81 @@ type upstream struct { ...@@ -23,6 +26,81 @@ type upstream struct {
Proxy *proxy.Proxy Proxy *proxy.Proxy
authBackend string authBackend string
relativeURLRoot string relativeURLRoot string
routes []route
}
type route struct {
method string
regex *regexp.Regexp
handler http.Handler
}
const projectPattern = `^/[^/]+/[^/]+/`
const gitProjectPattern = `^/[^/]+/[^/]+\.git/`
const apiPattern = `^/api/`
const projectsAPIPattern = `^/api/v3/projects/[^/]+/`
const ciAPIPattern = `^/ci/api/`
// Routing table
// We match against URI not containing the relativeUrlRoot:
// see upstream.ServeHTTP
var routes []route
func (u *upstream) compileRoutes() {
u.routes = []route{
// Git Clone
route{"GET", regexp.MustCompile(gitProjectPattern + `info/refs\z`), git.GetInfoRefs(u.API)},
route{"POST", regexp.MustCompile(gitProjectPattern + `git-upload-pack\z`), contentEncodingHandler(git.PostRPC(u.API))},
route{"POST", regexp.MustCompile(gitProjectPattern + `git-receive-pack\z`), contentEncodingHandler(git.PostRPC(u.API))},
route{"PUT", regexp.MustCompile(gitProjectPattern + `gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`), lfsAuthorizeHandler(u.API, handleStoreLfsObject(u.Proxy))},
// Repository Archive
route{"GET", regexp.MustCompile(projectPattern + `repository/archive\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectPattern + `repository/archive.zip\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectPattern + `repository/archive.tar\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectPattern + `repository/archive.tar.gz\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectPattern + `repository/archive.tar.bz2\z`), git.GetArchive(u.API)},
// Repository Archive API
route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.zip\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar.gz\z`), git.GetArchive(u.API)},
route{"GET", regexp.MustCompile(projectsAPIPattern + `repository/archive.tar.bz2\z`), git.GetArchive(u.API)},
// CI Artifacts API
route{"POST", regexp.MustCompile(ciAPIPattern + `v1/builds/[0-9]+/artifacts\z`), contentEncodingHandler(artifactsAuthorizeHandler(u.API, handleFileUploads(u.Proxy)))},
// Explicitly u.Proxy API requests
route{"", regexp.MustCompile(apiPattern), u.Proxy},
route{"", regexp.MustCompile(ciAPIPattern), u.Proxy},
// Serve assets
route{"", regexp.MustCompile(`^/assets/`),
u.handleServeFile(documentRoot, CacheExpireMax,
handleDevelopmentMode(developmentMode,
handleDeployPage(documentRoot,
errorpage.Inject(*documentRoot,
u.Proxy,
),
),
),
),
},
// Serve static files or forward the requests
route{"", nil,
u.handleServeFile(documentRoot, CacheDisabled,
handleDeployPage(documentRoot,
errorpage.Inject(*documentRoot,
u.Proxy,
),
),
),
},
}
} }
func newUpstream(authBackend string, authSocket string) *upstream { func newUpstream(authBackend string, authSocket string) *upstream {
...@@ -63,7 +141,7 @@ func newUpstream(authBackend string, authSocket string) *upstream { ...@@ -63,7 +141,7 @@ func newUpstream(authBackend string, authSocket string) *upstream {
Proxy: proxy.NewProxy(parsedURL, proxyTransport, Version), Proxy: proxy.NewProxy(parsedURL, proxyTransport, Version),
relativeURLRoot: relativeURLRoot, relativeURLRoot: relativeURLRoot,
} }
up.compileRoutes()
return up return up
} }
...@@ -72,7 +150,7 @@ func (u *upstream) relativeURIPath(p string) string { ...@@ -72,7 +150,7 @@ func (u *upstream) relativeURIPath(p string) string {
} }
func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) { func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
var g httpRoute var g route
w := newLoggingResponseWriter(ow) w := newLoggingResponseWriter(ow)
defer w.Log(r) defer w.Log(r)
...@@ -98,7 +176,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) { ...@@ -98,7 +176,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
// Look for a matching Git service // Look for a matching Git service
foundService := false foundService := false
for _, g = range httpRoutes { for _, g = range u.routes {
if g.method != "" && r.Method != g.method { if g.method != "" && r.Method != g.method {
continue continue
} }
......
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