Skip to content

Commit c4519b6

Browse files
committed
ADD: support for custom path proxy
1 parent 6195886 commit c4519b6

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed

src/handlers/default_handlers.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import (
66
"html"
77
"log"
88
"net/http"
9+
"net/http/httputil"
10+
"net/url"
11+
"strings"
912
)
1013

1114
// StaticContentHandler it's a provider static content cloned from repository
@@ -78,3 +81,24 @@ func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
7881

7982
fmt.Fprintf(w, healthCheck.JSONHealthCheck())
8083
}
84+
85+
// ServeReverseProxy reverse proxy handler
86+
// Handle custom paths request
87+
func ServeReverseProxy(w http.ResponseWriter, r *http.Request) {
88+
path := r.URL.Path
89+
90+
exists, customPath := utils.FindPath(path)
91+
92+
if !exists {
93+
w.WriteHeader(http.StatusNotFound)
94+
return
95+
}
96+
targetUrl, _ := url.Parse(customPath.GetTarget())
97+
98+
if customPath.IsRewrite() {
99+
r.URL.Path = strings.ReplaceAll(path, fmt.Sprintf("/%s", customPath.GetPath()), "")
100+
}
101+
proxy := httputil.NewSingleHostReverseProxy(targetUrl)
102+
103+
proxy.ServeHTTP(w, r)
104+
}

src/server.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,21 @@ func main() {
1414
healthCheckControl := utils.GetHealthCheckControlInstance()
1515

1616
repo := utils.GetRepositoryConfigInstance()
17+
customPaths := utils.GetCustomPathsInstance()
1718

1819
utils.CloneRepository(repo.GetRepo(), repo.GetBranch(), repo.GetTargetFolder(), true)
1920

2021
http.HandleFunc(fmt.Sprintf("/%s/", routeConfig.GetClone()), handlers.CloneHandler)
2122
http.HandleFunc(fmt.Sprintf("/%s/", routeConfig.GetPull()), handlers.PullHandler)
2223
http.HandleFunc(fmt.Sprintf("/%s/", routeConfig.GetHealthCheck()), handlers.HealthCheckHandler)
24+
if len(*customPaths) > 0 {
25+
26+
for _, customPath := range *customPaths {
27+
http.HandleFunc(fmt.Sprintf("/%s/", customPath.GetPath()), handlers.ServeReverseProxy)
28+
log.Printf("[CUSTOM_PATH] /%s with target: %s", customPath.GetPath(), customPath.GetTarget())
29+
}
30+
31+
}
2332
http.HandleFunc("/", handlers.StaticContentHandler)
2433

2534
port := os.Getenv("HTTP_PORT")

src/utils/custom_path.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"strings"
8+
)
9+
10+
type CustomPath struct {
11+
path string
12+
target string
13+
rewrite bool
14+
}
15+
16+
// GetPath - return path value
17+
func (cp CustomPath) GetPath() string {
18+
return cp.path
19+
}
20+
21+
// GetTarget - return target value
22+
func (cp CustomPath) GetTarget() string {
23+
return cp.target
24+
}
25+
26+
// IsRewrite - return true if rewrite is available
27+
func (cp CustomPath) IsRewrite() bool {
28+
return cp.rewrite
29+
}
30+
31+
var baseCustomPathsInstance *[]CustomPath
32+
33+
// GetAllCustomPaths it's a function to get all custom paths
34+
// started with GHS_CUSTOM_PATH_
35+
// Recommended to be used on redirects for cloud storages
36+
func GetAllCustomPaths() *[]CustomPath {
37+
envVars := os.Environ()
38+
var result []CustomPath
39+
40+
for index, variable := range envVars {
41+
if strings.HasPrefix(variable, "GHS_CUSTOM_PATH_") {
42+
log.Println(fmt.Sprintf("I: %X - V: %s", index, variable))
43+
splitVar := strings.Split(variable, "=")
44+
45+
newPath := strings.ReplaceAll(splitVar[0], "GHS_CUSTOM_PATH_", "")
46+
if len(splitVar) > 1 {
47+
varObject := CustomPath{
48+
path: newPath,
49+
target: splitVar[1],
50+
rewrite: checkIfEnvVariableIsSet(envVars, fmt.Sprintf("GHS_CUSTOM_REWRITE_%s", newPath)),
51+
}
52+
53+
result = append(result, varObject)
54+
}
55+
}
56+
57+
}
58+
59+
return &result
60+
}
61+
func checkIfEnvVariableIsSet(envVars []string, envVar string) bool {
62+
63+
for _, variable := range envVars {
64+
if strings.HasPrefix(variable, envVar) {
65+
return true
66+
}
67+
}
68+
69+
return false
70+
71+
}
72+
73+
// FindPath - Find path on custom path instance
74+
func FindPath(pathRequested string) (bool, *CustomPath) {
75+
76+
paths := GetCustomPathsInstance()
77+
78+
for _, path := range *paths {
79+
prefixPath := fmt.Sprintf("/%s", path.GetPath())
80+
if strings.HasPrefix(pathRequested, prefixPath) {
81+
return true, &path
82+
}
83+
}
84+
85+
return false, nil
86+
87+
}
88+
func GetCustomPathsInstance() *[]CustomPath {
89+
if baseCustomPathsInstance == nil {
90+
91+
lock.Lock()
92+
defer lock.Unlock()
93+
94+
if baseCustomPathsInstance == nil {
95+
log.Println("[CustomPaths] Creating new instance")
96+
97+
baseCustomPathsInstance = GetAllCustomPaths()
98+
}
99+
}
100+
101+
return baseCustomPathsInstance
102+
}

src/utils/custom_path_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package utils
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"log"
6+
"os"
7+
"strings"
8+
"testing"
9+
)
10+
11+
func TestGetAllCustomPaths(t *testing.T) {
12+
os.Setenv("GHS_CUSTOM_PATH_images/digilex-infordoc-images", "https://storage.gra.cloud.ovh.net/v1/AUTH_ed33ec9e34c64b54aca49d6fcb6dc4c8/infordoc-img")
13+
os.Setenv("GHS_CUSTOM_REWRITE_images/digilex-infordoc-images", "")
14+
os.Setenv("GHS_CUSTOM_PATH_images/digilex-infordoc-images-1", "https://storage.gra.cloud.ovh.net/v1/AUTH_ed33ec9e34c64b54aca49d6fcb6dc4c8/img")
15+
os.Setenv("GHS_CUSTOM_PATH_images/digilex-infordoc-images-2", "https://storage.gra.cloud.ovh.net/v1/AUTH_ed33ec9e34c64b54aca49d6fcb6dc4c8/infordoc")
16+
result := GetCustomPathsInstance()
17+
18+
assert.True(t, len(*result) == 3)
19+
20+
for _, customVar := range *result {
21+
log.Printf("Path: %s - Target: %s - Rewrite: %t \n", customVar.GetPath(), customVar.GetTarget(), customVar.IsRewrite())
22+
assert.False(t, strings.HasPrefix(customVar.path, "GHS_CUSTOM_PATH_"))
23+
24+
}
25+
26+
}

0 commit comments

Comments
 (0)