An API implementing the instructions from this API.
The instructions could (and probably should) have been interpreted a little more literally than what this repo represents. An API with two endpoints, one for London users and another for users within 50 miles of London would have probably sufficed.
However, after looking at the source API and the requested features I thought I'd implement an API providing the capability I'd imagine would be required from the API after several rounds of iteration. This approach isn't always a good idea given the requirements for the additional functionality might never materialise and it ignores the principle of YAGNI, however, I thought I'd do it anyway.
Therefore, this API has an endpoint that will return people for any given city, as long as the city has results in the source API. The same endpoint also allows a variable distance from which people should be returned from any city, rather than just London.
This API has been documented using OpenAPI 3.0 Specification. The file is available within the repo - swagger.yml.
To view the file in an online editor and use the 'Try it out' features, click this link.
Note: there is no link between the editor and the repository. Any changes made in the editor will not be saved back to the repository.
Node.js needs to be installed in the environment
where the app will be run. Dependencies are installed via npm install
.
The app can be started by running npm run start
after which the API will be
available at http://localhost:3000.
If you have Docker installed, the app can be built
and run without any concern for the state of the local environment e.g. which
version of Node.js
is installed, is npm
up to date, etc.
There is an image available in DockerHub at
st3v3nhunt/people-lister.
Running docker pull st3v3nhunt/people-lister:latest && docker run --init -p 3000:3000 st3v3nhunt/people-lister:latest
will retrieve the image
and start application running.
It will be available at http://localhost:3000.
The app can be built and run locally (rather than using the DockerHub image).
To do this, build the image with docker build . -t people-lister
(this may
take several minutes depending on network and machine performance).
Once the image is built it can be run with docker run --init -p 3000:3000 -t people-lister
. This will start the application running on port
3000
and will be available at http://localhost:3000.
If port 3000
isn't suitable, change the first 3000
in the docker run
command
to a suitable port e.g. docker run --init -p 5000:3000 -t people-lister
would
make the site available on port 5000
.
The root route of the API provides a set of links which can be followed to see the results of the requested functionality i.e. listing users living in London and listing users located within 50 miles of London. There are additional links, each with information about what the link provides.
The root of the API e.g. http://localhost:3000 is best viewed using a browser with a JSON pretty print extension e.g. JSONView or JSON Formatter (both of which are Chrome browser extensions - other browsers and extensions are available).
The following environment variables are used within the application.
Variable | Description | Default |
---|---|---|
API_SERVER |
FQDN of the API server, including protocol | https://bpdts-test-app.herokuapp.com |
LOG_LEVEL |
An integer representing the level of logging to do. See Bunyan Levels | 30 (info) |
PORT |
The port the application is available on | 3000 |
The source API is case sensitive. I've decided not to enforce case sensitivity
on my API and I've assumed cities are capitalised on the first letter only -
should this not be the case, this API would return a 404
as no
results would be found on the source API. Assumptions are generally not a good
idea but in this case I'm unable to ask whether this is correct or not.
I've not enforced case sensitivity, even though there are several
RFCs stating this should be the case
because I believe it is a more pragmatic approach, making the API easier to
use. The easier an API is to use, the more likely it is to be used whilst also
reducing the number of bugs - whether they are defects in the software or
understanding of how it works by users.
Case sensitivity feels like an unnecessary implementation detail that should
not be exposed to clients.
In order to provide the ability for cities other than London to return results with a given distance I've used Geocode.xyz. Geocode provides a free API for geocoding. The API is rate limited to ~1 request per second when no authentication is supplied as per the usage limits. All cities expect for London are looked up. London's coordinates are hard coded within the app to ensure it will work even if Geocode was to fail. Caching the results of the lookup would be a good next step to take as the location of a city is unlikely to change over the course of the application's runtime.
Testing has been focused on outside in i.e. an integration test was created to test a feature of the API. As a consequence and largely due to the simplicity of the API, there are very few unit tests. Code coverage stats show the test coverage is high.
- Language - Node.js
- Package manager - npm
- Web framework - Express.js
- HTTP request library - request-promise-native.
- Geocoding uses the geocode.xyz API
- Logging - bunyan
- nodemon for auto-reloading of the app
- husky for githooks
- Test framework - Mocha
- Assertion library - Chai assertions and Chai HTTP for integration testing
- API response mocking - nock
- Code coverage - nyc
- Linting - ESLint with eslint-config-nhsuk