Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27d54a67c5 | ||
|
|
394b6c6b19 | ||
|
|
572a661570 | ||
|
|
ae2c5d1f80 | ||
|
|
0b8223504c | ||
|
|
d10a176e53 | ||
|
|
e8636e09ac | ||
|
|
109e665451 | ||
|
|
33c6293042 | ||
|
|
6c93e2987b | ||
|
|
cfdeef0e2a | ||
|
|
1842453288 | ||
|
|
9fdfd5cb17 | ||
|
|
62d92811ce | ||
|
|
5e0380377f | ||
|
|
669c88abce | ||
|
|
46ce22d8ec | ||
|
|
6e8531123f | ||
|
|
f651a27580 | ||
|
|
900118758f | ||
|
|
2da157319c | ||
|
|
1f0946a0b1 | ||
|
|
1b5234d37c | ||
|
|
b334dcfcea | ||
|
|
f09931b33a | ||
|
|
afd2708b14 | ||
|
|
f35f940d90 |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [lukaszbudnik]
|
||||
2
.github/workflows/docker-image.yml
vendored
2
.github/workflows/docker-image.yml
vendored
@@ -7,6 +7,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- name: Build the Docker image
|
||||
run: docker build . --file Dockerfile --tag yosoy-local:$(date +%s)
|
||||
|
||||
10
.github/workflows/docker-publish.yml
vendored
10
.github/workflows/docker-publish.yml
vendored
@@ -15,16 +15,16 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.1.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
lukasz/yosoy
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
type=semver,pattern={{major}}
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
||||
4
.github/workflows/go.yml
vendored
4
.github/workflows/go.yml
vendored
@@ -6,10 +6,10 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
- uses: actions/checkout@v3.1.0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.16
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.17.0-alpine3.13 as builder
|
||||
FROM golang:1.17.3-alpine3.13 as builder
|
||||
|
||||
LABEL maintainer="Łukasz Budnik lukasz.budnik@gmail.com"
|
||||
|
||||
@@ -6,7 +6,7 @@ LABEL maintainer="Łukasz Budnik lukasz.budnik@gmail.com"
|
||||
ADD . /go/yosoy
|
||||
RUN cd /go/yosoy && go build
|
||||
|
||||
FROM alpine:3.14.1
|
||||
FROM alpine:3.16.2
|
||||
COPY --from=builder /go/yosoy/yosoy /bin
|
||||
|
||||
# register entrypoint
|
||||
|
||||
113
README.md
113
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
|
||||
- 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
|
||||
|
||||
See [Kubernetes example](#kubernetes-example) below.
|
||||
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\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2
go.mod
2
go.mod
@@ -5,5 +5,5 @@ go 1.16
|
||||
require (
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
)
|
||||
|
||||
13
go.sum
13
go.sum
@@ -1,5 +1,6 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
@@ -9,8 +10,12 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"])
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user