2021-01-05 16:05:40 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2021-01-05 16:05:40 +03:00
2021-06-09 02:33:54 +03:00
package install
2021-01-05 16:05:40 +03:00
import (
2022-08-28 12:43:25 +03:00
goctx "context"
2021-01-05 16:05:40 +03:00
"fmt"
2023-03-04 05:12:02 +03:00
"html"
2021-01-05 16:05:40 +03:00
"net/http"
2021-01-26 18:36:53 +03:00
"path"
2021-01-05 16:05:40 +03:00
2022-07-23 09:38:03 +03:00
"code.gitea.io/gitea/modules/httpcache"
2021-01-05 16:05:40 +03:00
"code.gitea.io/gitea/modules/log"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/public"
2021-01-05 16:05:40 +03:00
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2021-01-30 11:55:53 +03:00
"code.gitea.io/gitea/modules/web/middleware"
2021-06-09 02:33:54 +03:00
"code.gitea.io/gitea/routers/common"
2022-05-04 14:56:20 +03:00
"code.gitea.io/gitea/routers/web/healthcheck"
2021-04-06 22:44:05 +03:00
"code.gitea.io/gitea/services/forms"
2021-01-05 16:05:40 +03:00
2021-01-26 18:36:53 +03:00
"gitea.com/go-chi/session"
2021-01-05 16:05:40 +03:00
)
2021-06-09 02:33:54 +03:00
type dataStore map [ string ] interface { }
func ( d * dataStore ) GetData ( ) map [ string ] interface { } {
return * d
}
2022-08-28 12:43:25 +03:00
func installRecovery ( ctx goctx . Context ) func ( next http . Handler ) http . Handler {
_ , rnd := templates . HTMLRenderer ( ctx )
2021-01-05 16:05:40 +03:00
return func ( next http . Handler ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
defer func ( ) {
// Why we need this? The first recover will try to render a beautiful
// error page for user, but the process can still panic again, then
// we have to just recover twice and send a simple error page that
2023-03-04 05:12:02 +03:00
// should not panic anymore.
2021-01-05 16:05:40 +03:00
defer func ( ) {
if err := recover ( ) ; err != nil {
2022-01-20 14:41:25 +03:00
combinedErr := fmt . Sprintf ( "PANIC: %v\n%s" , err , log . Stack ( 2 ) )
log . Error ( "%s" , combinedErr )
2021-10-20 17:37:19 +03:00
if setting . IsProd {
2022-03-23 07:54:07 +03:00
http . Error ( w , http . StatusText ( http . StatusInternalServerError ) , http . StatusInternalServerError )
2021-01-15 00:17:03 +03:00
} else {
2022-03-23 07:54:07 +03:00
http . Error ( w , combinedErr , http . StatusInternalServerError )
2021-01-05 16:05:40 +03:00
}
}
} ( )
if err := recover ( ) ; err != nil {
2022-01-20 14:41:25 +03:00
combinedErr := fmt . Sprintf ( "PANIC: %v\n%s" , err , log . Stack ( 2 ) )
log . Error ( "%s" , combinedErr )
2021-01-05 16:05:40 +03:00
2021-01-30 11:55:53 +03:00
lc := middleware . Locale ( w , req )
2022-01-20 20:46:10 +03:00
store := dataStore {
2021-06-09 02:33:54 +03:00
"Language" : lc . Language ( ) ,
"CurrentURL" : setting . AppSubURL + req . URL . RequestURI ( ) ,
2022-06-27 23:58:46 +03:00
"locale" : lc ,
2021-06-09 02:33:54 +03:00
"SignedUserID" : int64 ( 0 ) ,
"SignedUserName" : "" ,
2021-01-05 16:05:40 +03:00
}
2023-03-08 23:40:04 +03:00
httpcache . SetCacheControlInHeader ( w . Header ( ) , 0 , "no-transform" )
2021-08-06 23:47:10 +03:00
w . Header ( ) . Set ( ` X-Frame-Options ` , setting . CORSConfig . XFrameOptions )
2021-01-05 16:05:40 +03:00
2021-10-20 17:37:19 +03:00
if ! setting . IsProd {
2021-06-09 02:33:54 +03:00
store [ "ErrorMsg" ] = combinedErr
2021-01-05 16:05:40 +03:00
}
2022-03-23 07:54:07 +03:00
err = rnd . HTML ( w , http . StatusInternalServerError , "status/500" , templates . BaseVars ( ) . Merge ( store ) )
2021-01-05 16:05:40 +03:00
if err != nil {
log . Error ( "%v" , err )
}
}
} ( )
next . ServeHTTP ( w , req )
} )
}
}
2021-01-26 18:36:53 +03:00
2021-06-09 02:33:54 +03:00
// Routes registers the install routes
2022-08-28 12:43:25 +03:00
func Routes ( ctx goctx . Context ) * web . Route {
2021-01-26 18:36:53 +03:00
r := web . NewRoute ( )
2021-06-09 02:33:54 +03:00
for _ , middle := range common . Middlewares ( ) {
2021-01-26 18:36:53 +03:00
r . Use ( middle )
}
2022-01-20 14:41:25 +03:00
r . Use ( web . WrapWithPrefix ( public . AssetsURLPathPrefix , public . AssetsHandlerFunc ( & public . Options {
2021-05-30 13:25:11 +03:00
Directory : path . Join ( setting . StaticRootPath , "public" ) ,
2022-01-20 14:41:25 +03:00
Prefix : public . AssetsURLPathPrefix ,
} ) , "InstallAssetsHandler" ) )
2021-05-30 13:25:11 +03:00
2021-01-26 18:36:53 +03:00
r . Use ( session . Sessioner ( session . Options {
Provider : setting . SessionConfig . Provider ,
ProviderConfig : setting . SessionConfig . ProviderConfig ,
CookieName : setting . SessionConfig . CookieName ,
CookiePath : setting . SessionConfig . CookiePath ,
Gclifetime : setting . SessionConfig . Gclifetime ,
Maxlifetime : setting . SessionConfig . Maxlifetime ,
Secure : setting . SessionConfig . Secure ,
2021-05-31 21:22:36 +03:00
SameSite : setting . SessionConfig . SameSite ,
2021-01-26 18:36:53 +03:00
Domain : setting . SessionConfig . Domain ,
} ) )
2022-08-28 12:43:25 +03:00
r . Use ( installRecovery ( ctx ) )
r . Use ( Init ( ctx ) )
2023-03-04 05:12:02 +03:00
r . Get ( "/" , Install ) // it must be on the root, because the "install.js" use the window.location to replace the "localhost" AppURL
2021-06-09 02:33:54 +03:00
r . Post ( "/" , web . Bind ( forms . InstallForm { } ) , SubmitInstall )
2023-03-04 05:12:02 +03:00
r . Get ( "/post-install" , InstallDone )
2022-05-04 14:56:20 +03:00
r . Get ( "/api/healthz" , healthcheck . Check )
2022-01-20 14:41:25 +03:00
r . NotFound ( web . Wrap ( installNotFound ) )
2021-01-26 18:36:53 +03:00
return r
}
2022-01-20 14:41:25 +03:00
func installNotFound ( w http . ResponseWriter , req * http . Request ) {
2023-03-04 05:12:02 +03:00
w . Header ( ) . Add ( "Content-Type" , "text/html; charset=utf-8" )
w . Header ( ) . Add ( "Refresh" , fmt . Sprintf ( "1; url=%s" , setting . AppSubURL + "/" ) )
// do not use 30x status, because the "post-install" page needs to use 404/200 to detect if Gitea has been installed.
// the fetch API could follow 30x requests to the page with 200 status.
w . WriteHeader ( http . StatusNotFound )
_ , _ = fmt . Fprintf ( w , ` Not Found. <a href="%s">Go to default page</a>. ` , html . EscapeString ( setting . AppSubURL + "/" ) )
2022-01-20 14:41:25 +03:00
}