REST API built with Go, Echo, PostgreSQL, Pgx, go-migrate and SQLC
- Go 1.22+
- Git
- Docker
The goal here is to build tests first whenever possible so that the API design and driven by tests.
The httpexpect
package is being used for testing the REST API.
It is a really cool package and has a realy cool API that makes
testing HTTP and REST api cool.
The tests take advantage of TestMain
which resets the database
before the tests run. go-migrate
is used to drop the schema
and then generate the schema whenever tests are run.
Go caches the tests but that is not desired here so ensure
cache is not enabled I have added a make test
command
which ensures the code runs in test mode APP_ENV=test
and
cache is disabled -count=1
. The test
command:
I was struggling to write http related tests in Go cuz I
didn't like the API but things became clearer to me when
I found out about httpexpect
and saw the
echo test example.
The example from the repo as you see is really simple but it is enough
to get started. I have added a bunch of things on top of it like
testutils
functions which reset the test database and create a testing user.
I have also refactored the example code to use newer code from the echo
documentation.
test:
APP_ENV=test go test ./... -count=1
- Create a .env file, install required tools and run docker compose
cp .env.example .env
make install-tools
make tidy
make docker-up
- Seed the database
make db-seed
- Run the dev server
air
Server is running on localhost:8080
I installed wrk
to benchmark my API locally. That is how I did:
- Build the binary and run it in production mode
make build-api
make start
- Seed the database
make db-seed
- Login to generate a jwt token
## TODO: use application/json instead. change handler to decode JSON from body
curl -X POST http://localhost:8080/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "email=paulo@example.com&password=password12"
# Result
{"token": "..."}
- Copy the generated token and export an env variable
export JWT="<copied token>"
- Run wrk against a protected route which will verify the token on every request
# Using 15 threads and 1000 concurrent connections during 1 minute
wrk -t15 -c1000 -d60s -H 'Content-Type: application/json' \
-H "Authorization: Bearer ${JWT}" \
http://localhost:8080/restricted/hello
- Result I got. My specs: M2 Pro 16GB RAM
Running 1m test @ http://localhost:8080/restricted/hello
15 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.50ms 4.22ms 62.80ms 71.86%
Req/Sec 3.49k 1.64k 8.67k 70.98%
3125402 requests in 1.00m, 482.86MB read
Socket errors: connect 755, read 100, write 0, timeout 0
Requests/sec: 52053.16
Transfer/sec: 8.04MB
I'm impressed! That is really cool. No performance tunning has been made.