Takehome is a production-ready REST API that accepts a list of country codes and returns a list of country codes that are in the same continent as the country code input.
To keep the data of countries and continents up to date, it's sourced from the [GraphQL Countries API] (https://countries.trevorblades.com/graphql) and cached when the application starts. In further updates, we can implement a scheduled job to update the cache periodically.
In order to not overwhelm the server, this Takehome Project integrates with the Spring Security OAuth2 and JWT framework to provide a secured REST API with limits depends on the user's authentication status.
A rate limit of 5 requests per sec for unauthenticated users and 20 requests per second for authenticated users.
Google Guava RateLimiter is used to implement the rate limiting. There is possibility to exceed the rate limit
by a few requests.
In further updates, we can implement a more accurate rate limiting by rewrite the RateLimitingFilter.
In addition, you may use Docker to containerize this API.
- Build the project using 'gradle build'
./gradlew build
- Create docker image using 'docker build -t evanshi80/takehome .'
docker build -t evanshi80/takehome .
- Run the docker image using 'docker run -p 8080:8080 evanshi80/takehome'
docker run -d -p 8080:8080 evanshi80/takehome
- the app is running on localhost:8080
- Use Postman to send a POST request to http://localhost:8080/findOtherCountries with a JSON body containing a list of country codes
["US","CA","CN","Z11W"]
- The response will be a JSON body containing a list of JSON Objects. Different continents will be clustered in different groups.
[
{ // each continent is a group
"countryCodes": [ // this represents the requested country codes grouped by continent
"CN"
],
"continentName": "Asia", // this represents the continent name
"otherCountryCodes": [ // this represents the other country codes found in the same continent,
// excluding the requested country codes
"AE",
"AF",
...]
},
{ // this is another group of the continent "North America"
"countryCodes": [
"US",
"CA"
],
"continentName": "North America",
"otherCountryCodes": [
"AG",
"AI",
"AW",
...]
}
]
- If one of the country codes is invalid, that code will be ignored.
- If all the country codes are invalid, the response will be a JSON body containing an empty list
- Use PostMan Collection's Run feature to run the test cases,create a collection 'Takehome API test'
- Drag the above Http Request test into this collection
- Set the runner to run the collection 10 times without delay
- Run the collection
- '429 Too Many Requests responses' will be returned on those requests that exceed the rate limit 5
- Fetch the token from the Auth0 Aurthorization Server
curl --request POST \
--url https://dev-ousg77uz1ajb0gz0.us.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{"client_id":"AL54SE9RglWZdLUJ9hNNBqU3UJLUQ1NQ","client_secret":"LQNaSty9bSBMV0LMwsxtZcoIyNO2rmmbLWV_BLvT47uWKpJ-GevrgQgec-ZAs4NW","audience":"https://takehome.yfs/api/","grant_type":"client_credentials"}'
- Set the Authorization property in HTTP Request to use OAuth 2 and select the option 'add auth data to Request Headers'
- In the Access Token field, paste the token from the response of the step 6
- Make sure the header prefix is set to Bearer
- Run the collection again
- You will see the requests are all successful with 200 OK responses
- You could also use the Actuator APIs to monitor the application
- The Actuator APIs are secured by Spring Security OAuth2 and JWT framework
- You need to send bearer token to access the Actuator APIs within the Authorization header
- The bearer token is the same as the one used to access the Takehome API
- The Actuator APIs are available at http://localhost:8080/actuator
- Only the following APIs are available
/actuator/health
/actuator/info
/actuator/metrics
/actuator/metrics/{requiredMetricName}
- BTW, the Actuator APIs are not rate limited.