Skip to content
Draft
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
12 changes: 12 additions & 0 deletions exercisefiles/node/endpoints/calculateMemoryConsumption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* GET /CalculateMemoryConsumption
* Reports heap usage in GB
*/
function handleCalculateMemoryConsumption(query, res) {
const memoryUsage = process.memoryUsage();
const memoryInGB = (memoryUsage.heapUsed / (1024 * 1024 * 1024)).toFixed(2);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(memoryInGB);
}

module.exports = handleCalculateMemoryConsumption;
21 changes: 21 additions & 0 deletions exercisefiles/node/endpoints/daysBetweenDates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* GET /DaysBetweenDates?date1=YYYY-MM-DD&date2=YYYY-MM-DD
* Computes absolute difference in days between two dates
*/
function handleDaysBetweenDates(query, res) {
const date1 = query.date1;
const date2 = query.date2;
if (date1 && date2) {
const d1 = new Date(date1);
const d2 = new Date(date2);
const diffTime = Math.abs(d2 - d1);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(String(diffDays));
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('date1 and date2 parameters are required');
}
}

module.exports = handleDaysBetweenDates;
16 changes: 16 additions & 0 deletions exercisefiles/node/endpoints/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* GET /get?key=VALUE
* Returns 'hello VALUE' if key is provided, otherwise 400 error
*/
function handleGet(query, res) {
const key = query.key;
if (key) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('hello ' + key);
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('key not passed');
}
}

module.exports = handleGet;
20 changes: 20 additions & 0 deletions exercisefiles/node/endpoints/getFullTextFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const fs = require('fs');

/**
* GET /GetFullTextFile
* Reads entire file and filters lines containing 'Fusce'
*/
function handleGetFullTextFile(query, res, dirname) {
fs.readFile(dirname + '/sample.txt', 'utf8', (err, data) => {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error reading file');
return;
}
const lines = data.split('\n').filter(line => line.includes('Fusce'));
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(lines.join('\n'));
});
}

module.exports = handleGetFullTextFile;
42 changes: 42 additions & 0 deletions exercisefiles/node/endpoints/getLineByLineFromTextFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const fs = require('fs');
const readline = require('readline');

/**
* GET /GetLineByLinefromtTextFile
* Streams file line-by-line and collects lines containing 'Fusce'
*/
function handleGetLineByLineFromTextFile(query, res, dirname) {
const readFileLineByLine = () => {
return new Promise((resolve, reject) => {
const fileStream = fs.createReadStream(dirname + '/sample.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
const matchingLines = [];
rl.on('line', (line) => {
if (line.includes('Fusce')) {
matchingLines.push(line);
}
});
rl.on('close', () => {
resolve(matchingLines);
});
rl.on('error', (err) => {
reject(err);
});
});
};

readFileLineByLine()
.then(lines => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(lines));
})
.catch(err => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error reading file');
});
}

module.exports = handleGetLineByLineFromTextFile;
10 changes: 10 additions & 0 deletions exercisefiles/node/endpoints/health.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* GET /health or /healthz
* Simple liveness probe; returns 'ok' when the server is running
*/
function handleHealth(query, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
}

module.exports = handleHealth;
40 changes: 40 additions & 0 deletions exercisefiles/node/endpoints/moviesByDirector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const axios = require('axios');

/**
* GET /MoviesByDirector?director=NAME
* Uses OMDb API to search and filter movies by director
*/
function handleMoviesByDirector(query, res, omdbApiKey) {
const director = query.director;
if (director) {
// Search for movies, then filter by director
axios.get(`http://www.omdbapi.com/?apikey=${omdbApiKey}&s=${encodeURIComponent(director)}&type=movie`)
.then(async response => {
if (response.data.Response === 'True') {
// Get detailed info for each movie to verify director
const moviePromises = response.data.Search.map(movie =>
axios.get(`http://www.omdbapi.com/?apikey=${omdbApiKey}&i=${movie.imdbID}`)
);
const movieDetails = await Promise.all(moviePromises);
const directorMovies = movieDetails
.map(m => m.data)
.filter(m => m.Director && m.Director.toLowerCase().includes(director.toLowerCase()));

res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(directorMovies));
} else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'No movies found' }));
}
})
.catch(error => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error fetching movies');
});
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('director parameter is required');
}
}

module.exports = handleMoviesByDirector;
22 changes: 22 additions & 0 deletions exercisefiles/node/endpoints/parseUrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* GET /ParseUrl?someurl=ENCODED_URL
* Parses provided URL and returns host component
*/
function handleParseUrl(query, res) {
const someurl = query.someurl;
if (someurl) {
try {
const parsedSomeUrl = new URL(someurl);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(parsedSomeUrl.host);
} catch (error) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('invalid url');
}
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('someurl parameter is required');
}
}

