forgejo-pages-proxy/router.go
Arija A. dcd67d3689
Add routing to pages branch
Signed-off-by: Arija A. <ari@ari.lt>
2026-05-30 21:48:36 +03:00

124 lines
3.3 KiB
Go

// Copyright (C) 2026 VšĮ „0011.LT"
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 ONLY.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
package main
import (
"path"
"strings"
)
func is_pages_path(request_path string) bool {
if request_path == "" || request_path == "/" {
return false
}
path_segments := strings.Split(strings.Trim(request_path, "/"), "/")
return len(path_segments) >= 1 && path_segments[0] != ""
}
func build_upstream_paths(request_path string) ([]string, bool) {
trimmed_request_path := strings.Trim(request_path, "/")
if trimmed_request_path == "" {
return nil, false
}
path_segments := strings.Split(trimmed_request_path, "/")
user_name := path_segments[0]
var repo_name string
var remainder_segments []string
if len(path_segments) == 1 {
// Path is just "/username" -> assume "/username/.webpage"
repo_name = ".webpage"
remainder_segments = []string{}
} else {
// Path is "/username/repo/..."
repo_name = path_segments[1]
remainder_segments = path_segments[2:]
}
if user_name == "" || repo_name == "" {
return nil, false
}
// Validate segments
for _, segment := range remainder_segments {
if segment == "" || segment == "." || segment == ".." {
return nil, false
}
}
// Define base root variations
roots := []string{
"/" + user_name + "/" + repo_name + "/raw",
"/" + user_name + "/" + repo_name + "/raw/branch/pages",
"/" + user_name + "/" + repo_name + "/raw/branch/main",
}
var candidate_paths []string
remainder_path := strings.Join(remainder_segments, "/")
for _, root := range roots {
if len(remainder_segments) == 0 {
// Case: /username/repo/ -> root/index.html
candidate_paths = append(candidate_paths, root+"/index.html")
} else {
// Case: /username/repo/path/to/file
candidate_paths = append(candidate_paths, root+"/"+remainder_path)
// Case: Trailing slash or directory -> root/path/to/file/index.html
if strings.HasSuffix(request_path, "/") || path.Ext(remainder_path) == "" {
candidate_paths = append(candidate_paths, root+"/"+remainder_path+"/index.html")
}
}
}
return unique_strings(candidate_paths), true
}
func unique_strings(values []string) []string {
seen_values := make(map[string]struct{}, len(values))
unique_values := make([]string, 0, len(values))
for _, value := range values {
if _, exists := seen_values[value]; exists {
continue
}
seen_values[value] = struct{}{}
unique_values = append(unique_values, value)
}
return unique_values
}
func same_host_port(left_host string, right_host string) bool {
return strings.EqualFold(left_host, right_host)
}
func join_paths(base_path string, request_path string) string {
if base_path == "" || base_path == "/" {
if request_path == "" {
return "/"
}
return request_path
}
if !strings.HasPrefix(base_path, "/") {
base_path = "/" + base_path
}
if request_path == "" {
request_path = "/"
}
return strings.TrimRight(base_path, "/") + "/" + strings.TrimLeft(request_path, "/")
}