68 lines
1.8 KiB
Go
68 lines
1.8 KiB
Go
|
// Copyright (C) 2024 Umorpha Systems
|
||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"regexp"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// - /HEAD
|
||
|
// - /objects/[0-9a-f]{2}/[0-9a-f]{38}
|
||
|
// - /objects/pack/
|
||
|
// - /objects/info/packs (*)
|
||
|
// - /objects/info/alternates
|
||
|
// - /objects/info/http-alternates
|
||
|
// - /info/refs (*)
|
||
|
|
||
|
|
||
|
var reGitHTTP = regexp.MustCompile(`^.*/(?:` +
|
||
|
`HEAD` + `|` +
|
||
|
`objects(?:/[/a-z0-9]*)?` + `|` +
|
||
|
`info/refs(?:[?&](?:service=[-_a-z0-9]+)$` + `)` +
|
||
|
`)$`)
|
||
|
|
||
|
// routeGitHTTP takes a gitprotocol-http(5) request and parses it into
|
||
|
// a repoPath component and a service query component.
|
||
|
//
|
||
|
// - Returns ("", "", "", nil) if the request does not look like a
|
||
|
// gitprotocol-http(5) request.
|
||
|
//
|
||
|
// Returns ("", "", err) if the request looks like a
|
||
|
// gitprotocol-http(5) request, but has a malformed query string.
|
||
|
func routeGitHTTP(r *http.Request) (repoPath, file, service string, err error) {
|
||
|
idx := strings.LastIndex(r.RequestURI, "/info/refs")
|
||
|
if idx < 0 {
|
||
|
return "", "", "", nil
|
||
|
}
|
||
|
|
||
|
repoPath = r.RequestURI[:idx]
|
||
|
rawQuery := r.RequestURI[idx+len("/info/refs"):]
|
||
|
var query url.Values
|
||
|
if rawQuery != "" {
|
||
|
queryPrefix := "?"
|
||
|
if strings.Contains(repoPath, "?") {
|
||
|
queryPrefix = "&"
|
||
|
}
|
||
|
if !strings.HasPrefix(rawQuery, queryPrefix) {
|
||
|
return "", "", "", nil
|
||
|
}
|
||
|
var err error
|
||
|
query, err = url.ParseQuery(rawQuery[len(queryPrefix):])
|
||
|
if err != nil {
|
||
|
return "", "", "", fmt.Errorf("invalid query string: %w", err)
|
||
|
}
|
||
|
if len(query) > 1 || len(query["service"]) > 1 {
|
||
|
return "", "", "", fmt.Errorf("invalid query string: too many query parameters")
|
||
|
}
|
||
|
if len(query) > 0 && query["service"] == nil {
|
||
|
return "", "", "", fmt.Errorf("invalid query string: unexpected query parameters")
|
||
|
}
|
||
|
}
|
||
|
return repoPath, "TODO", query.Get("service"), nil
|
||
|
}
|