---
# System prepended metadata

title: 'Task: create an endpoint to list all the referrals a user has made'

---

# 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)
- 