github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/pkg/setup/cors.go (about)

     1  /*This file is part of kuberpult.
     2  
     3  Kuberpult is free software: you can redistribute it and/or modify
     4  it under the terms of the Expat(MIT) License as published by
     5  the Free Software Foundation.
     6  
     7  Kuberpult is distributed in the hope that it will be useful,
     8  but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    10  MIT License for more details.
    11  
    12  You should have received a copy of the MIT License
    13  along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
    14  
    15  Copyright 2023 freiheit.com*/
    16  
    17  // Middleware for handling CORS (cross origin requests)
    18  // Warning: CORS requests needs to be whitelisted on ist.io ingress configuration
    19  // Technically this middleware shouldn't be necessary but currently the ingress
    20  // proxy forwards the CORS preflight request to the pod
    21  package setup
    22  
    23  import (
    24  	"fmt"
    25  	"net/http"
    26  )
    27  
    28  type CORSPolicy struct {
    29  	AllowMethods     string
    30  	AllowHeaders     string
    31  	AllowOrigin      string
    32  	AllowCredentials bool
    33  	MaxAge           int
    34  }
    35  
    36  type CORSMiddleware struct {
    37  	PolicyFor   func(req *http.Request) *CORSPolicy
    38  	NextHandler http.Handler
    39  }
    40  
    41  func (check *CORSMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    42  	origin := req.Header.Get("Origin")
    43  	if origin == "" {
    44  		check.NextHandler.ServeHTTP(rw, req)
    45  		return
    46  	}
    47  
    48  	requestMethod := req.Header.Get("Access-Control-Request-Method")
    49  	policy := check.PolicyFor(req)
    50  	if policy == nil {
    51  		rw.WriteHeader(403)
    52  		req.Body.Close()
    53  		return
    54  	}
    55  
    56  	if req.Method == "OPTIONS" && requestMethod != "" {
    57  
    58  		rw.Header().Add("Access-Control-Allow-Methods", policy.AllowMethods)
    59  		rw.Header().Add("Access-Control-Allow-Headers", policy.AllowHeaders)
    60  		if policy.AllowCredentials {
    61  			rw.Header().Add("Access-Control-Allow-Credentials", "true")
    62  		}
    63  		rw.Header().Add("Access-Control-Max-Age", fmt.Sprintf("%d", policy.MaxAge))
    64  		rw.Header().Add("Access-Control-Allow-Origin", policy.AllowOrigin)
    65  
    66  		rw.WriteHeader(204)
    67  		req.Body.Close()
    68  		return
    69  	}
    70  	rw.Header().Add("Access-Control-Allow-Origin", policy.AllowOrigin)
    71  	if policy.AllowCredentials {
    72  		rw.Header().Add("Access-Control-Allow-Credentials", "true")
    73  	}
    74  	check.NextHandler.ServeHTTP(rw, req)
    75  
    76  }