module.exports = handleParseUrl;
61 changes: 61 additions & 0 deletions exercisefiles/node/endpoints/randomEuropeanCountry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Static reference data for /RandomEuropeanCountry
const europeanCountries = [
{ country: 'Albania', isoCode: 'AL' },
{ country: 'Andorra', isoCode: 'AD' },
{ country: 'Austria', isoCode: 'AT' },
{ country: 'Belarus', isoCode: 'BY' },
{ country: 'Belgium', isoCode: 'BE' },
{ country: 'Bosnia and Herzegovina', isoCode: 'BA' },
{ country: 'Bulgaria', isoCode: 'BG' },
{ country: 'Croatia', isoCode: 'HR' },
{ country: 'Cyprus', isoCode: 'CY' },
{ country: 'Czech Republic', isoCode: 'CZ' },
{ country: 'Denmark', isoCode: 'DK' },
{ country: 'Estonia', isoCode: 'EE' },
{ country: 'Finland', isoCode: 'FI' },
{ country: 'France', isoCode: 'FR' },
{ country: 'Germany', isoCode: 'DE' },
{ country: 'Greece', isoCode: 'GR' },
{ country: 'Hungary', isoCode: 'HU' },
{ country: 'Iceland', isoCode: 'IS' },
{ country: 'Ireland', isoCode: 'IE' },
{ country: 'Italy', isoCode: 'IT' },
{ country: 'Latvia', isoCode: 'LV' },
{ country: 'Liechtenstein', isoCode: 'LI' },
{ country: 'Lithuania', isoCode: 'LT' },
{ country: 'Luxembourg', isoCode: 'LU' },
{ country: 'Malta', isoCode: 'MT' },
{ country: 'Moldova', isoCode: 'MD' },
{ country: 'Monaco', isoCode: 'MC' },
{ country: 'Montenegro', isoCode: 'ME' },
{ country: 'Netherlands', isoCode: 'NL' },
{ country: 'North Macedonia', isoCode: 'MK' },
{ country: 'Norway', isoCode: 'NO' },
{ country: 'Poland', isoCode: 'PL' },
{ country: 'Portugal', isoCode: 'PT' },
{ country: 'Romania', isoCode: 'RO' },
{ country: 'Russia', isoCode: 'RU' },
{ country: 'San Marino', isoCode: 'SM' },
{ country: 'Serbia', isoCode: 'RS' },
{ country: 'Slovakia', isoCode: 'SK' },
{ country: 'Slovenia', isoCode: 'SI' },
{ country: 'Spain', isoCode: 'ES' },
{ country: 'Sweden', isoCode: 'SE' },
{ country: 'Switzerland', isoCode: 'CH' },
{ country: 'Ukraine', isoCode: 'UA' },
{ country: 'United Kingdom', isoCode: 'GB' },
{ country: 'Vatican City', isoCode: 'VA' }
];

/**
* GET /RandomEuropeanCountry
* Returns a random country from static list
*/
function handleRandomEuropeanCountry(query, res) {
const randomIndex = Math.floor(Math.random() * europeanCountries.length);
const randomCountry = europeanCountries[randomIndex];
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(randomCountry));
}

module.exports = handleRandomEuropeanCountry;
32 changes: 32 additions & 0 deletions exercisefiles/node/endpoints/returnColorCode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const fs = require('fs');

/**
* GET /ReturnColorCode?color=NAME
* Looks up color hex code from colors.json
*/
function handleReturnColorCode(query, res, dirname) {
const color = query.color;
if (color) {
fs.readFile(dirname + '/colors.json', 'utf8', (err, data) => {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error reading colors file');
return;
}
const colors = JSON.parse(data);
const foundColor = colors.find(c => c.color.toLowerCase() === color.toLowerCase());
if (foundColor) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(foundColor.code.hex);
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('color not found');
}
});
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('color parameter is required');
}
}

module.exports = handleReturnColorCode;
23 changes: 23 additions & 0 deletions exercisefiles/node/endpoints/tellMeAJoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const axios = require('axios');

/**
* GET /TellMeAJoke
* Fetches a random joke from public API
*/
function handleTellMeAJoke(query, res) {
axios.get('https://official-joke-api.appspot.com/random_joke')
.then(response => {
const joke = response.data;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
setup: joke.setup,
punchline: joke.punchline
}));
})
.catch(error => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Error fetching joke');
});
}

module.exports = handleTellMeAJoke;
23 changes: 23 additions & 0 deletions exercisefiles/node/endpoints/validatePhoneNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* GET /Validatephonenumber?phoneNumber=+34#########
* Validates Spanish phone numbers (+34 followed by 9 digits)
*/
function handleValidatePhoneNumber(query, res) {
const phoneNumber = query.phoneNumber;
if (phoneNumber) {
// Spanish phone number format: +34 followed by 9 digits
const spanishPhoneRegex = /^\+34[0-9]{9}$/;
if (spanishPhoneRegex.test(phoneNumber)) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('valid');
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('invalid');
}
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('phoneNumber parameter is required');
}
}

module.exports = handleValidatePhoneNumber;
32 changes: 32 additions & 0 deletions exercisefiles/node/endpoints/validateSpanishDNI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* GET /ValidateSpanishDNI?dni=########X
* Validates Spanish DNI checksum letter
*/
function handleValidateSpanishDNI(query, res) {
const dni = query.dni;
if (dni) {
const dniRegex = /^(\d{8})([A-Z])$/i;
const letters = 'TRWAGMYFPDXBNJZSQVHLCKE';
const match = dni.match(dniRegex);
if (match) {
const number = parseInt(match[1], 10);
const letter = match[2].toUpperCase();
const correctLetter = letters[number % 23];
if (letter === correctLetter) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('valid');
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('invalid');
}
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('invalid');
}
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('dni parameter is required');
}
}

module.exports = handleValidateSpanishDNI;
Loading