1+ package middlewares
2+
3+ import (
4+ "bytes"
5+ "io"
6+ "net/http"
7+ "os"
8+ "regexp"
9+ "strings"
10+
11+ "github.com/codeshelldev/gotl/pkg/logger"
12+ "github.com/codeshelldev/gotl/pkg/request"
13+ "github.com/codeshelldev/secured-signal-api/internals/config"
14+ )
15+
16+ var InternalAPI Middleware = Middleware {
17+ Name : "_Internal_API" ,
18+ Use : internalAPIHandler ,
19+ }
20+
21+ func internalAPIHandler (next http.Handler ) http.Handler {
22+ mux := http .NewServeMux ()
23+
24+ const aboutEndpoint = "/v1/about"
25+ mux .HandleFunc (aboutEndpoint , func (w http.ResponseWriter , req * http.Request ) {
26+ res , err := redirectRequestToBackend (req , config .DEFAULT .API .URL + aboutEndpoint )
27+
28+ if err != nil {
29+ logger .Error ("Error requesting Backend: " , err .Error ())
30+ http .Error (w , "Internal Server Error " , http .StatusBadGateway )
31+ return
32+ }
33+
34+ body , err := request .GetResBody (res )
35+
36+ if err != nil {
37+ logger .Error ("Could not get Response Body: " , err .Error ())
38+ http .Error (w , "Internal Server Error" , http .StatusInternalServerError )
39+ return
40+ }
41+
42+ for key , values := range res .Header {
43+ for _ , value := range values {
44+ w .Header ().Add (key , value )
45+ }
46+ }
47+
48+ if ! body .Empty {
49+ var version string
50+
51+ if isValidSemver (os .Getenv ("IMAGE_TAG" )) {
52+ version , _ = strings .CutPrefix (version , "v" )
53+ }
54+
55+ payload := map [string ]any {
56+ "version" : version ,
57+ "auth_required" : ! config .ENV .INSECURE ,
58+ }
59+
60+ body .Data ["secured-signal-api" ] = payload
61+
62+ err := body .Write (w )
63+
64+ if err != nil {
65+ logger .Error ("Could not write to Response Body: " , err .Error ())
66+ http .Error (w , "Internal Server Error" , http .StatusInternalServerError )
67+ return
68+ }
69+ }
70+
71+ w .WriteHeader (res .StatusCode )
72+ })
73+
74+ mux .HandleFunc ("/favicon.ico" , func (w http.ResponseWriter , req * http.Request ) {
75+ http .ServeFile (w , req , config .ENV .FAVICON_PATH )
76+ })
77+
78+ mux .Handle ("/" , next )
79+
80+ return mux
81+ }
82+
83+ func isValidSemver (version string ) bool {
84+ re , err := regexp .Compile (`^v?([0-9]+)\.([0-9]+)\.([0-9]+)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$` )
85+
86+ if err != nil {
87+ return false
88+ }
89+
90+ return re .MatchString (version )
91+ }
92+
93+ func redirectRequestToBackend (req * http.Request , url string ) (* http.Response , error ) {
94+ var body io.Reader
95+
96+ if req .Body != nil {
97+ bodyBytes , err := io .ReadAll (req .Body )
98+
99+ if err != nil {
100+ return nil , err
101+ }
102+ req .Body .Close ()
103+
104+ body = bytes .NewReader (bodyBytes )
105+ req .Body = io .NopCloser (bytes .NewReader (bodyBytes ))
106+ }
107+
108+ return requestBackend (req .Method , url , body , req .Header )
109+ }
110+
111+ func requestBackend (method , url string , body io.Reader , headers map [string ][]string ) (* http.Response , error ) {
112+ backendReq , err := http .NewRequest (method , url , body )
113+ if err != nil {
114+ return nil , err
115+ }
116+
117+ for key , values := range headers {
118+ for _ , value := range values {
119+ backendReq .Header .Add (key , value )
120+ }
121+ }
122+
123+ client := & http.Client {}
124+
125+ res , err := client .Do (backendReq )
126+ if err != nil {
127+ return nil , err
128+ }
129+
130+ return res , nil
131+ }
0 commit comments