aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--http_handle_group_index.go3
-rw-r--r--http_handle_repo_raw.go3
-rw-r--r--http_server.go29
-rw-r--r--lmtp_server.go3
-rw-r--r--misc/url.go (renamed from url.go)42
-rw-r--r--remote_url.go6
-rw-r--r--ssh_utils.go3
7 files changed, 48 insertions, 41 deletions
diff --git a/http_handle_group_index.go b/http_handle_group_index.go
index 67cffd8..568a38e 100644
--- a/http_handle_group_index.go
+++ b/http_handle_group_index.go
@@ -11,6 +11,7 @@ import (
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
+ "go.lindenii.runxiyu.org/forge/misc"
)
// httpHandleGroupIndex provides index pages for groups, which includes a list
@@ -130,7 +131,7 @@ func httpHandleGroupIndex(writer http.ResponseWriter, request *http.Request, par
return
}
- redirectUnconditionally(writer, request)
+ misc.RedirectUnconditionally(writer, request)
return
}
diff --git a/http_handle_repo_raw.go b/http_handle_repo_raw.go
index ea2925c..3a4e152 100644
--- a/http_handle_repo_raw.go
+++ b/http_handle_repo_raw.go
@@ -10,6 +10,7 @@ import (
"strings"
"go.lindenii.runxiyu.org/forge/git2c"
+ "go.lindenii.runxiyu.org/forge/misc"
)
// httpHandleRepoRaw serves raw files, or directory listings that point to raw
@@ -43,7 +44,7 @@ func httpHandleRepoRaw(writer http.ResponseWriter, request *http.Request, params
params["readme"] = template.HTML("<p>README rendering here is WIP again</p>") // TODO
renderTemplate(writer, "repo_raw_dir", params)
case content != "":
- if redirectNoDir(writer, request) {
+ if misc.RedirectNoDir(writer, request) {
return
}
writer.Header().Set("Content-Type", "application/octet-stream")
diff --git a/http_server.go b/http_server.go
index 5d45d00..3f8e36c 100644
--- a/http_server.go
+++ b/http_server.go
@@ -12,6 +12,7 @@ import (
"strings"
"github.com/jackc/pgx/v5"
+ "go.lindenii.runxiyu.org/forge/misc"
)
type forgeHTTPRouter struct{}
@@ -39,7 +40,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
var sepIndex int
params := make(map[string]any)
- if segments, _, err = parseReqURI(request.RequestURI); err != nil {
+ if segments, _, err = misc.ParseReqURI(request.RequestURI); err != nil {
errorPage400(writer, params, "Error parsing request URI: "+err.Error())
return
}
@@ -82,7 +83,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
if len(segments) < 2 {
errorPage404(writer, params)
return
- } else if len(segments) == 2 && redirectDir(writer, request) {
+ } else if len(segments) == 2 && misc.RedirectDir(writer, request) {
return
}
@@ -133,7 +134,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
switch {
case sepIndex == -1:
- if redirectDir(writer, request) {
+ if misc.RedirectDir(writer, request) {
return
}
httpHandleGroupIndex(writer, request, params)
@@ -165,8 +166,8 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
}
}
- if params["ref_type"], params["ref_name"], err = getParamRefTypeName(request); err != nil {
- if errors.Is(err, errNoRefSpec) {
+ if params["ref_type"], params["ref_name"], err = misc.GetParamRefTypeName(request); err != nil {
+ if errors.Is(err, misc.ErrNoRefSpec) {
params["ref_type"] = ""
} else {
errorPage400(writer, params, "Error querying ref type: "+err.Error())
@@ -189,7 +190,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
params["ssh_clone_url"] = genSSHRemoteURL(groupPath, moduleName)
if len(segments) == sepIndex+3 {
- if redirectDir(writer, request) {
+ if misc.RedirectDir(writer, request) {
return
}
httpHandleRepoIndex(writer, request, params)
@@ -199,7 +200,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
repoFeature := segments[sepIndex+3]
switch repoFeature {
case "tree":
- if anyContain(segments[sepIndex+4:], "/") {
+ if misc.AnyContain(segments[sepIndex+4:], "/") {
errorPage400(writer, params, "Repo tree paths may not contain slashes in any segments")
return
}
@@ -208,18 +209,18 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
} else {
params["rest"] = strings.Join(segments[sepIndex+4:], "/")
}
- if len(segments) < sepIndex+5 && redirectDir(writer, request) {
+ if len(segments) < sepIndex+5 && misc.RedirectDir(writer, request) {
return
}
httpHandleRepoTree(writer, request, params)
case "branches":
- if redirectDir(writer, request) {
+ if misc.RedirectDir(writer, request) {
return
}
httpHandleRepoBranches(writer, request, params)
return
case "raw":
- if anyContain(segments[sepIndex+4:], "/") {
+ if misc.AnyContain(segments[sepIndex+4:], "/") {
errorPage400(writer, params, "Repo tree paths may not contain slashes in any segments")
return
}
@@ -228,7 +229,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
} else {
params["rest"] = strings.Join(segments[sepIndex+4:], "/")
}
- if len(segments) < sepIndex+5 && redirectDir(writer, request) {
+ if len(segments) < sepIndex+5 && misc.RedirectDir(writer, request) {
return
}
httpHandleRepoRaw(writer, request, params)
@@ -237,7 +238,7 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
errorPage400(writer, params, "Too many parameters")
return
}
- if redirectDir(writer, request) {
+ if misc.RedirectDir(writer, request) {
return
}
httpHandleRepoLog(writer, request, params)
@@ -246,13 +247,13 @@ func (router *forgeHTTPRouter) ServeHTTP(writer http.ResponseWriter, request *ht
errorPage400(writer, params, "Incorrect number of parameters")
return
}
- if redirectNoDir(writer, request) {
+ if misc.RedirectNoDir(writer, request) {
return
}
params["commit_id"] = segments[sepIndex+4]
httpHandleRepoCommit(writer, request, params)
case "contrib":
- if redirectDir(writer, request) {
+ if misc.RedirectDir(writer, request) {
return
}
switch len(segments) {
diff --git a/lmtp_server.go b/lmtp_server.go
index cdfcffb..fc3d92d 100644
--- a/lmtp_server.go
+++ b/lmtp_server.go
@@ -17,6 +17,7 @@ import (
"github.com/emersion/go-message"
"github.com/emersion/go-smtp"
+ "go.lindenii.runxiyu.org/forge/misc"
)
type lmtpHandler struct{}
@@ -136,7 +137,7 @@ func (session *lmtpSession) Data(r io.Reader) error {
}
localPart := to[:len(to)-len("@"+config.LMTP.Domain)]
var segments []string
- segments, err = pathToSegments(localPart)
+ segments, err = misc.PathToSegments(localPart)
if err != nil {
// TODO: Should the entire email fail or should we just
// notify them out of band?
diff --git a/url.go b/misc/url.go
index ad5c8bb..b77d8ce 100644
--- a/url.go
+++ b/misc/url.go
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package main
+package misc
import (
"errors"
@@ -11,13 +11,13 @@ import (
)
var (
- errDupRefSpec = errors.New("duplicate ref spec")
- errNoRefSpec = errors.New("no ref spec")
+ ErrDupRefSpec = errors.New("duplicate ref spec")
+ ErrNoRefSpec = errors.New("no ref spec")
)
// getParamRefTypeName looks at the query parameters in an HTTP request and
// returns its ref name and type, if any.
-func getParamRefTypeName(request *http.Request) (retRefType, retRefName string, err error) {
+func GetParamRefTypeName(request *http.Request) (retRefType, retRefName string, err error) {
rawQuery := request.URL.RawQuery
queryValues, err := url.ParseQuery(rawQuery)
if err != nil {
@@ -28,12 +28,12 @@ func getParamRefTypeName(request *http.Request) (retRefType, retRefName string,
refName, ok := queryValues[refType]
if ok {
if done {
- err = errDupRefSpec
+ err = ErrDupRefSpec
return
}
done = true
if len(refName) != 1 {
- err = errDupRefSpec
+ err = ErrDupRefSpec
return
}
retRefName = refName[0]
@@ -41,17 +41,17 @@ func getParamRefTypeName(request *http.Request) (retRefType, retRefName string,
}
}
if !done {
- err = errNoRefSpec
+ err = ErrNoRefSpec
}
return
}
-// parseReqURI parses an HTTP request URL, and returns a slice of path segments
+// ParseReqURI parses an HTTP request URL, and returns a slice of path segments
// and the query parameters. It handles %2F correctly.
-func parseReqURI(requestURI string) (segments []string, params url.Values, err error) {
+func ParseReqURI(requestURI string) (segments []string, params url.Values, err error) {
path, paramsStr, _ := strings.Cut(requestURI, "?")
- segments, err = pathToSegments(path)
+ segments, err = PathToSegments(path)
if err != nil {
return
}
@@ -60,7 +60,7 @@ func parseReqURI(requestURI string) (segments []string, params url.Values, err e
return
}
-func pathToSegments(path string) (segments []string, err error) {
+func PathToSegments(path string) (segments []string, err error) {
segments = strings.Split(strings.TrimPrefix(path, "/"), "/")
for i, segment := range segments {
@@ -73,10 +73,10 @@ func pathToSegments(path string) (segments []string, err error) {
return
}
-// redirectDir returns true and redirects the user to a version of the URL with
+// RedirectDir returns true and redirects the user to a version of the URL with
// a trailing slash, if and only if the request URL does not already have a
// trailing slash.
-func redirectDir(writer http.ResponseWriter, request *http.Request) bool {
+func RedirectDir(writer http.ResponseWriter, request *http.Request) bool {
requestURI := request.RequestURI
pathEnd := strings.IndexAny(requestURI, "?#")
@@ -95,10 +95,10 @@ func redirectDir(writer http.ResponseWriter, request *http.Request) bool {
return false
}
-// redirectNoDir returns true and redirects the user to a version of the URL
+// RedirectNoDir returns true and redirects the user to a version of the URL
// without a trailing slash, if and only if the request URL has a trailing
// slash.
-func redirectNoDir(writer http.ResponseWriter, request *http.Request) bool {
+func RedirectNoDir(writer http.ResponseWriter, request *http.Request) bool {
requestURI := request.RequestURI
pathEnd := strings.IndexAny(requestURI, "?#")
@@ -117,9 +117,9 @@ func redirectNoDir(writer http.ResponseWriter, request *http.Request) bool {
return false
}
-// redirectUnconditionally unconditionally redirects the user back to the
+// RedirectUnconditionally unconditionally redirects the user back to the
// current page while preserving query parameters.
-func redirectUnconditionally(writer http.ResponseWriter, request *http.Request) {
+func RedirectUnconditionally(writer http.ResponseWriter, request *http.Request) {
requestURI := request.RequestURI
pathEnd := strings.IndexAny(requestURI, "?#")
@@ -134,17 +134,17 @@ func redirectUnconditionally(writer http.ResponseWriter, request *http.Request)
http.Redirect(writer, request, path+rest, http.StatusSeeOther)
}
-// segmentsToURL joins URL segments to the path component of a URL.
+// SegmentsToURL joins URL segments to the path component of a URL.
// Each segment is escaped properly first.
-func segmentsToURL(segments []string) string {
+func SegmentsToURL(segments []string) string {
for i, segment := range segments {
segments[i] = url.PathEscape(segment)
}
return strings.Join(segments, "/")
}
-// anyContain returns true if and only if ss contains a string that contains c.
-func anyContain(ss []string, c string) bool {
+// AnyContain returns true if and only if ss contains a string that contains c.
+func AnyContain(ss []string, c string) bool {
for _, s := range ss {
if strings.Contains(s, c) {
return true
diff --git a/remote_url.go b/remote_url.go
index 5c980f5..f227dbf 100644
--- a/remote_url.go
+++ b/remote_url.go
@@ -6,6 +6,8 @@ package main
import (
"net/url"
"strings"
+
+ "go.lindenii.runxiyu.org/forge/misc"
)
// We don't use path.Join because it collapses multiple slashes into one.
@@ -13,11 +15,11 @@ import (
// genSSHRemoteURL generates SSH remote URLs from a given group path and repo
// name.
func genSSHRemoteURL(groupPath []string, repoName string) string {
- return strings.TrimSuffix(config.SSH.Root, "/") + "/" + segmentsToURL(groupPath) + "/-/repos/" + url.PathEscape(repoName)
+ return strings.TrimSuffix(config.SSH.Root, "/") + "/" + misc.SegmentsToURL(groupPath) + "/-/repos/" + url.PathEscape(repoName)
}
// genHTTPRemoteURL generates HTTP remote URLs from a given group path and repo
// name.
func genHTTPRemoteURL(groupPath []string, repoName string) string {
- return strings.TrimSuffix(config.HTTP.Root, "/") + "/" + segmentsToURL(groupPath) + "/-/repos/" + url.PathEscape(repoName)
+ return strings.TrimSuffix(config.HTTP.Root, "/") + "/" + misc.SegmentsToURL(groupPath) + "/-/repos/" + url.PathEscape(repoName)
}
diff --git a/ssh_utils.go b/ssh_utils.go
index 476fc31..c906ab3 100644
--- a/ssh_utils.go
+++ b/ssh_utils.go
@@ -11,6 +11,7 @@ import (
"net/url"
"go.lindenii.runxiyu.org/forge/ansiec"
+ "go.lindenii.runxiyu.org/forge/misc"
)
var errIllegalSSHRepoPath = errors.New("illegal SSH repo path")
@@ -22,7 +23,7 @@ func getRepoInfo2(ctx context.Context, sshPath, sshPubkey string) (groupPath []s
var sepIndex int
var moduleType, moduleName string
- segments, err = pathToSegments(sshPath)
+ segments, err = misc.PathToSegments(sshPath)
if err != nil {
return
}