# Task: create an endpoint to list all the referrals a user has made The app should be able to call `GET /waitlist/referrals` and get a list of all the referrals a user has made, *roughly* something like: ``` { "referrals": 7 } ``` ## How to create a new API endpoint If you want to create an endpoint `/waitlist/referrals`, you need to figure out which service handles all the paths under `/waitlist`. You can look at `ingress/kube.yaml` to figure this out. (In this case it's `service.waitlist`.) The most basic endpoint would look something like this (at `service.waitlist/http_server/get_waitlist_referrals.go`): ``` package http_server import ( "net/http" "github.com/umbermoney/buildthebank/libraries/errors" "github.com/umbermoney/buildthebank/libraries/session" "github.com/umbermoney/buildthebank/service.waitlist/dao" ) type GETWaitlistReferralsResponse struct { Referrals int `json:"referrals"` } func GETWaitlistReferrals(req *http.Request) (interface{}, *errors.Error) { userID, err := session.GetAuthenticatedUserID(req) if err != nil { return nil, err } referralsCount, err := dao.CountReferralsByUser(userID) if err != nil { return nil, err } return GETWaitlistReferralsResponse{ Referrals: referralsCount, }, nil } ``` This function would need to be registered in `service.waitlist/http_server/server.go`, in order for it to serve the right path. You need to implement a `dao` method that counts the number of referrals for a particular user. It may be helpful to look at: - https://www.db-fiddle.com/ (for testing out SQL queries) - https://gorm.io/docs/connecting_to_the_database.html (to see how our ORM works, so you know how to query the database (you can use `db.Raw` to query the database with raw SQL if need be)) ## How to test this endpoint locally From within `~/src/github.com/umbermoney/buildthebank`: ``` ./scripts/local/teardown.sh ./scripts/local/setup.sh ./scripts/local/locurl.sh GET service.waitlist /waitlist/referrals ``` ## Glossary **Endpoint**: A combination of an HTTP method and a path. An endpoint is something you can `curl` and get a response. **Handler**: A function that handles a request - either an HTTP request from the outside world, or a GRPC request from another service. API handlers will live in an `http_server` directory, whereas GRPC handlers will live in an `rpc_server` directory. ## How local services work We have a script at `scripts/local/setup.sh`. This lists every directory beginning with "service.", checks if it's a Go program (i.e. if it contains a file `main.go` at the root of the directory), then builds it. It then picks a random port, starts the service running at that port (by starting it with an environment variable `SERVICE_{WHATEVER}_API_PORT` and/or `SERVICE_{WHATEVER}_RPC_PORT` for the HTTP and GRPC servers respectively, if it has either or both) and writing those ports to a file called `/tmp/umber/local/.profile`. ### Errors with local services **Connection refused** This probably means the service was started but crashed immediately. The [stderr](https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)) file stream, which normally would be printed to your terminal if you ran it with `go run`, is written to `/tmp/umber/local/service.user/stderr`, replacing `service.user` with whatever the service in question is. **Authentication error** Either you didn't supply the two headers `AgentUserID` and `AgentAuthToken`, or these were invalid. You *could* try to log in, but the login process is complicated (for good reason). It's probably easiest to create a new user, and store the `session` object returned in the JSON response. Then whenever you make a `curl` command to an endpoint that requires the user to be logged in, make sure it contains the headers. E.g.: `curl -H "AgentUserID: user_abc" -H "AgentAuthToken: awlkdnawlkd" -X POST -d '{"foo": "bar"}' localhost:$SERVICE_USER_API_PORT/users/update` We should have a neater way of doing this, but for now the easiest way is to manually edit the `scripts/local/locurl.sh` script to shove those headers in right after the word `curl`. It's early days! ## Resources **Go in general** - [Go By Example](https://gobyexample.com/) - [Effective Go](https://golang.org/doc/effective_go.html) **HTTP in general** - [The HTTP protocol (Mozilla)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview) **The command line in general** - [Unix command line cheatsheet](http://www.mathcs.emory.edu/~valerie/courses/fall10/155/resources/unix_cheatsheet.html) -