From f35f940d90660ba461d3dc4e9e43dfbc9d7e0274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Budnik?= Date: Tue, 24 Aug 2021 21:25:44 +0200 Subject: [PATCH] additional fields in JSON response --- README.md | 115 ++++++++++++++++++++++++++++--------------- server.go | 8 +++ server_test.go | 6 ++- test/deployment.yaml | 2 +- 4 files changed, 89 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 11aa8b7..f71f7d6 100644 --- a/README.md +++ b/README.md @@ -2,39 +2,49 @@ yosoy is a HTTP service for stubbing and prototyping distributed applications. It is a service which will introduce itself to the caller and print some useful information about its environment. "Yo soy" in espaƱol means "I am". -yosoy is extremely useful when creating a distributed application stub and you need to see a more meaningful responses than a default nginx welcome page. +yosoy is extremely useful when creating a distributed application stub and you need to see more meaningful responses than a default nginx welcome page. Typical use cases include: -* testing HTTP routing & ingress -* testing HTTP load balancing -* testing HTTP caching -* stubbing and prototyping distributed applications +- testing HTTP routing & ingress +- testing HTTP load balancing +- testing HTTP caching +- stubbing and prototyping distributed applications ## API yosoy responds to all requests with a JSON containing the information about: -* HTTP request: - * Host - * Request URI - * Remote IP - * HTTP headers - * HTTP proxy headers -* host: - * Hostname - * How many times it was called - * Env variables if `YOSOY_SHOW_ENVS` is set to `true`, `yes`, `on`, or `1` - * Files' contents if `YOSOY_SHOW_FILES` is set to a comma-separated list of (valid) files - -See [Kubernetes example](#kubernetes-example) below. +- HTTP request: + - Host + - Request URI + - Method + - Scheme + - Proto + - URL + - Remote IP + - HTTP headers + - HTTP proxy headers +- host: + - Hostname + - How many times it was called + - Env variables if `YOSOY_SHOW_ENVS` is set to `true`, `yes`, `on`, or `1` + - Files' contents if `YOSOY_SHOW_FILES` is set to a comma-separated list of (valid) files + +Checkout out [Sample JSON response](#sample-json-response) below to see how useful yosoy is when troubleshooting/stubbing/prototyping distributed applications. ## Docker image The docker image is available on docker hub: +```sh +docker pull lukasz/yosoy ``` -lukasz/yosoy + +and ghcr.io: + +```sh +docker pull ghcr.io/lukaszbudnik/yosoy ``` It exposes HTTP service on port 80. @@ -59,40 +69,65 @@ curl -H "Host: gateway.myapp.com" $URL/camarero/abc curl -H "Host: gateway.myapp.com" $URL/camarero/abc ``` -A sample response looks like this: +## Sample JSON response + +A sample yosoy JSON response to a request made from a single page application (SPA) to a backend API deployed in Kubernetes behind nginx ingress and [haproxy-auth-gateway](https://github.com/lukaszbudnik/haproxy-auth-gateway) looks like this: ```json { - "host": "gateway.myapp.com", - "requestUri": "/camarero/abc", - "remoteAddr": "172.17.0.1", - "counter": 4, + "host": "api.localtest.me", + "proto": "HTTP/1.1", + "method": "GET", + "scheme": "https", + "requestUri": "/camarero", + "url": "https:///camarero", + "remoteAddr": "192.168.65.3", + "counter": 1, "headers": { - "Accept": [ - "*/*" + "Accept": ["*/*"], + "Accept-Encoding": ["gzip, deflate, br"], + "Accept-Language": ["en-US,en;q=0.9,pl-PL;q=0.8,pl;q=0.7,es;q=0.6"], + "Authorization": [ + "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXejFuaDNCWDI4UHMxVEMzSDRoOW52Q1VWRXpjVVBzQms4Z1NmeEp4ZS1JIn0.eyJleHAiOjE2Mjk4MjM3OTMsImlhdCI6MTYyOTgyMjg5MywiYXV0aF90aW1lIjoxNjI5ODIyODkyLCJqdGkiOiI3ZmQzMjkwZi05NjMyLTQ0NzEtYjRjOS1lNTFjZDYwMjllYjgiLCJpc3MiOiJodHRwczovL2F1dGgubG9jYWx0ZXN0Lm1lL2F1dGgvcmVhbG1zL2hvdGVsIiwic3ViIjoiMDdmYzM3YmYtMmJjNy00ZTRmLWE3MDUtYzRjNjgzNTIwYmU1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicmVhY3QiLCJub25jZSI6IjQzNDhmMjU5LTliYTYtNDk2ZC04N2I5LWZmZGYzNDMwN2UzOSIsInNlc3Npb25fc3RhdGUiOiJmNTM5OGI3Ny01OTNhLTQ3OWYtOTc5NS00NGIyNGJjMjhkYjQiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHBzOi8vbHVrYXN6YnVkbmlrLmdpdGh1Yi5pbyJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiY2FtYXJlcm8iXX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJzaWQiOiJmNTM5OGI3Ny01OTNhLTQ3OWYtOTc5NS00NGIyNGJjMjhkYjQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJKdWxpbyIsInByZWZlcnJlZF91c2VybmFtZSI6Imp1bGlvIiwiZ2l2ZW5fbmFtZSI6Ikp1bGlvIn0.t5y3L4FzGxM0zwI3fskDI8Kemxz_izcvPPKciSEvNHnZWGQK-9AclGNFz_A9cLFSkpc6l6lBmt7WaC0i04c4h1a9G9AOFImmVXPMPDdTXOQ4aah4CvlN6Fy8ShvSHrQA-wMHEELBpIFsKFx2WP3QHiy27ycr3kqQzW4QymyU7J8tM4-qKR_H1_8aiNOrm5fIED-nEP096V2zvWXiGZX7ts6XE2-annhKphCABLdmIiwgDUnhlAz0hdiDrDbIjzr0ldW4AnUkSQxIZY0PnoEnGVuUvkOYvJpFx10gjORMnRgHSEj9Mk5dtyVGHcihZ5TntCL40WoymNxae6K4-FH3Lw" ], + "Origin": ["https://lukaszbudnik.github.io"], + "Referer": ["https://lukaszbudnik.github.io/"], + "Sec-Ch-Ua": [ + "\" Not;A Brand\";v=\"99\", \"Google Chrome\";v=\"91\", \"Chromium\";v=\"91\"" + ], + "Sec-Ch-Ua-Mobile": ["?0"], + "Sec-Fetch-Dest": ["empty"], + "Sec-Fetch-Mode": ["cors"], + "Sec-Fetch-Site": ["cross-site"], "User-Agent": [ - "curl/7.64.1" - ] + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" + ], + "X-Forwarded-For": ["192.168.65.3", "10.1.3.9"], + "X-Forwarded-Host": ["api.localtest.me"], + "X-Forwarded-Port": ["443"], + "X-Forwarded-Proto": ["https"], + "X-Real-Ip": ["192.168.65.3"], + "X-Request-Id": ["48a77564d88ca8a893610b9458bfd885"], + "X-Scheme": ["https"] }, - "hostname": "camarero-77787464ff-hjdkq", + "hostname": "camarero-cf7c95ccd-cz5lh", "envVariables": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "HOSTNAME=camarero-77787464ff-hjdkq", - "YOSOY_SHOW_ENVS=true", + "HOSTNAME=camarero-cf7c95ccd-cz5lh", "YOSOY_SHOW_FILES=/etc/podinfo/labels,/etc/podinfo/annotations", - "CAMARERO_SERVICE_HOST=10.97.113.33", - "CAMARERO_PORT=tcp://10.97.113.33:80", - "CAMARERO_PORT_80_TCP=tcp://10.97.113.33:80", - "CAMARERO_PORT_80_TCP_ADDR=10.97.113.33", - "CAMARERO_SERVICE_PORT=80", - "CAMARERO_PORT_80_TCP_PROTO=tcp", - "CAMARERO_PORT_80_TCP_PORT=80", + "YOSOY_SHOW_ENVS=true", + "KUBERNETES_SERVICE_PORT=443", + "KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443", + "KUBERNETES_PORT=tcp://10.96.0.1:443", + "KUBERNETES_PORT_443_TCP_PORT=443", + "KUBERNETES_SERVICE_HOST=10.96.0.1", + "KUBERNETES_PORT_443_TCP_PROTO=tcp", + "KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1", "HOME=/root" ], "files": { - "/etc/podinfo/annotations": "kubernetes.io/config.seen=\"2021-02-03T13:18:34.563751030Z\"\nkubernetes.io/config.source=\"api\"", - "/etc/podinfo/labels": "app.kubernetes.io/name=\"camarero\"\npod-template-hash=\"77787464ff\"" + "/etc/podinfo/annotations": "kubernetes.io/config.seen=\"2021-08-24T15:12:19.555374430Z\"\nkubernetes.io/config.source=\"api\"", + "/etc/podinfo/labels": "app.kubernetes.io/component=\"api\"\napp.kubernetes.io/name=\"camarero\"\napp.kubernetes.io/part-of=\"hotel\"\napp.kubernetes.io/version=\"0.0.1\"\npod-template-hash=\"cf7c95ccd\"" } } ``` diff --git a/server.go b/server.go index 2bf93cf..8f03098 100644 --- a/server.go +++ b/server.go @@ -14,7 +14,11 @@ import ( type response struct { Host string `json:"host"` + Proto string `json:"proto"` + Method string `json:"method"` + Scheme string `json:"scheme"` RequestURI string `json:"requestUri"` + URL string `json:"url"` RemoteAddr string `json:"remoteAddr"` Counter int `json:"counter"` Headers map[string][]string `json:"headers"` @@ -52,7 +56,11 @@ func handler(w http.ResponseWriter, req *http.Request) { response.RequestURI = req.RequestURI response.Host = req.Host + response.Proto = req.Proto + response.Method = req.Method + response.Scheme = req.URL.Scheme response.Headers = req.Header + response.URL = req.URL.String() response.Hostname = hostname diff --git a/server_test.go b/server_test.go index 896b8d1..7a0e7b0 100644 --- a/server_test.go +++ b/server_test.go @@ -14,7 +14,7 @@ func TestHandler(t *testing.T) { os.Setenv("YOSOY_SHOW_ENVS", "true") os.Setenv("YOSOY_SHOW_FILES", ".gitignore") - req, err := http.NewRequest("GET", "https://example.org/sample/path", nil) + req, err := http.NewRequest("GET", "https://example.org/sample/path?one=jeden&two=dwa", nil) if err != nil { t.Fatal(err) } @@ -35,6 +35,10 @@ func TestHandler(t *testing.T) { // test response assert.Equal(t, 1, response.Counter) assert.Equal(t, "example.org", response.Host) + assert.Equal(t, "GET", response.Method) + assert.Equal(t, "https", response.Scheme) + assert.Equal(t, "HTTP/1.1", response.Proto) + assert.Equal(t, "https://example.org/sample/path?one=jeden&two=dwa", response.URL) assert.NotEmpty(t, response.EnvVariables) assert.NotEmpty(t, response.Files[".gitignore"]) diff --git a/test/deployment.yaml b/test/deployment.yaml index 1b672e7..75acab3 100644 --- a/test/deployment.yaml +++ b/test/deployment.yaml @@ -16,7 +16,7 @@ spec: spec: containers: - name: yosoy - image: lukasz/yosoy + image: lukasz/yosoy:2.0.3 env: - name: YOSOY_SHOW_ENVS value: "true"