TripAdvisor Data Service Layer
This Node/Express application centralizes calls to the TripAdvisor reviews APIs, leveraging Redis and Mongo to cache the data, both limiting requests to TripAdvisor and improving performance.
Installation
First, clone the repo and install dependencies:
git clone https://bitbucket.org/wdnteam/resort-review
cd resort-review
npm install --production
Note that for development purposes, leave out the --production
flag to install development packages as well.
Configuration
To run, the following environment variables need to be configured in advance. As discussed in detail below, all of these could optionally be set up in a config.json file, except for NODE_ENV
- this one variable MUST be set up explicitly as an environment variable.
Variable | Description |
---|
NODE_ENV | The name of the execution environment. Case sensitive. The special value production indicates a production environment. This value is also used to identify configuration values from the configuration file as discussed below |
ENABLE_CLUSTER | Case insensitive. If true , one worker thread will be spun up per CPU core. Assumed true and ignored of NODE_ENV = production . |
PORT | The TCP port # to listen on. |
MONGODB_URI | Connection string for the Mongo database. Expected format is similar to mongodb://user:pass@server.com:27017/database |
CACHE_SERVER | Connection string for the Redis cache server. Expected format is similar to redis://localhost:6379 . |
CACHE_PASSWORD | The password, if any, to authenticate to the Redis cache server. |
TIMEOUT | How long, in seconds to keep data in Redis. This must be sufficiently large to avoid pounding on TripAdvisor's services. For production, recommend the value equal to 24 hours (86400). If not supplied, defaults to 10 seconds. |
TRIP_ADVISOR_KEY | API Key assigned by TripAdvisor. |
LANGS | CSV list of languages supported by TripAdvisor for us to display on RCI.com. Recommended value is en,zh,da,nl,fi,fr,de,el,hu,it,ja,pl,pt,ru,es,tr,sv (all TripAdvisor languages except for Arabic and Hebrew which are RTL). |
MONGODB_COLLECTION | The name of the collection (i.e., table) in Mongo to use for storing the reviews. Recommend a sensible name such as reviews . |
PAGESIZE | The # of reviews to display on RCI.com at a time. Current business requirements call for this value to be 8 . |
TA_URL_ROOT | The base URL for TripAdvisor services. The value should be https://api.tripadvisor.com/api/partner/2.0/location |
TA_TIMEOUT | The amount of time, in seconds, to require TripAdvisor.com services to respond in else assume failure and respond to the client immediately. If not supplied, defaults to 2 . Note that the underlying request library specifically defines this time as "the number of milliseconds to wait for a server to send response headers (and start the response body) before aborting the request". This value will be multipled by 1000 so as to be in milliseconds as required by request . |
LOG_DIRECTORY | The directory to output logging errors to. This must include a trailing directory signal (\ or / , depending on the operating system), or else logs will get written into an incorrect location. Log files will be named in accordance with the date/timestamp of first error output. Note that the application keeps the most-recent logfile open, so do not attempt to delete that file. |
API_KEYS | Comma separated list of authorization keys. WARNING: if this is not indicated, application-level security will be disabled (simplies the development experience, but inappropriate for production). At least one (randomized) key should be assigned to RCI services, and at least one other assigned for Endava’s use. |
Using a config.json file
As indicated above, NODE_ENV
is the only configuration variable that must be configured as an environmental variable. All other variables can be defined in a file config.json
inside of the config
folder. Any values specified in config.json
will override any values assigned as environment variables. Note that for security reasons, this file is excluded from the repo via .gitignore
.
The config/config.json
file is structured as follows. It is a simple JSON file, with one or more root nodes, the name of which matches an expected value of the NODE_ENV
environment variable. Each child key of that node is the name of one of the above-mentioned configuration variables, with its value the value to assign to the variable. For example, if NODE_ENV
=development
, the config.json
might look like the following:
{
"development": {
"PORT": 3000,
"MONGODB_URI": "mongodb://localhost:27017/Reviews",
"CACHE_SERVER": "redis://localhost:6379",
"TIMEOUT": 30,
"TRIP_ADVISOR_KEY" : "XXXXXXXXXXXXXXXXX",
"LANGS" : "en,es,fr,de,cz,el",
"MONGODB_COLLECTION" : "reviews_dev",
"PAGESIZE" : "8",
"TA_URL_ROOT" : "https://api.tripadvisor.com/api/partner/2.0/location",
"LOG_DIRECTORY" : "/tmp/logs/TA/"
}
}
Multiple configuration environments are supported in a single config.json
file as follows:
{
"development": {
...
},
"qa": {
...
},
"production": {
...
}
}
In this case, you could switch between configurations by changing the value of NODE_ENV
between development
, qa
, and production
.
Exposed Endpoints
/resorts/:ids
Fetch summary information (# of reviews, overall rating, etc.) about one or more resorts.
The :ids
URL parameter can be either a single RCI Resort ID (such as 0450
for Sheraton Vistana), or can be a comma-separated list of ids such as 0450,0451,A358
.
The return value will be a JSON array, where each array element corresponds to exactly one of the input IDs. If an invalid ID is specified as part of the :ids
parameter, it will not be included in the array.
The response will be similar to the following:
[
{
"id": "0004",
"count": "5463",
"imgUrl": "https://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/4.0-32772-5.svg",
"rating": "4.0"
},
{
"id": "0450",
"count": "6457",
"imgUrl": "https://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/4.5-32772-5.svg",
"rating": "4.5"
}
]
In this case, the value of :ids
was 0004,2153,0450
. Note that 2153 is not a valid RCI ID as far as TripAdvisor is aware, so it was excluded from the response.
Two querystring parameters, lang
and subratings
may be used to alter the response.
subratings
- a boolean, by default false
. If true
, it will return a significantly larger amount of information for each resort including subrating data (cleanliness/etc.), URLs for reading additional reviews, etc.lang
indicates the TripAdvisor language code to request the response in. Currently, this only affects the data returned by the subratings
flag.
/resort/:id/reviews/languages
Fetch which languages for the specified resort have reviews already submitted.
The :id
URL parameter must be a single RCI Resort ID (such as 0450
for Sheraton Vistana). This value is passed directly to TripAdvisor. If the specified :id
is not preconfigured in TripAdvisor's mapping system, which converts RCI Resort IDs into TripAdvisor IDs, this service will return HTTP Status 502
along with a JSON Payload indicating the resort was not found, even if the RCI Resort ID is otherwise valid. That response will resemble the following:
{
"err": {
"message": "Resort 0457 not found"
}
}
The response in the happy path will have HTTP Status 200
along with a JSON array indicating the languages with reviews already submitted, such as:
[
"en",
"nl",
"de",
"it",
"pt"
]
If the resort has no submitted reviews, the array will be empty, as follows:
[]
One querystring parameter, member
, may be used to alter the response.
member
- A boolean (true
/false
) indicating whether to request languages for all submitted reviews (false
), or only for member-submitted review (true
). If not supplied, defaults to false
.
/resort/:id/reviews/:lang
Fetch review texts for the specified resort in the specified language.
URL Parameter | Significance |
---|
:id | Must be a single RCI Resort ID (such as 0450 for Sheraton Vistana). This value is passed directly to TripAdvisor. If the specified :id is not preconfigured in TripAdvisor's mapping system, which converts RCI Resort IDs into TripAdvisor IDs, this service will return HTTP Status 502 along with a JSON Payload indicating the resort was not found, even if the RCI Resort ID is otherwise valid. |
:lang | Get reviews in this language. This value must be one of the values returned by the /resort/:id/reviews/languages service call, or no reviews will be fetched. In addition to only returning reviews in the specified language, the localized_name field of the subratings element will be translated into the specified language. |
The response in the happy path will be an HTTP Status 200
along with a JSON payload resembling the following:
{
"count": 0,
"reviews": []
}
The count
field indicates the total number of matching reviews, not necessarily the number of reviews actually returned in the reviews
array. Note that for non-member reviews (when member
=false
as described below), this number will be the lesser of 5
or the total number of non-member reviews in the specified language, as per TripAdvisor's functional limitations.
The reviews
array will be an array of review objects in the format specified by TripAdvisor. As of the drafting of this README file, it resembles the following:
{
"id": "530369539",
"lang": "en",
"location_id": "115389",
"published_date": "2017-10-05T17:26:46-0400",
"rating": 4,
"helpful_votes": "0",
"rating_image_url": "https://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/s4.0-32772-5.svg",
"url": "https://www.tripadvisor.com/ShowUserReviews-g34515-d115389-r530369539-m32772-Sheraton_Vistana_Resort_Lake_Buena_Vista-Orlando_Florida.html#review530369539",
"trip_type": "Couples",
"travel_date": "2017-09",
"text": "Definitely a great choice when staying in the Lake Buena Vista area. However if you are looking for a small quaint hotel, this isn't it. This is a huge immense resort that covers acres and acres. Several pools and dining options are available but everything is extremely spread out. The room was clean and comfortable and definitely what we needed. The staff was a little uninterested when asked questions about the area. All in all a nice stay, just very large and spread out.",
"user": {
"username": "VickiFromPhilly",
"user_location": {
"name": "Philadelphia, Pennsylvania",
"id": "60795"
}
},
"title": "Great resort",
"owner_response": {
"id": "530506860",
"lang": "en",
"published_date": "2017-10-06T06:05:48-0400",
"author": "das51, Guest Relations Manager at Sheraton Vistana Resort - Lake Buena Vista, responded to this review",
"text": "We thank you for taking the time to write and share your impressions and experience at the lovely Sheraton Vistana Resort.\n\nWe are hopeful you had time to enjoy one of our sparkling pools, or restaurant/bar.\n \nThank you for selecting our resort, we hope to serve you for many years. We are sorry to learn that our Teams did not display \"alertness\" when asked about area happenings. Your valuable comments were shared with the Management Team for their awareness.\n\nWe are glad you were safe, and enjoyed our accommodation, location and amenities.\nLooking forward to host you again soon.\nBest Wishes \nSincerely\nDassie\nResort Management Team. ",
"title": "Owner Response"
},
"subratings": [
{
"rating_image_url": "https://static.tacdn.com/img2/ratings/traveler/ss4.0.gif",
"name": "rate_room",
"value": "4",
"localized_name": "Rooms"
},
{
"rating_image_url": "https://static.tacdn.com/img2/ratings/traveler/ss4.0.gif",
"name": "rate_cleanliness",
"value": "4",
"localized_name": "Cleanliness"
},
{
"rating_image_url": "https://static.tacdn.com/img2/ratings/traveler/ss3.0.gif",
"name": "rate_service",
"value": "3",
"localized_name": "Service"
}
]
}
The following querystring parameters may be used to alter the response:
Querystring Parameter | Significance |
---|
member | A boolean (true /false ) indicating whether to request languages for all submitted reviews (false ), or only for member-submitted review (true ). If not supplied, defaults to false . |
offset | The number of reviews to "skip" when fetching paginated results. If not supplied, defaults to 0 . Ignored when member =false . |
limit | The maximum number of reviews to return. If not supplied, defaults to the PAGESIZE environment variable. Ignored when member =false . |
sort | The attribute by which to sort reviews. Valid values are date and rating . If not supplied or an invalid value is supplied, defaults to date . Ignored when member =false . |
sortdir | Valid values are 1 and -1 . Defines whether to sort ascending (1 ) or descending (-1 ). Note that when sorting by date, ascending means "oldest first" and descending means "newest first". If not supplied or an invalid value is supplied, defaults to -1 . Ignored when member =false . |