package utils import ( "math/rand" "os" "path/filepath" ) // ErrorPageConfig holds configuration for generating error pages type ErrorPageConfig struct { OverrideDir string // Directory where override templates are stored DebugMode bool // Whether to show debug information } // ErrorType represents HTTP error types type ErrorType int const ( ErrorTypeNotFound ErrorType = 404 ErrorTypeMethodNotAllowed ErrorType = 405 ErrorTypeInternalError ErrorType = 500 ErrorTypeForbidden ErrorType = 403 // Added CSRF/Forbidden error type ) // ErrorPage generates an HTML error page based on the error type // It first checks for an override file, and if not found, generates a default page func ErrorPage(config ErrorPageConfig, errorType ErrorType, url string, errMsg string) string { // Check for override file if config.OverrideDir != "" { var filename string switch errorType { case ErrorTypeNotFound: filename = "404.html" case ErrorTypeMethodNotAllowed: filename = "405.html" case ErrorTypeInternalError: filename = "500.html" case ErrorTypeForbidden: filename = "403.html" } if filename != "" { overridePath := filepath.Join(config.OverrideDir, filename) if content, err := os.ReadFile(overridePath); err == nil { return string(content) } } } // No override found, generate default page switch errorType { case ErrorTypeNotFound: return generateNotFoundHTML(url) case ErrorTypeMethodNotAllowed: return generateMethodNotAllowedHTML(url) case ErrorTypeInternalError: return generateInternalErrorHTML(config.DebugMode, url, errMsg) case ErrorTypeForbidden: return generateForbiddenHTML(config.DebugMode, url, errMsg) default: // Fallback to internal error return generateInternalErrorHTML(config.DebugMode, url, errMsg) } } // NotFoundPage generates a 404 Not Found error page func NotFoundPage(config ErrorPageConfig, url string) string { return ErrorPage(config, ErrorTypeNotFound, url, "") } // MethodNotAllowedPage generates a 405 Method Not Allowed error page func MethodNotAllowedPage(config ErrorPageConfig, url string) string { return ErrorPage(config, ErrorTypeMethodNotAllowed, url, "") } // InternalErrorPage generates a 500 Internal Server Error page func InternalErrorPage(config ErrorPageConfig, url string, errMsg string) string { return ErrorPage(config, ErrorTypeInternalError, url, errMsg) } // ForbiddenPage generates a 403 Forbidden error page func ForbiddenPage(config ErrorPageConfig, url string, errMsg string) string { return ErrorPage(config, ErrorTypeForbidden, url, errMsg) } // generateInternalErrorHTML creates a 500 Internal Server Error page func generateInternalErrorHTML(debugMode bool, url string, errMsg string) string { errorMessages := []string{ "Oops! Something went wrong", "Oh no! The server choked", "Well, this is embarrassing...", "Houston, we have a problem", "Gremlins in the system", "The server is taking a coffee break", "Moonshark encountered a lunar eclipse", "Our code monkeys are working on it", "The server is feeling under the weather", "500 Brain Not Found", } randomMessage := errorMessages[rand.Intn(len(errorMessages))] return generateErrorHTML("500", randomMessage, "Internal Server Error", debugMode, errMsg) } // generateForbiddenHTML creates a 403 Forbidden error page func generateForbiddenHTML(debugMode bool, url string, errMsg string) string { errorMessages := []string{ "Access denied", "You shall not pass", "This area is off-limits", "Security check failed", "Invalid security token", "Request blocked for security reasons", "Permission denied", "Security violation detected", "This request was rejected", "Security first, access second", } defaultMsg := "Invalid or missing CSRF token. This could be due to an expired form or a cross-site request forgery attempt." if errMsg == "" { errMsg = defaultMsg } randomMessage := errorMessages[rand.Intn(len(errorMessages))] return generateErrorHTML("403", randomMessage, "Forbidden", debugMode, errMsg) } // generateNotFoundHTML creates a 404 Not Found error page func generateNotFoundHTML(url string) string { errorMessages := []string{ "Nothing to see here", "This page is on vacation", "The page is missing in action", "This page has left the building", "This page is in another castle", "Sorry, we can't find that", "The page you're looking for doesn't exist", "Lost in space", "That's a 404", "Page not found", } randomMessage := errorMessages[rand.Intn(len(errorMessages))] return generateErrorHTML("404", randomMessage, "Page Not Found", false, url) } // generateMethodNotAllowedHTML creates a 405 Method Not Allowed error page func generateMethodNotAllowedHTML(url string) string { errorMessages := []string{ "That's not how this works", "Method not allowed", "Wrong way!", "This method is not supported", "You can't do that here", "Sorry, wrong door", "That method won't work here", "Try a different approach", "Access denied for this method", "Method mismatch", } randomMessage := errorMessages[rand.Intn(len(errorMessages))] return generateErrorHTML("405", randomMessage, "Method Not Allowed", false, url) } // generateErrorHTML creates the common HTML structure for error pages func generateErrorHTML(errorCode, mainMessage, subMessage string, showDebugInfo bool, codeContent string) string { errorHTML := `
` + mainMessage + `
` if codeContent != "" { errorHTML += `` + codeContent + `
`
}
// Add a note for debug mode
if showDebugInfo {
errorHTML += `
An error occurred while processing your request.
Please check the server logs for details.