Skip to content

Commit 2642afd

Browse files
committed
Simple mock server to simulate integrations
1 parent 028b197 commit 2642afd

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed

mock-server/lockpath/login-req.xml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<Login><username>username</username><password>password</password></Login>

mock-server/lockpath/login-resp.xml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<boolean xmlns="http://schemas.microsoft.com/2003/10/Serialization/">true</boolean>

mock-server/lockpath/routes.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"path": "/SecurityService/Login",
4+
"method": "POST",
5+
"request": "login-req.xml",
6+
"response": "login-resp.xml"
7+
},
8+
{
9+
"path": "/SecurityService/Logout",
10+
"method": "POST"
11+
},
12+
{
13+
"path": "/ComponentService/GetComponentList",
14+
"method": "POST"
15+
}
16+
]

mock-server/server.go

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
"io/ioutil"
9+
"encoding/json"
10+
"net/http"
11+
"strconv"
12+
"bytes"
13+
"io"
14+
)
15+
16+
var (
17+
folder = flag.String("folder", ".", "The location of the responses and routes files")
18+
port = flag.String("port", "5050", "The port to listen on")
19+
)
20+
21+
type param struct {
22+
Name string `json:"name"`
23+
Type string `json:"type"`
24+
Mandatory bool `json:"mandatory"`
25+
}
26+
27+
type route struct {
28+
Path string `json:"path"` // Path we should listen to
29+
Method string `json:"method"` // Method we expect
30+
Parameters []param `json:"parameters"` // Parameters we should accept and check
31+
Request string `json:"request"` // Request body we should get
32+
Status int `json:"status"`
33+
Response string `json:"response"` // Response file - assumed to be in the same folder
34+
Headers string `json:"headers"` // Headers to return - can also include cookies, etc. - JSON format
35+
}
36+
37+
type header struct {
38+
Name string `json:"name"`
39+
Value string `json:"value"`
40+
}
41+
42+
func printAndExit(format string, args ...interface{}) {
43+
fmt.Fprintf(os.Stderr, format, args...)
44+
os.Exit(1)
45+
}
46+
47+
func check(err error) {
48+
if err != nil {
49+
printAndExit("%v", err)
50+
}
51+
}
52+
53+
type handler struct {
54+
routes []route
55+
}
56+
57+
func checkParam(p *param, r *http.Request) error {
58+
val := r.Form.Get(p.Name)
59+
if p.Mandatory && val == "" {
60+
return fmt.Errorf("Param [%s] was not provided", p.Name)
61+
}
62+
switch p.Type {
63+
case "int":
64+
_, err := strconv.Atoi(val)
65+
return err
66+
case "bool":
67+
_, err := strconv.ParseBool(val)
68+
return err
69+
}
70+
return nil
71+
}
72+
73+
func (h *handler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
74+
fmt.Printf("Received %s\n", r.URL.Path)
75+
for _, rp := range h.routes {
76+
if rp.Path == r.URL.Path && rp.Method == r.Method {
77+
fmt.Printf("Found handler - %s\n", rp.Path)
78+
for _, p := range rp.Parameters {
79+
err := checkParam(&p, r)
80+
if err != nil {
81+
rw.WriteHeader(http.StatusBadRequest)
82+
rw.Write([]byte(err.Error()))
83+
return
84+
}
85+
}
86+
if rp.Request != "" {
87+
reqdata, err := ioutil.ReadFile(filepath.Join(*folder, rp.Request))
88+
check(err)
89+
actual := make([]byte, len(reqdata))
90+
_, err = r.Body.Read(actual)
91+
if err != nil && err != io.EOF {
92+
rw.WriteHeader(http.StatusBadRequest)
93+
rw.Write([]byte(err.Error()))
94+
return
95+
}
96+
if !bytes.Equal(reqdata, actual) {
97+
rw.WriteHeader(http.StatusBadRequest)
98+
rw.Write([]byte(fmt.Sprintf("Wrong request.\nExpected:\n[%s]\nGot:\n[%s]\n", string(reqdata), string(actual))))
99+
return
100+
}
101+
}
102+
if rp.Response != "" {
103+
data, err := ioutil.ReadFile(filepath.Join(*folder, rp.Response))
104+
check(err)
105+
_, err = rw.Write(data)
106+
check(err)
107+
}
108+
if rp.Headers != "" {
109+
headersData, err := ioutil.ReadFile(filepath.Join(*folder, rp.Headers))
110+
check(err)
111+
var headers []header
112+
err = json.Unmarshal(headersData, &headers)
113+
check(err)
114+
for _, h := range headers {
115+
rw.Header().Add(h.Name, h.Value)
116+
}
117+
}
118+
status := rp.Status
119+
if status == 0 {
120+
status = 200
121+
}
122+
rw.WriteHeader(rp.Status)
123+
return
124+
}
125+
}
126+
rw.WriteHeader(http.StatusNotFound)
127+
_, err := rw.Write([]byte("Not found"))
128+
check(err)
129+
}
130+
131+
func main() {
132+
flag.Parse()
133+
routesFile := filepath.Join(*folder, "routes.json")
134+
routesData, err := ioutil.ReadFile(routesFile)
135+
check(err)
136+
var routes []route
137+
err = json.Unmarshal(routesData, &routes)
138+
check(err)
139+
h := &handler{routes: routes}
140+
err = http.ListenAndServe(":" + *port, h)
141+
check(err)
142+
}

0 commit comments

Comments
 (0)