124 lines
3.3 KiB
Go
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, "/")
|
|
}
|