Skip to content

Commit 1bd15c4

Browse files
committed
switch to go
1 parent f35299c commit 1bd15c4

File tree

7 files changed

+340
-196
lines changed

7 files changed

+340
-196
lines changed

Dockerfile

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
FROM python:3.9-alpine
2-
3-
WORKDIR /app
4-
5-
RUN pip install flask requests
6-
7-
COPY . .
8-
9-
ENV PORT=8880
10-
11-
EXPOSE ${PORT}
12-
13-
CMD ["python", "app.py"]
1+
FROM golang:1.24
2+
3+
WORKDIR /app
4+
5+
COPY go.mod go.sum ./
6+
7+
RUN go mod download
8+
9+
COPY *.go ./
10+
11+
RUN CGO_ENABLED=0 GOOS=linux go build -o /secured-signal-api
12+
13+
ENV PORT=8880
14+
15+
EXPOSE ${PORT}
16+
17+
CMD ["/docker-gs-ping"]

app.py

Lines changed: 0 additions & 183 deletions
This file was deleted.

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module github.com/codeshelldev/secured-signal-api
2+
3+
go 1.24.4
4+
5+
require go.uber.org/zap v1.27.0
6+
7+
require go.uber.org/multierr v1.10.0 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
2+
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
3+
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
4+
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=

internals/proxy/proxy.go

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package proxy
2+
3+
import (
4+
"bytes"
5+
"encoding/base64"
6+
"io"
7+
"net/http"
8+
"net/http/httputil"
9+
"net/url"
10+
"os"
11+
"slices"
12+
"strings"
13+
"text/template"
14+
15+
log "github.com/codeshelldev/secured-signal-api/utils"
16+
)
17+
18+
type AuthType string
19+
20+
const (
21+
Bearer AuthType = "Bearer"
22+
Basic AuthType = "Basic"
23+
Query AuthType = "Query"
24+
None AuthType = ""
25+
)
26+
27+
func getAuthType(str string) AuthType {
28+
switch str {
29+
case "Bearer":
30+
return Bearer
31+
case "Basic":
32+
return Basic
33+
default:
34+
return None
35+
}
36+
}
37+
38+
func renderTemplate(name string, tmplStr string, data any) (string, error) {
39+
tmpl, err := template.New(name).Parse(tmplStr)
40+
41+
if err != nil {
42+
return "", err
43+
}
44+
var buf bytes.Buffer
45+
46+
err = tmpl.Execute(&buf, data)
47+
48+
if err != nil {
49+
return "", err
50+
}
51+
return buf.String(), nil
52+
}
53+
54+
func AuthMiddleware(next http.Handler) http.Handler {
55+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
56+
log.Info("Request:", req.Method, req.URL.Path)
57+
58+
token := os.Getenv("API_TOKEN")
59+
user := "api"
60+
61+
authHeader := req.Header.Get("Authorization")
62+
63+
authQuery := req.URL.Query().Get("authorization")
64+
65+
var authType AuthType
66+
67+
success := false
68+
69+
if authHeader != "" {
70+
authBody := strings.Split(authHeader, " ")
71+
72+
authType = getAuthType(authBody[0])
73+
authToken := authBody[1]
74+
75+
switch authType {
76+
case Bearer:
77+
if authToken == token {
78+
success = true
79+
}
80+
81+
case Basic:
82+
basicAuthBody, err := base64.StdEncoding.DecodeString(authToken)
83+
84+
if err != nil {
85+
log.Error("Could not decode Basic Auth Payload: ", err.Error())
86+
}
87+
88+
basicAuth := string(basicAuthBody)
89+
basicAuthParams := strings.Split(basicAuth, ":")
90+
91+
if basicAuthParams[0] == user && basicAuthParams[1] == token {
92+
success = true
93+
}
94+
}
95+
96+
} else if authQuery != "" {
97+
authType = Query
98+
99+
authToken, _ := url.QueryUnescape(authQuery)
100+
101+
if authToken == token {
102+
success = true
103+
}
104+
}
105+
106+
if !success {
107+
log.Warn("User failed ", string(authType), " Auth")
108+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
109+
return
110+
}
111+
112+
next.ServeHTTP(w, req)
113+
})
114+
}
115+
116+
func BlockedEndpointMiddleware(next http.Handler, BLOCKED_ENDPOINTS []string) http.Handler {
117+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
118+
reqPath := req.URL.Path
119+
120+
if slices.Contains(BLOCKED_ENDPOINTS, reqPath) {
121+
log.Warn("User tried to access blocked endpoint: ", reqPath)
122+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
123+
return
124+
}
125+
126+
next.ServeHTTP(w, req)
127+
})
128+
}
129+
130+
func TemplatingMiddleware(next http.Handler, VARIABLES map[string]string) http.Handler {
131+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
132+
if req.Body != nil {
133+
bodyBytes, err := io.ReadAll(req.Body)
134+
135+
if err != nil {
136+
log.Error("Could not decode Body: ", err.Error())
137+
http.Error(w, "Internal Error", http.StatusInternalServerError)
138+
return
139+
}
140+
141+
req.Body.Close()
142+
143+
modifiedBody := string(bodyBytes)
144+
145+
modifiedBody, _ = renderTemplate("json", modifiedBody, VARIABLES)
146+
modifiedBodyBytes := []byte(modifiedBody)
147+
148+
req.Body = io.NopCloser(bytes.NewReader(modifiedBodyBytes))
149+
}
150+
151+
reqPath := req.URL.Path
152+
153+
modifiedReqPath, _ := renderTemplate("path", reqPath, VARIABLES)
154+
155+
req.URL.Path = modifiedReqPath
156+
157+
next.ServeHTTP(w, req)
158+
})
159+
}
160+
161+
func Create(targetUrl string) *httputil.ReverseProxy {
162+
url, _ := url.Parse(targetUrl)
163+
164+
proxy := httputil.NewSingleHostReverseProxy(url)
165+
166+
return proxy
167+
}

0 commit comments

Comments
 (0)