Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed English (UK) language code to fix Issue #122 #123

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions app.js → modules/app.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
const { JSDOM } = require('jsdom'),
express = require('express'),
rateLimit = require("express-rate-limit"),
serverless = require('serverless-http'),
router = express.Router(),
PORT = process.env.port || 3000,

utils = require('./modules/utils.js'),
errors = require('./modules/errors.js'),
dictionary = require('./modules/dictionary.js'),
utils = require('./utils.js'),
errors = require('./errors.js'),
dictionary = require('./dictionary.js'),

// HTML Parser
{ DOMParser } = new JSDOM().window,
parser = new DOMParser(),

app = express(),


keyGenerator = function (req, res) {
return req.headers['publicIp'] || req.headers['ip'] || req.headers['client-ip'];
};
limiter = rateLimit({
windowMs: 5 * 60 * 1000, // 5 minutes
max: 450 // limit each IP to 450 requests per windowMs
max: 450, // limit each IP to 450 requests per windowMs
keyGenerator: keyGenerator
}),

// Versions
Expand All @@ -30,11 +39,12 @@ const { JSDOM } = require('jsdom'),
// Headers
HEADER_CONTENT_TYPE = 'Content-Type',
HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin';
HEADER_X_POWERED_BY = 'X-Powered-By';

// GLOBALS
global._ = require('lodash');

function cleanText (text) {
function cleanText(text) {
if (!text) { return text; }

return parser
Expand All @@ -43,13 +53,13 @@ function cleanText (text) {
}


function handleError (error = {}) {
function handleError(error = {}) {
// Using duck typing to know if we explicitly threw this error
// If not then wrapping original error into UnexpectedError
if (!error.requestType) { error = new errors.UnexpectedError({ original_error: error }); }

const { requestType, title, message, resolution } = error;
status = REQUEST_TYPE_STATUS_CODE[requestType],
status = REQUEST_TYPE_STATUS_CODE[requestType],
body = JSON.stringify({
title,
message,
Expand All @@ -58,6 +68,7 @@ function handleError (error = {}) {

this.set(HEADER_CONTENT_TYPE, 'application/json');
this.set(HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, '*');
this.set(HEADER_X_POWERED_BY, 'Efforts, Sweat, Dedication, Desire and Open Source');

return this.status(status).send(body);
};
Expand All @@ -66,7 +77,15 @@ app.set('trust proxy', true);

app.use(limiter);

app.get('/api/:version/entries/:language/:word', async (req, res) => {
app.use('/', router);

router.get('/api', (req, res) => {
res.set(HEADER_X_POWERED_BY, "Efforts, Sweat, Dedication and Desire");
res.json({ message: "Hello from Dictionary API" });
});

router.get('/api/:version/entries/:language/:word', async (req, res) => {
console.log('Reached in api route')
let { word, language, version } = req.params,
include = _.reduce(_.get(req.query, 'include', '').split(','), (accumulator, current) => {
accumulator[current] = true;
Expand All @@ -77,7 +96,8 @@ app.get('/api/:version/entries/:language/:word', async (req, res) => {
word = decodeURIComponent(word);

if (!word || !language || !version) {
return handleError.call(res, new errors.NoDefinitionsFound());
console.log(`Word: ${word} | Language: ${language} | Version: ${version} is blank or undefined`);
return handleError.call(res, new errors.NoDefinitionsFound());
}

// @todo: Find better error.
Expand All @@ -104,6 +124,7 @@ app.get('/api/:version/entries/:language/:word', async (req, res) => {
definitions = dictionary.transformV2toV1(definitions);
}

console.log(`definitions response: ${JSON.stringify(definitions)}`);
body = JSON.stringify(definitions, (key, value) => {
if (typeof value === 'object') { return value; }

Expand All @@ -112,11 +133,15 @@ app.get('/api/:version/entries/:language/:word', async (req, res) => {

res.set(HEADER_CONTENT_TYPE, 'application/json');
res.set(HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, '*');
res.set(HEADER_X_POWERED_BY, 'Efforts, Sweat, Dedication, Desire and Open Source');

return res.status(status).send(body);
} catch (error) {
console.log(`Error finding definition for ${word}; Error message: ${error}`);
return handleError.call(res, error);
}
});

app.listen(3000, () => console.log('Server running on port 3000'));
// app.listen(3000, () => console.log('Server running on port 3000'));

module.exports.handler = serverless(app);
4 changes: 2 additions & 2 deletions modules/dictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ async function queryInternet (word, language) {
url.searchParams.set('async', `term:${encodeURIComponent(word)},corpus:${language},hhdr:true,hwdgt:true,wfp:true,ttl:,tsl:,ptl:`);

url = url.toString();

console.log(`Generated URL: ${url}`);
let response = await fetch(url, {
agent: httpsAgent,
headers: new fetch.Headers({
Expand All @@ -152,7 +152,7 @@ async function queryInternet (word, language) {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
})
});

console.log(`Response: ${JSON.stringify(response)}; Response Status: ${response.status}`);
if (response.status === 404) { throw new errors.NoDefinitionsFound({ reason: 'Website returned 404.'}); }

if (response.status === 429) { throw new errors.RateLimitError(); }
Expand Down
4 changes: 2 additions & 2 deletions modules/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const // Versions
SUPPORTED_LANGUAGES = new Set([
'hi', // Hindi
'en', // English (US)
'en-uk', // English (UK)
'en_GB', // English (UK)
'es', // Spanish
'fr', // French
'ja', // Japanese
Expand Down Expand Up @@ -43,4 +43,4 @@ module.exports = {
isVersionSupported (version) {
return SUPPORTED_VERSIONS.has(version);
}
}
}
15 changes: 15 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[build]
functions="modules"

[[redirects]]
from="/*"
to="/.netlify/functions/app/:splat"
status=200

[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
X-Content-Type-Options = "nosniff"
Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
Loading