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

Add service with get, post, delete requests #5

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
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
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,55 @@
# node-mentoring-introduction
Task 1
Task 5

https://d17btkcdsmqrmh.cloudfront.net/node-gmp/docs/network/task

We have been asked to develop a REST API for users and their hobbies. The API should have the following functionality:

- Create/delete user.
- Partially update user properties.
- Retrieve user by id, list of users. Returns only user data, no hobbies are returned.
- Add/delete hobby for a specific user.
- Get a list of user hobbies.

Data can be stored in memory as an array. Check the structure of User below:

![2023-09-29_21h02_22](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/299626bb-6d98-431f-af68-13c2acfd7459)


- No frameworks are used. Server is created using http module.
- API is designed based on REST API principles. Constraints are not violated.
- The functionality mentioned above is implemented. Proper status codes are used for responses (not only 200, but also e.g 201, 404). Input validation and authentication can be skipped.
- Note: Try to think of modular structure for the task. Please do not have all the implementation in one file.

Additional (optional tasks):
- Caching headers are added (hint: hobbies do not change so often).
- Hypermedia links (HATEOAS) are included (for each user to retrieve a list of hobbies).

Some results

![2023-10-02_22h13_46](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/ed8fc1c6-3d02-40ea-8a77-785bad6810eb)

![2023-10-02_22h14_52](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/f6da5e4b-2959-4842-ab9f-ea330a4b2ccf)

![image](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/93449270-ee27-4240-9bcb-a445a78f75e7)

![2023-10-02_22h16_36](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/e06107a0-ef9f-4f0a-aa70-e0c62239b0a3)

![2023-10-02_22h17_37](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/4e38d9ee-40a7-4666-b08b-781d289ac0b4)

![2023-10-02_22h22_12](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/b60d27dd-51d2-48ed-a257-5c18b4b1cc8a)

![image](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/77c2f0d6-e214-4f97-a2f4-84c12b0a622d)

![image](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/7feecf9f-c953-42e5-a22f-fbc2db1fdc9c)

![image](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/562c1e4a-090a-4a21-8c93-a85b28a117af)

![image](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/15371933-5a6c-4645-981b-cb43810297fb)

![2023-10-02_22h33_47](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/75d7d896-e499-4bb5-aad4-3eb97963bd3e)





39 changes: 39 additions & 0 deletions client/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { request } from 'http';
import { createInterface } from "node:readline"


const readline = createInterface({
input: process.stdin,
output: process.stdout
});

readline.question('Enter id (number)', id => {
readline.close();

const options = {
hostname: 'http://localhost:3000',
port: 3000,
path: `/users/${id}`,
method: 'DELETE',
};

const req = request(options, (res) => {
console.log(`Status Code: ${res.statusCode}`);
console.log('Response Headers:', res.headers);

res.on('data', (chunk) => {
console.log(`Received Data: ${chunk}`);
});

res.on('end', () => {
console.log('Request Complete');
});
});

console.log('Starting DELETE request');
req.on('error', (error) => {
console.error(`Request Error: ${error.message}`);
});
req.end();

});
36 changes: 36 additions & 0 deletions client/patch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { request } from 'http';
import { getRandomString } from '../src/utils/utils.js';

const options = {
hostname: 'http://localhost:3000/',
port: 3000,
path: '/users/3',
method: 'PATCH',
};
const randomIntString = getRandomString(10,100);

const newValues = {
name: "Changed Name"+randomIntString,
}

const req = request(options, (res) => {
console.log(`Status Code: ${res.statusCode}`);
console.log('Response Headers:', res.headers);

res.on('data', (chunk) => {
console.log(`Received Data: ${chunk}`);
});

res.on('end', () => {
console.log('Request Complete');
});
});

req.on('error', (error) => {
console.error(`Request Error: ${error.message}`);
});

req.write(JSON.stringify(newValues));
req.end();

console.log('Starting PATCH request');
38 changes: 38 additions & 0 deletions client/post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { request } from 'http';
import { getRandomString } from '../src/utils/utils.js';

const options = {
hostname: 'http://localhost:3000/',
port: 3000,
path: '/users',
method: 'POST',
};
const randomIntString = getRandomString(10,100);

const newUser = {
name: "New User" + randomIntString,
email: randomIntString + '@google.com',
hobbies: ['series', 'sport', randomIntString],
}

const req = request(options, (res) => {
console.log(`Status Code: ${res.statusCode}`);
console.log('Response Headers:', res.headers);

res.on('data', (chunk) => {
console.log(`Received Data: ${chunk}`);
});

res.on('end', () => {
console.log('Request Complete');
});
});

req.on('error', (error) => {
console.error(`Request Error: ${error.message}`);
});

req.write(JSON.stringify(newUser));
req.end();

console.log('Starting POST request');
52 changes: 52 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { createServer } from "http";
import { createNewUser, createUserHobby, deleteUser, deleteUserHobby, getUserById, getUserHobbies, getUsers, updateUser } from "./src/controller/controller.js";
import { isHobby, isUserById, isUserHobbies, isUserHobby, stripTrailingSlash } from "./src/utils/utils.js";
import { sendResp } from "./src/utils/resp_utils.js";
import { getHobby } from "./src/controller/hobbies-controller.js";

const server = createServer(async (req, res) => {
try {
const url = stripTrailingSlash(req.url);
// console.log(url);
// console.log(req.method);

if (req.method === 'GET' && url === '/users') {
await getUsers(res);
}
else if (req.method === 'GET' && isUserById(url)) {
await getUserById(req, res);
}
else if (req.method === 'POST' && url === '/users') {
await createNewUser(req, res);
}
else if (req.method === 'DELETE' && isUserById(url)) {
await deleteUser(req, res);
}
else if (req.method === 'PATCH' && isUserById(url)) {
await updateUser(req, res);
}
else if (req.method === 'GET' && isUserHobbies(url)) {
await getUserHobbies(req, res);
}
else if (req.method === 'POST' && isUserHobbies(url)) {
await createUserHobby(req, res);
}
else if (req.method === 'DELETE' && isUserHobby(url)) {
await deleteUserHobby(req, res);
}
else if (req.method === 'GET' && isHobby(url)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

супер, что добавила проверку на входящие параметры

await getHobby(req, res);
}
else {
throw new Error('No such resource');
}
}
catch ({ message }) {
console.log('Error', message);
sendResp(res, message, 404);
}
})

server.listen(3000, () => {
console.log('Server is running on port 3000');
})
Loading