diff options
Diffstat (limited to 'internal/modules/handler.go')
| -rw-r--r-- | internal/modules/handler.go | 107 |
1 files changed, 81 insertions, 26 deletions
diff --git a/internal/modules/handler.go b/internal/modules/handler.go index 9fa1094..c01f716 100644 --- a/internal/modules/handler.go +++ b/internal/modules/handler.go @@ -5,6 +5,7 @@ import ( "fmt" "log/slog" "net/http" + "net/url" "path/filepath" "strings" @@ -18,6 +19,74 @@ type ModuleHandler struct { serverHost string } +// normalizeImportPath creates a properly formatted full import path +func (h *ModuleHandler) normalizeImportPath(modulePath string) (string, error) { + if h.serverHost == "" { + return "", fmt.Errorf("serverHost cannot be empty") + } + if modulePath == "" { + return "", fmt.Errorf("modulePath cannot be empty") + } + if strings.Contains(modulePath, "..") { + return "", fmt.Errorf("modulePath cannot contain '..'") + } + + // Clean the inputs + host := strings.TrimRight(h.serverHost, "/") + module := strings.Trim(modulePath, "/") + + // Validate that module path doesn't contain invalid characters + if strings.ContainsAny(module, " \t\n\r") { + return "", fmt.Errorf("modulePath cannot contain whitespace characters") + } + + return host + "/" + module, nil +} + +// buildRepoURL creates a proper repository URL +func (h *ModuleHandler) buildRepoURL(modulePath string) (string, error) { + _, err := h.normalizeImportPath(modulePath) + if err != nil { + return "", err + } + + // Use proper URL building to ensure valid URLs + repoURL := &url.URL{ + Scheme: "https", + Host: h.serverHost, + Path: "/" + strings.Trim(modulePath, "/"), + } + + return repoURL.String(), nil +} + +// generateGoImportHTML creates the HTML response for go-import requests +func (h *ModuleHandler) generateGoImportHTML(modulePath string) (string, error) { + fullImportPath, err := h.normalizeImportPath(modulePath) + if err != nil { + return "", fmt.Errorf("failed to normalize import path: %w", err) + } + + repoURL, err := h.buildRepoURL(modulePath) + if err != nil { + return "", fmt.Errorf("failed to build repository URL: %w", err) + } + + return fmt.Sprintf(`<!DOCTYPE html> +<html> +<head> + <meta name="go-import" content="%s git %s"> + <meta name="go-source" content="%s %s %s/tree/{/dir} %s/blob/{/dir}/{file}#L{line}"> +</head> +<body> + go get %s +</body> +</html>`, + fullImportPath, repoURL, + fullImportPath, repoURL, repoURL, repoURL, + fullImportPath), nil +} + // NewModuleHandler creates a new module handler with explicit routes for known repos func NewModuleHandler(reposDir, serverHost string, config *admin.ServerRepos) http.Handler { handler := &ModuleHandler{ @@ -266,19 +335,12 @@ func (h *ModuleHandler) handleGoImportForModule(w http.ResponseWriter, r *http.R } // Generate HTML with go-import meta tag - html := fmt.Sprintf(`<!DOCTYPE html> -<html> -<head> - <meta name="go-import" content="%s git https://%s/%s"> - <meta name="go-source" content="%s https://%s/%s https://%s/%s/tree/{/dir} https://%s/%s/blob/{/dir}/{file}#L{line}"> -</head> -<body> - go get %s -</body> -</html>`, - modulePath, h.serverHost, modulePath, - modulePath, h.serverHost, modulePath, h.serverHost, modulePath, h.serverHost, modulePath, - modulePath) + html, err := h.generateGoImportHTML(modulePath) + if err != nil { + slog.Error("failed to generate go-import HTML", "module", modulePath, "error", err) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusOK) @@ -300,19 +362,12 @@ func (h *ModuleHandler) handleGoImport(w http.ResponseWriter, r *http.Request) { modulePath := ExtractModulePath(r.URL.Path) // Generate HTML with go-import meta tag - html := fmt.Sprintf(`<!DOCTYPE html> -<html> -<head> - <meta name="go-import" content="%s git https://%s/%s"> - <meta name="go-source" content="%s https://%s/%s https://%s/%s/tree/{/dir} https://%s/%s/blob/{/dir}/{file}#L{line}"> -</head> -<body> - go get %s -</body> -</html>`, - modulePath, h.serverHost, modulePath, - modulePath, h.serverHost, modulePath, h.serverHost, modulePath, h.serverHost, modulePath, - modulePath) + html, err := h.generateGoImportHTML(modulePath) + if err != nil { + slog.Error("failed to generate go-import HTML", "module", modulePath, "error", err) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusOK) |