2022-11-12 19:43:44 +00:00
package handler
import (
"net/http"
"strings"
"github.com/rs/zerolog/log"
2024-02-15 16:08:29 +00:00
"codeberg.org/codeberg/pages/config"
2022-11-12 19:43:44 +00:00
"codeberg.org/codeberg/pages/html"
"codeberg.org/codeberg/pages/server/cache"
"codeberg.org/codeberg/pages/server/context"
"codeberg.org/codeberg/pages/server/gitea"
)
const (
headerAccessControlAllowOrigin = "Access-Control-Allow-Origin"
headerAccessControlAllowMethods = "Access-Control-Allow-Methods"
2022-11-12 20:16:11 +00:00
defaultPagesRepo = "pages"
2022-11-12 19:43:44 +00:00
)
// Handler handles a single HTTP request to the web server.
2024-02-15 16:08:29 +00:00
func Handler (
cfg config . ServerConfig ,
2022-11-12 19:43:44 +00:00
giteaClient * gitea . Client ,
2024-02-15 16:08:29 +00:00
dnsLookupCache , canonicalDomainCache , redirectsCache cache . ICache ,
2022-11-12 19:43:44 +00:00
) http . HandlerFunc {
return func ( w http . ResponseWriter , req * http . Request ) {
2022-11-15 15:15:11 +00:00
log := log . With ( ) . Strs ( "Handler" , [ ] string { req . Host , req . RequestURI } ) . Logger ( )
2022-11-12 19:43:44 +00:00
ctx := context . New ( w , req )
2023-11-15 01:49:29 +00:00
ctx . RespWriter . Header ( ) . Set ( "Server" , "pages-server" )
2022-11-12 19:43:44 +00:00
// Force new default from specification (since November 2020) - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#strict-origin-when-cross-origin
ctx . RespWriter . Header ( ) . Set ( "Referrer-Policy" , "strict-origin-when-cross-origin" )
// Enable browser caching for up to 10 minutes
ctx . RespWriter . Header ( ) . Set ( "Cache-Control" , "public, max-age=600" )
trimmedHost := ctx . TrimHostPort ( )
2024-02-15 16:08:29 +00:00
// Add HSTS for RawDomain and MainDomain
if hsts := getHSTSHeader ( trimmedHost , cfg . MainDomain , cfg . RawDomain ) ; hsts != "" {
2022-11-12 19:43:44 +00:00
ctx . RespWriter . Header ( ) . Set ( "Strict-Transport-Security" , hsts )
}
// Handle all http methods
ctx . RespWriter . Header ( ) . Set ( "Allow" , http . MethodGet + ", " + http . MethodHead + ", " + http . MethodOptions )
switch ctx . Req . Method {
case http . MethodOptions :
// return Allow header
ctx . RespWriter . WriteHeader ( http . StatusNoContent )
return
case http . MethodGet ,
http . MethodHead :
// end switch case and handle allowed requests
break
default :
// Block all methods not required for static pages
ctx . String ( "Method not allowed" , http . StatusMethodNotAllowed )
return
}
// Block blacklisted paths (like ACME challenges)
2024-02-15 16:08:29 +00:00
for _ , blacklistedPath := range cfg . BlacklistedPaths {
2022-11-12 19:43:44 +00:00
if strings . HasPrefix ( ctx . Path ( ) , blacklistedPath ) {
2023-11-16 17:11:35 +00:00
html . ReturnErrorPage ( ctx , "requested path is blacklisted" , http . StatusForbidden )
2022-11-12 19:43:44 +00:00
return
}
}
// Allow CORS for specified domains
allowCors := false
2024-02-15 16:08:29 +00:00
for _ , allowedCorsDomain := range cfg . AllowedCorsDomains {
2022-11-12 19:43:44 +00:00
if strings . EqualFold ( trimmedHost , allowedCorsDomain ) {
allowCors = true
break
}
}
if allowCors {
ctx . RespWriter . Header ( ) . Set ( headerAccessControlAllowOrigin , "*" )
ctx . RespWriter . Header ( ) . Set ( headerAccessControlAllowMethods , http . MethodGet + ", " + http . MethodHead )
}
// Prepare request information to Gitea
pathElements := strings . Split ( strings . Trim ( ctx . Path ( ) , "/" ) , "/" )
2024-02-15 16:08:29 +00:00
if cfg . RawDomain != "" && strings . EqualFold ( trimmedHost , cfg . RawDomain ) {
2023-11-15 01:49:29 +00:00
log . Debug ( ) . Msg ( "raw domain request detected" )
2022-11-12 19:43:44 +00:00
handleRaw ( log , ctx , giteaClient ,
2024-02-15 16:08:29 +00:00
cfg . MainDomain ,
2022-11-12 19:43:44 +00:00
trimmedHost ,
pathElements ,
2023-03-30 21:36:31 +00:00
canonicalDomainCache , redirectsCache )
2024-02-15 16:08:29 +00:00
} else if strings . HasSuffix ( trimmedHost , cfg . MainDomain ) {
2023-11-15 01:49:29 +00:00
log . Debug ( ) . Msg ( "subdomain request detected" )
2022-11-12 19:43:44 +00:00
handleSubDomain ( log , ctx , giteaClient ,
2024-02-15 16:08:29 +00:00
cfg . MainDomain ,
cfg . PagesBranches ,
2022-11-12 19:43:44 +00:00
trimmedHost ,
pathElements ,
2023-03-30 21:36:31 +00:00
canonicalDomainCache , redirectsCache )
2022-11-12 19:43:44 +00:00
} else {
2023-11-15 01:49:29 +00:00
log . Debug ( ) . Msg ( "custom domain request detected" )
2022-11-12 19:43:44 +00:00
handleCustomDomain ( log , ctx , giteaClient ,
2024-02-15 16:08:29 +00:00
cfg . MainDomain ,
2022-11-12 19:43:44 +00:00
trimmedHost ,
pathElements ,
2024-02-15 16:08:29 +00:00
cfg . PagesBranches [ 0 ] ,
2023-03-30 21:36:31 +00:00
dnsLookupCache , canonicalDomainCache , redirectsCache )
2022-11-12 19:43:44 +00:00
}
}
}