-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathecho-service.go
More file actions
133 lines (112 loc) · 3.52 KB
/
echo-service.go
File metadata and controls
133 lines (112 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"encoding/json"
"github.com/golang-jwt/jwt/v5"
"io"
"log"
"net/http"
"strconv"
"strings"
"time"
)
type Response struct {
Http Http `json:"http,omitempty"`
Header map[string][]string `json:"header,omitempty"`
RemoteAddress string `json:"remoteAddress,omitempty"`
Request Request `json:"request,omitempty"`
Authorization JwtPayload `json:"authorization,omitempty"`
InstanceName string `json:"instanceName,omitempty"`
}
type Http struct {
Method string `json:"method,omitempty"`
Protocol string `json:"protocol,omitempty"`
Host string `json:"host,omitempty"`
ContentLength int64 `json:"contentLength,omitempty"`
}
type Request struct {
RequestURI string `json:"requestURI,omitempty"`
Path string `json:"path,omitempty"`
QueryString string `json:"queryString,omitempty"`
Body interface{} `json:"body,omitempty"`
}
type JwtPayload struct {
Header map[string]interface{} `json:"header"`
Payload interface{} `json:"payload"`
}
var InstanceName string
func StartEchoService(port int, instanceName string) error {
log.Printf("Starting echo-service at port %v and instance name %v\n", port, instanceName)
InstanceName = instanceName
http.HandleFunc("/", handleRequest)
err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
if err != nil {
log.Printf("Unable to start http server on port %v: %v\n", port, err)
}
return err
}
func handleRequest(w http.ResponseWriter, req *http.Request) {
response := Response{}
response.Http.Method = req.Method
response.Http.ContentLength = req.ContentLength
response.Http.Protocol = req.Proto
response.Http.Host = req.Host
response.Request.RequestURI = req.RequestURI
response.Request.QueryString = req.URL.RawQuery
response.Request.Path = req.URL.Path
response.RemoteAddress = req.RemoteAddr
response.Header = req.Header
response.InstanceName = InstanceName
authHeader := req.Header.Get("Authorization")
if authHeader != "" {
handleJWT(authHeader, &response.Authorization)
}
handleBody(req, &response)
handleTimeout(req)
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Printf("Unable to send or decode JSON: %v", err)
}
}
func handleTimeout(req *http.Request) {
timeoutValue := req.URL.Query().Get("timeout")
if timeoutValue == "" {
timeoutValue = req.Header.Get("X-Timeout")
}
if timeoutValue != "" {
duration, err := time.ParseDuration(timeoutValue)
if err == nil {
log.Printf("Cannot parse duration. Check format! %v", err)
}
log.Printf("Sleep for %v.", duration)
time.Sleep(duration)
}
}
func handleBody(req *http.Request, res *Response) {
b, err := io.ReadAll(req.Body)
if err != nil {
log.Printf("Cannot create request body: %v", err)
res.Request.Body = "N/A"
return
}
contentType := req.Header.Get("Content-Type")
if strings.EqualFold("application/json", contentType) {
err = json.Unmarshal(b, &res.Request.Body)
if err != nil {
log.Printf("Cannot create json for request body: %v", err)
res.Request.Body = "N/A"
}
} else {
res.Request.Body = string(b)
}
}
func handleJWT(tokenString string, jwtPayload *JwtPayload) {
tokenString, _ = strings.CutPrefix(tokenString, "Bearer ")
token, _, err := jwt.NewParser().ParseUnverified(tokenString, jwt.MapClaims{})
if err != nil {
log.Printf("Error parsing JWT Token: %v", err)
return
}
jwtPayload.Header = token.Header
jwtPayload.Payload = token.Claims
}