-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathapi_http.go
More file actions
95 lines (84 loc) · 2.65 KB
/
api_http.go
File metadata and controls
95 lines (84 loc) · 2.65 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
package docs
import (
"encoding/json"
"net/http"
"os"
"strings"
"github.com/pkg/errors"
)
// Swagger returns an HTTP handler that exposes the swagger.json doc directly.
// It's not a gRPC method because some clients will want to consume this URL directly,
// rather than interpreting a JSON string from inside a response.
func Swagger() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
b, err := swaggerForRequest(req, "/stackrox/static-data/docs/api/v1/swagger.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
msg := err.Error()
_, _ = w.Write([]byte(msg))
return
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write(b)
})
}
// SwaggerV2 returns an HTTP handler that exposes the v2 API's swagger.json doc directly.
// It's not a gRPC method because some clients will want to consume this URL directly,
// rather than interpreting a JSON string from inside a response.
func SwaggerV2() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
b, err := swaggerForRequest(req, "/stackrox/static-data/docs/api/v2/swagger.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
msg := err.Error()
_, _ = w.Write([]byte(msg))
return
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write(b)
})
}
func swaggerForRequest(req *http.Request, swaggerPath string) ([]byte, error) {
b, err := os.ReadFile(swaggerPath)
if err != nil {
return nil, errors.Wrap(err, "could not load swagger file")
}
var swaggerSpec map[string]json.RawMessage
if err := json.Unmarshal(b, &swaggerSpec); err != nil {
return nil, errors.Wrap(err, "could not parse swagger spec")
}
swaggerSpecOut := make(map[string]interface{}, len(swaggerSpec)+2)
for k, v := range swaggerSpec {
swaggerSpecOut[k] = v
}
scheme, host := extractSchemeAndHost(req)
swaggerSpecOut["host"] = host
swaggerSpecOut["schemes"] = []string{scheme}
out, err := json.MarshalIndent(swaggerSpecOut, "", " ")
if err != nil {
return nil, errors.Wrap(err, "could not marshal swagger spec")
}
return out, nil
}
func extractSchemeAndHost(req *http.Request) (string, string) {
forwardedProto := req.Header.Get("X-Forwarded-Proto")
forwardedHost := req.Header.Get("X-Forwarded-Host")
if forwardedHost != "" && forwardedProto != "" {
return strings.ToLower(forwardedProto), forwardedHost
}
scheme := req.URL.Scheme
if scheme == "" {
if req.TLS != nil {
scheme = "https"
} else {
scheme = "http"
}
}
host := req.Host
if host == "" {
host = req.URL.Host
}
return scheme, host
}