Simple HTTP server that manages user data. XML and JSON payload types are both accepted.
Functionalities are below:
POST /users
create new user given user email and name. It will return a created user with a unique system assigned user ID. Additionally, I added the constraint that emails are unique.GET /users/:userID
get user data given a system assigned user ID. It will returns saved user data.PATCH /users/:userID
update user data given a system assigned user ID. It will allow to change user name only.
As extra, I have added below behaviors to the API:
- basic rate limiting of 30 req/min.
- autogenerated X-Request-Id which is logged during every request and returned in headers.
- returned 409 for all domain business errors. This is to reduce the number of HTTP status that a consumer has to handle. Also, 400 is returned when there is a validation error with the request. 500 is for unexpected or critical errors.
- Fiber: web framework used, an express like for Go.
- Air: for live reloading of the service during local development.
- Testify: assertion library used.
- go.uuid: for unique id generation.
- validator: for validating using struct tags.
# clone repo
git clone https://github.com/JordyBaylac/user-management-service.git -b main
# install dependencies
go get ./...
# build, test and run
go build -v ./...
go test -v
go run main.go
# make sure api is working
curl --request GET --url http://localhost:8080/health
## (optional) for live reloading
# install air
curl -sSfL https://raw.githubusercontent.com/cosmtrek/air/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
# run
air
# if error 'air: command not found', then add to PATH and run again
export PATH=$PATH:$(go env GOPATH)/bin
curl --request POST \
--url https://jbaylac-user-management-svc.herokuapp.com/users \
--header 'Content-Type: application/xml' \
--data '<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>Neymar</name>
<email>[email protected]</email>
</user>'
curl --request GET --url https://jbaylac-user-management-svc.herokuapp.com/users/:userID
curl --request PATCH \
--url https://jbaylac-user-management-svc.herokuapp.com/users/:userID \
--header 'Content-Type: application/json' \
--data '{
"name": "Neymar da Silva Santos Junior"
}'
This solution embraces decoupling and extensibility through inversion of control. There is a lot of room for improvement, but I think this architecture is easy to maintain, change and evolve with new requirements.
- api/ package is the interface of this service. It's where the http server is configured (routes, middlewares, etc)
- user/ it is a domain specific package that contains business regarding the management of users.
- pentest the api.
- implement persistence storage with a real database.
- implement a custom error handler.
- improve error response model and add codes to business errros.
- add swagger generation for the api.
- add correlation id for distributed tracing.
- add structured logging.
- add metrics.
- refactor project layout to a more conventional one.
- authenticate calls, so that updating a user is only allowed to the creator.
- integrate with a configuration as a service to get secrets and other configs per environment.
- run performance tests, pprof and check race conditions.