2023-05-04 09:36:34 +03:00
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package common
import (
"fmt"
"net/http"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
2023-10-31 17:11:48 +03:00
"code.gitea.io/gitea/modules/context"
2023-05-04 09:36:34 +03:00
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/modules/web/routing"
)
const tplStatus500 base . TplName = "status/500"
// RenderPanicErrorPage renders a 500 page, and it never panics
func RenderPanicErrorPage ( w http . ResponseWriter , req * http . Request , err any ) {
combinedErr := fmt . Sprintf ( "%v\n%s" , err , log . Stack ( 2 ) )
log . Error ( "PANIC: %s" , combinedErr )
defer func ( ) {
if err := recover ( ) ; err != nil {
2023-05-29 18:00:21 +03:00
log . Error ( "Panic occurs again when rendering error page: %v. Stack:\n%s" , err , log . Stack ( 2 ) )
2023-05-04 09:36:34 +03:00
}
} ( )
routing . UpdatePanicError ( req . Context ( ) , err )
httpcache . SetCacheControlInHeader ( w . Header ( ) , 0 , "no-transform" )
w . Header ( ) . Set ( ` X-Frame-Options ` , setting . CORSConfig . XFrameOptions )
2023-10-31 17:11:48 +03:00
tmplCtx := context . TemplateContext { }
tmplCtx [ "Locale" ] = middleware . Locale ( w , req )
ctxData := middleware . GetContextData ( req . Context ( ) )
2023-05-04 09:36:34 +03:00
// This recovery handler could be called without Gitea's web context, so we shouldn't touch that context too much.
// Otherwise, the 500-page may cause new panics, eg: cache.GetContextWithData, it makes the developer&users couldn't find the original panic.
2023-10-31 17:11:48 +03:00
user , _ := ctxData [ middleware . ContextDataKeySignedUser ] . ( * user_model . User )
2023-05-04 09:36:34 +03:00
if ! setting . IsProd || ( user != nil && user . IsAdmin ) {
2023-10-31 17:11:48 +03:00
ctxData [ "ErrorMsg" ] = "PANIC: " + combinedErr
2023-05-04 09:36:34 +03:00
}
2023-10-31 17:11:48 +03:00
err = templates . HTMLRenderer ( ) . HTML ( w , http . StatusInternalServerError , string ( tplStatus500 ) , ctxData , tmplCtx )
2023-05-04 09:36:34 +03:00
if err != nil {
log . Error ( "Error occurs again when rendering error page: %v" , err )
w . WriteHeader ( http . StatusInternalServerError )
_ , _ = w . Write ( [ ] byte ( "Internal server error, please collect error logs and report to Gitea issue tracker" ) )
}
}