-
Notifications
You must be signed in to change notification settings - Fork 23
/
server_gen.go
129 lines (91 loc) · 2.77 KB
/
server_gen.go
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
// Code copied from github.com/nsmithuk/local-kms/src:/server.go for testing by synapse modulecopier DO NOT EDIT."
package internal
import (
"fmt"
"github.com/nsmithuk/local-kms/src/config"
"github.com/nsmithuk/local-kms/src/data"
"github.com/nsmithuk/local-kms/src/handler"
log "github.com/sirupsen/logrus"
"net/http"
"reflect"
"strings"
)
func Run(port, seedPath string) {
//-----------
// DB Setup
database := data.NewDatabase(config.DatabasePath)
defer database.Close()
//-----------
// Seeding
seed(seedPath, database)
//-----------
// Start
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
handleRequest(w, r, database)
})
logger.Infof("Data will be stored in %s", config.DatabasePath)
logger.Infof("Local KMS started on 0.0.0.0:%s", port)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func handleRequest(w http.ResponseWriter, r *http.Request, database *data.Database) {
logger.Debugf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL)
if r.URL.Path != "/" {
error404(w)
} else if r.Method != "POST" {
error405(w)
} else if !strings.Contains(r.Header.Get("Content-Type"), "json") {
// Allows both application/x-amz-json-1.1 and application/json
error415(w)
} else {
w.Header().Set("Content-Type", "application/x-amz-json-1.1")
h := handler.NewRequestHandler(r, logger, database)
/*
The target endpoint is specified in the `X-Amz-Target` header.
The format is: TrentService.<method>
For example: TrentService.ListKeys
*/
target := strings.Split(r.Header.Get("X-Amz-Target"), ".")
// Ensure we have at least the 2 components we expect.
if len(target) >= 2 {
method := reflect.ValueOf(h).MethodByName(target[1])
if method.IsValid() {
result := method.Call([]reflect.Value{})
if len(result) == 0 {
logger.Panicf("Missing expected response from reflected method call\n")
}
response, ok := result[0].Interface().(handler.Response)
if !ok {
logger.Panicf("Unable to assert type of returned response\n")
}
respond(w, response)
return
}
}
// If we couldn't find a valid method matching the request
error501(w, r)
return
}
}
func respond(w http.ResponseWriter, r handler.Response) {
w.WriteHeader(r.Code)
fmt.Fprint(w, r.Body)
}
func error404(w http.ResponseWriter) {
w.WriteHeader(404)
fmt.Fprint(w, "Page not found")
}
func error405(w http.ResponseWriter) {
w.WriteHeader(405)
fmt.Fprint(w, "Method Not Allowed")
}
func error415(w http.ResponseWriter) {
w.WriteHeader(415)
fmt.Fprint(w, "Only JSON based content types accepted")
}
func error501(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(501)
fmt.Fprintf(w, "Passed X-Amz-Target (%s) is not implemented", r.Header.Get("X-Amz-Target"))
}