├── ch2
├── part5
│ ├── db
│ │ ├── dumps
│ │ │ └── .gitkeep
│ │ ├── links.dev.json
│ │ └── links.prod.json
│ ├── README.md
│ ├── controllers
│ │ ├── ping.js
│ │ ├── addAlias.js
│ │ └── resolveAlias.js
│ ├── config
│ │ └── index.js
│ ├── middlewares
│ │ ├── notFound.js
│ │ ├── errorHandler.js
│ │ └── accessLogs.js
│ ├── utils
│ │ ├── getDatabaseFilePath.js
│ │ ├── dumpDatabase.js
│ │ └── compressFile.js
│ ├── modules
│ │ └── error.js
│ ├── services
│ │ └── links.js
│ └── server.js
├── part6
│ ├── db
│ │ ├── dumps
│ │ │ └── .gitkeep
│ │ ├── links.dev.json
│ │ └── links.prod.json
│ ├── controllers
│ │ ├── ping.js
│ │ ├── addAlias.js
│ │ └── resolveAlias.js
│ ├── README.md
│ ├── config
│ │ └── index.js
│ ├── middlewares
│ │ ├── notFound.js
│ │ ├── errorHandler.js
│ │ └── accessLogs.js
│ ├── utils
│ │ ├── getDatabaseFilePath.js
│ │ ├── dumpDatabase.js
│ │ ├── compressFile.js
│ │ └── monitorProcess.js
│ ├── modules
│ │ └── error.js
│ ├── services
│ │ └── links.js
│ └── server.js
├── part7
│ ├── db
│ │ ├── dumps
│ │ │ └── .gitkeep
│ │ ├── links.dev.json
│ │ └── links.prod.json
│ ├── README.md
│ ├── controllers
│ │ ├── ping.js
│ │ ├── addAlias.js
│ │ └── resolveAlias.js
│ ├── config
│ │ └── index.js
│ ├── middlewares
│ │ ├── disablePoweredBy.js
│ │ ├── notFound.js
│ │ ├── errorHandler.js
│ │ ├── accessLogs.js
│ │ └── security.js
│ ├── utils
│ │ ├── getDatabaseFilePath.js
│ │ ├── dumpDatabase.js
│ │ ├── compressFile.js
│ │ └── monitorProcess.js
│ ├── modules
│ │ └── error.js
│ ├── services
│ │ └── links.js
│ └── server.js
├── part8
│ ├── server
│ │ ├── db
│ │ │ ├── dumps
│ │ │ │ └── .gitkeep
│ │ │ ├── links.dev.json
│ │ │ └── links.prod.json
│ │ ├── README.md
│ │ ├── controllers
│ │ │ ├── ping.js
│ │ │ ├── addAlias.js
│ │ │ └── resolveAlias.js
│ │ ├── config
│ │ │ └── index.js
│ │ ├── middlewares
│ │ │ ├── disablePoweredBy.js
│ │ │ ├── notFound.js
│ │ │ ├── errorHandler.js
│ │ │ ├── accessLogs.js
│ │ │ └── security.js
│ │ ├── utils
│ │ │ ├── getDatabaseFilePath.js
│ │ │ ├── dumpDatabase.js
│ │ │ ├── compressFile.js
│ │ │ └── monitorProcess.js
│ │ ├── modules
│ │ │ └── error.js
│ │ ├── services
│ │ │ └── links.js
│ │ └── server.js
│ └── client
│ │ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── App.tsx
│ │ ├── tsconfig.node.json
│ │ ├── vite.config.ts
│ │ ├── dist
│ │ ├── assets
│ │ │ └── index.99fc237d.css
│ │ └── index.html
│ │ ├── index.html
│ │ ├── .gitignore
│ │ ├── tsconfig.json
│ │ └── package.json
├── part9
│ ├── server
│ │ ├── db
│ │ │ ├── dumps
│ │ │ │ └── .gitkeep
│ │ │ ├── links.dev.json
│ │ │ └── links.prod.json
│ │ ├── README.md
│ │ ├── controllers
│ │ │ ├── ping.js
│ │ │ ├── addAlias.js
│ │ │ └── resolveAlias.js
│ │ ├── config
│ │ │ └── index.js
│ │ ├── middlewares
│ │ │ ├── disablePoweredBy.js
│ │ │ ├── notFound.js
│ │ │ ├── errorHandler.js
│ │ │ ├── accessLogs.js
│ │ │ └── security.js
│ │ ├── utils
│ │ │ ├── getDatabaseFilePath.js
│ │ │ ├── dumpDatabase.js
│ │ │ ├── compressFile.js
│ │ │ └── monitorProcess.js
│ │ ├── modules
│ │ │ ├── error.js
│ │ │ └── wsClients.js
│ │ ├── ws.js
│ │ ├── services
│ │ │ └── links.js
│ │ └── server.js
│ └── client
│ │ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── index.css
│ │ ├── main.tsx
│ │ ├── Online.tsx
│ │ └── Home.tsx
│ │ ├── tsconfig.node.json
│ │ ├── vite.config.ts
│ │ ├── dist
│ │ ├── assets
│ │ │ └── index.99fc237d.css
│ │ └── index.html
│ │ ├── index.html
│ │ ├── .gitignore
│ │ ├── tsconfig.json
│ │ └── package.json
├── part1
│ ├── README.md
│ ├── controllers
│ │ ├── ping.js
│ │ └── resolveAlias.js
│ ├── config
│ │ └── index.js
│ ├── db
│ │ ├── links.dev.json
│ │ └── links.prod.json
│ ├── middlewares
│ │ ├── urlLogger.js
│ │ └── notFound.js
│ ├── services
│ │ └── links.js
│ └── server.js
├── part4
│ ├── README.md
│ ├── controllers
│ │ ├── ping.js
│ │ ├── addAlias.js
│ │ └── resolveAlias.js
│ ├── config
│ │ └── index.js
│ ├── middlewares
│ │ ├── notFound.js
│ │ ├── errorHandler.js
│ │ └── accessLogs.js
│ ├── db
│ │ ├── links.dev.json
│ │ └── links.prod.json
│ ├── modules
│ │ └── error.js
│ ├── server.js
│ └── services
│ │ └── links.js
├── part2
│ ├── controllers
│ │ ├── ping.js
│ │ ├── addAlias.js
│ │ └── resolveAlias.js
│ ├── README.md
│ ├── config
│ │ └── index.js
│ ├── middlewares
│ │ ├── urlLogger.js
│ │ └── notFound.js
│ ├── db
│ │ ├── links.dev.json
│ │ └── links.prod.json
│ ├── server.js
│ └── services
│ │ └── links.js
└── part3
│ ├── controllers
│ ├── ping.js
│ ├── addAlias.js
│ └── resolveAlias.js
│ ├── README.md
│ ├── config
│ └── index.js
│ ├── middlewares
│ ├── urlLogger.js
│ ├── notFound.js
│ └── errorHandler.js
│ ├── db
│ ├── links.dev.json
│ └── links.prod.json
│ ├── modules
│ └── error.js
│ ├── server.js
│ └── services
│ └── links.js
├── ch1
├── part1
│ ├── README.md
│ └── script.js
├── part3
│ ├── README.md
│ └── script.js
├── part4
│ ├── README.md
│ ├── links.dev.txt
│ ├── script.js
│ └── links.prod.txt
├── part5
│ ├── README.md
│ ├── links.dev.txt
│ ├── script.js
│ └── links.prod.txt
└── part2
│ ├── README.md
│ └── script.js
├── .gitignore
└── package.json
/ch2/part5/db/dumps/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ch2/part6/db/dumps/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ch2/part7/db/dumps/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ch2/part8/server/db/dumps/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ch2/part9/server/db/dumps/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ch1/part1/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | node script.js
3 | ```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | *.logs
4 | **/db/dumps/*.gz
5 | .DS_Store
--------------------------------------------------------------------------------
/ch2/part8/client/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/ch2/part9/client/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/ch2/part1/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | node server.js
3 |
4 | NODE_ENV=production node server.js
5 | ```
--------------------------------------------------------------------------------
/ch1/part3/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | node script.js map
3 |
4 | LINKS_TYPE=prod node script.js map
5 | ```
--------------------------------------------------------------------------------
/ch1/part4/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | node script.js map
3 |
4 | LINKS_TYPE=prod node script.js map
5 | ```
--------------------------------------------------------------------------------
/ch1/part5/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | node script.js map
3 |
4 | NODE_ENV=production node script.js map
5 | ```
--------------------------------------------------------------------------------
/ch2/part7/README.md:
--------------------------------------------------------------------------------
1 | Security
2 |
3 | ```
4 | node server
5 |
6 | NODE_ENV=production node server
7 | ```
--------------------------------------------------------------------------------
/ch2/part8/server/README.md:
--------------------------------------------------------------------------------
1 | Interface
2 |
3 | ```
4 | node server
5 |
6 | NODE_ENV=production node server
7 | ```
--------------------------------------------------------------------------------
/ch2/part9/server/README.md:
--------------------------------------------------------------------------------
1 | Interface
2 |
3 | ```
4 | node server
5 |
6 | NODE_ENV=production node server
7 | ```
--------------------------------------------------------------------------------
/ch1/part4/links.dev.txt:
--------------------------------------------------------------------------------
1 | music https://music.yandex.ru
2 | map https://yandex.ru/maps
3 | tr https://translate.yandex.ru
--------------------------------------------------------------------------------
/ch1/part5/links.dev.txt:
--------------------------------------------------------------------------------
1 | music https://music.yandex.ru
2 | map https://yandex.ru/maps
3 | tr https://translate.yandex.ru
--------------------------------------------------------------------------------
/ch2/part4/README.md:
--------------------------------------------------------------------------------
1 | Добавить логирование
2 |
3 | ```
4 | node server
5 |
6 | NODE_ENV=production node server
7 | ```
--------------------------------------------------------------------------------
/ch2/part5/README.md:
--------------------------------------------------------------------------------
1 | Добавить логирование
2 |
3 | ```
4 | node server
5 |
6 | NODE_ENV=production node server
7 | ```
--------------------------------------------------------------------------------
/ch1/part2/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | node script.js
3 |
4 | LINKS_TYPE=dev node script.js
5 |
6 | LINKS_TYPE=prod node script.js
7 | ```
--------------------------------------------------------------------------------
/ch2/part1/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part2/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part3/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part4/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part5/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part6/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part7/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part2/README.md:
--------------------------------------------------------------------------------
1 | Добавить POST запрос на добавление нового URL в БД
2 |
3 | ```
4 | node server.js
5 |
6 | NODE_ENV=production node server.js
7 | ```
--------------------------------------------------------------------------------
/ch2/part3/README.md:
--------------------------------------------------------------------------------
1 | Добавить POST запрос на добавление нового URL в БД
2 |
3 | ```
4 | node server.js
5 |
6 | NODE_ENV=production node server.js
7 | ```
--------------------------------------------------------------------------------
/ch2/part6/README.md:
--------------------------------------------------------------------------------
1 | Мониторинг нагрузки на процессор и потребляемой памяти
2 |
3 | ```
4 | node server
5 |
6 | NODE_ENV=production node server
7 | ```
--------------------------------------------------------------------------------
/ch2/part8/server/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part9/server/controllers/ping.js:
--------------------------------------------------------------------------------
1 | function ping(request, response) {
2 | return response.send('pong');
3 | }
4 |
5 | module.exports = { ping };
--------------------------------------------------------------------------------
/ch2/part1/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part1/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru"
5 | }
6 |
--------------------------------------------------------------------------------
/ch2/part2/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part3/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part4/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part5/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part6/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part7/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part8/server/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part9/server/config/index.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const dbPath = path.resolve(__dirname, '../db');
4 |
5 | module.exports = {
6 | dbPath,
7 | };
--------------------------------------------------------------------------------
/ch2/part1/middlewares/urlLogger.js:
--------------------------------------------------------------------------------
1 | function urlLogger(request, response, next) {
2 | console.log(request.originalUrl);
3 |
4 | next();
5 | }
6 |
7 | module.exports = { urlLogger };
8 |
--------------------------------------------------------------------------------
/ch2/part2/middlewares/urlLogger.js:
--------------------------------------------------------------------------------
1 | function urlLogger(request, response, next) {
2 | console.log(request.originalUrl);
3 |
4 | next();
5 | }
6 |
7 | module.exports = { urlLogger };
8 |
--------------------------------------------------------------------------------
/ch2/part3/middlewares/urlLogger.js:
--------------------------------------------------------------------------------
1 | function urlLogger(request, response, next) {
2 | console.log(request.originalUrl);
3 |
4 | next();
5 | }
6 |
7 | module.exports = { urlLogger };
8 |
--------------------------------------------------------------------------------
/ch2/part7/middlewares/disablePoweredBy.js:
--------------------------------------------------------------------------------
1 | function disablePoweredBy(request, response, next) {
2 | response.removeHeader("X-Powered-By");
3 |
4 | next();
5 | };
6 |
7 | module.exports = { disablePoweredBy };
--------------------------------------------------------------------------------
/ch2/part2/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat"
6 | }
--------------------------------------------------------------------------------
/ch2/part3/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat"
6 | }
--------------------------------------------------------------------------------
/ch2/part1/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part2/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part3/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part4/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part5/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part6/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part7/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part8/server/middlewares/disablePoweredBy.js:
--------------------------------------------------------------------------------
1 | function disablePoweredBy(request, response, next) {
2 | response.removeHeader("X-Powered-By");
3 |
4 | next();
5 | };
6 |
7 | module.exports = { disablePoweredBy };
--------------------------------------------------------------------------------
/ch2/part9/server/middlewares/disablePoweredBy.js:
--------------------------------------------------------------------------------
1 | function disablePoweredBy(request, response, next) {
2 | response.removeHeader("X-Powered-By");
3 |
4 | next();
5 | };
6 |
7 | module.exports = { disablePoweredBy };
--------------------------------------------------------------------------------
/ch2/part8/server/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part9/server/middlewares/notFound.js:
--------------------------------------------------------------------------------
1 | async function notFound(request, response) {
2 | response.status(404);
3 |
4 | return response.send({ messageId: "page-not-found" });
5 | }
6 |
7 | module.exports = { notFound };
8 |
--------------------------------------------------------------------------------
/ch2/part8/client/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/ch2/part9/client/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/ch2/part8/client/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | server: {
8 | port: 3001
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/ch2/part9/client/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | server: {
8 | port: 3001
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/ch2/part3/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part4/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part5/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part6/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part7/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part8/server/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part9/server/middlewares/errorHandler.js:
--------------------------------------------------------------------------------
1 | async function errorHandler(error, request, response, next) {
2 | console.log(error);
3 |
4 | response.status(error.status || 500).send({
5 | status: "error",
6 | message: error.message,
7 | });
8 | }
9 |
10 | module.exports = { errorHandler };
11 |
--------------------------------------------------------------------------------
/ch2/part8/client/dist/assets/index.99fc237d.css:
--------------------------------------------------------------------------------
1 | :root{font-family:Inter,Avenir,Helvetica,Arial,sans-serif;font-size:16px;line-height:24px;font-weight:400;color-scheme:light;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}
2 |
--------------------------------------------------------------------------------
/ch2/part9/client/dist/assets/index.99fc237d.css:
--------------------------------------------------------------------------------
1 | :root{font-family:Inter,Avenir,Helvetica,Arial,sans-serif;font-size:16px;line-height:24px;font-weight:400;color-scheme:light;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}
2 |
--------------------------------------------------------------------------------
/ch2/part2/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response) {
4 | const { alias, link } = request.body;
5 |
6 | await linksService.addAlias(alias, link);
7 |
8 | return response.send({ status: 'success' });
9 | }
10 |
11 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part8/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Shortener
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ch2/part9/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Shortener
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ch2/part8/client/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist-ssr
12 | *.local
13 |
14 | # Editor directories and files
15 | .vscode/*
16 | !.vscode/extensions.json
17 | .idea
18 | .DS_Store
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/ch2/part9/client/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist-ssr
12 | *.local
13 |
14 | # Editor directories and files
15 | .vscode/*
16 | !.vscode/extensions.json
17 | .idea
18 | .DS_Store
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/ch2/part8/client/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light;
8 |
9 | font-synthesis: none;
10 | text-rendering: optimizeLegibility;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | -webkit-text-size-adjust: 100%;
14 | }
15 |
--------------------------------------------------------------------------------
/ch2/part9/client/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light;
8 |
9 | font-synthesis: none;
10 | text-rendering: optimizeLegibility;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | -webkit-text-size-adjust: 100%;
14 | }
15 |
--------------------------------------------------------------------------------
/ch2/part8/client/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import { ChakraProvider } from '@chakra-ui/react'
4 | import App from './App'
5 | import './index.css'
6 |
7 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
8 |
9 |
10 |
11 |
12 |
13 | )
14 |
--------------------------------------------------------------------------------
/ch2/part3/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part4/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part5/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part6/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part7/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part8/server/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part9/server/controllers/addAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function addAlias(request, response, next) {
4 | try {
5 | const { alias, link } = request.body;
6 |
7 | await linksService.addAlias(alias, link);
8 |
9 | return response.send({ status: 'success' });
10 | } catch (err) {
11 | next(err);
12 | }
13 | }
14 |
15 | module.exports = { addAlias };
--------------------------------------------------------------------------------
/ch2/part4/middlewares/accessLogs.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const morgan = require("morgan");
4 |
5 | function accessLogs(toFile = false) {
6 | return morgan(":method :url - :status :response-time ms", {
7 | stream: toFile
8 | ? fs.createWriteStream(path.resolve(__dirname, "../access.logs"), { flags: 'a' })
9 | : undefined,
10 | });
11 | }
12 |
13 | module.exports = { accessLogs };
14 |
--------------------------------------------------------------------------------
/ch2/part5/middlewares/accessLogs.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const morgan = require("morgan");
4 |
5 | function accessLogs(toFile = false) {
6 | return morgan(":method :url - :status :response-time ms", {
7 | stream: toFile
8 | ? fs.createWriteStream(path.resolve(__dirname, "../access.logs"), { flags: 'a' })
9 | : undefined,
10 | });
11 | }
12 |
13 | module.exports = { accessLogs };
14 |
--------------------------------------------------------------------------------
/ch2/part6/middlewares/accessLogs.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const morgan = require("morgan");
4 |
5 | function accessLogs(toFile = false) {
6 | return morgan(":method :url - :status :response-time ms", {
7 | stream: toFile
8 | ? fs.createWriteStream(path.resolve(__dirname, "../access.log"), { flags: 'a' })
9 | : undefined,
10 | });
11 | }
12 |
13 | module.exports = { accessLogs };
14 |
--------------------------------------------------------------------------------
/ch2/part7/middlewares/accessLogs.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const morgan = require("morgan");
4 |
5 | function accessLogs(toFile = false) {
6 | return morgan(":method :url - :status :response-time ms", {
7 | stream: toFile
8 | ? fs.createWriteStream(path.resolve(__dirname, "../access.log"), { flags: 'a' })
9 | : undefined,
10 | });
11 | }
12 |
13 | module.exports = { accessLogs };
14 |
--------------------------------------------------------------------------------
/ch2/part8/server/middlewares/accessLogs.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const morgan = require("morgan");
4 |
5 | function accessLogs(toFile = false) {
6 | return morgan(":method :url - :status :response-time ms", {
7 | stream: toFile
8 | ? fs.createWriteStream(path.resolve(__dirname, "../access.log"), { flags: 'a' })
9 | : undefined,
10 | });
11 | }
12 |
13 | module.exports = { accessLogs };
14 |
--------------------------------------------------------------------------------
/ch2/part9/server/middlewares/accessLogs.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const morgan = require("morgan");
4 |
5 | function accessLogs(toFile = false) {
6 | return morgan(":method :url - :status :response-time ms", {
7 | stream: toFile
8 | ? fs.createWriteStream(path.resolve(__dirname, "../access.log"), { flags: 'a' })
9 | : undefined,
10 | });
11 | }
12 |
13 | module.exports = { accessLogs };
14 |
--------------------------------------------------------------------------------
/ch2/part5/utils/getDatabaseFilePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const { dbPath } = require("../config");
4 |
5 | function getDatabaseFilePath() {
6 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
7 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
8 |
9 | return process.env.LINKS_TYPE === "prod"
10 | ? linksProdFilePath
11 | : linksDevFilePath;
12 | }
13 |
14 | module.exports = { getDatabaseFilePath };
--------------------------------------------------------------------------------
/ch2/part6/utils/getDatabaseFilePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const { dbPath } = require("../config");
4 |
5 | function getDatabaseFilePath() {
6 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
7 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
8 |
9 | return process.env.LINKS_TYPE === "prod"
10 | ? linksProdFilePath
11 | : linksDevFilePath;
12 | }
13 |
14 | module.exports = { getDatabaseFilePath };
--------------------------------------------------------------------------------
/ch2/part7/utils/getDatabaseFilePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const { dbPath } = require("../config");
4 |
5 | function getDatabaseFilePath() {
6 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
7 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
8 |
9 | return process.env.LINKS_TYPE === "prod"
10 | ? linksProdFilePath
11 | : linksDevFilePath;
12 | }
13 |
14 | module.exports = { getDatabaseFilePath };
--------------------------------------------------------------------------------
/ch2/part8/client/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Shortener
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ch2/part8/server/utils/getDatabaseFilePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const { dbPath } = require("../config");
4 |
5 | function getDatabaseFilePath() {
6 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
7 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
8 |
9 | return process.env.LINKS_TYPE === "prod"
10 | ? linksProdFilePath
11 | : linksDevFilePath;
12 | }
13 |
14 | module.exports = { getDatabaseFilePath };
--------------------------------------------------------------------------------
/ch2/part9/client/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Shortener
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ch2/part9/server/utils/getDatabaseFilePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const { dbPath } = require("../config");
4 |
5 | function getDatabaseFilePath() {
6 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
7 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
8 |
9 | return process.env.LINKS_TYPE === "prod"
10 | ? linksProdFilePath
11 | : linksDevFilePath;
12 | }
13 |
14 | module.exports = { getDatabaseFilePath };
--------------------------------------------------------------------------------
/ch2/part4/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat",
6 | "carr": "https://yandex.ru/images/search?text=cat",
7 | "cat": "https://yandex.ru/images/search?text=cat",
8 | "var": "https://yandex.ru/images/search?text=cat",
9 | "c": "https://yandex.ru/images/search?text=cat",
10 | "catt": "https://yandex.ru/images/search?text=cat"
11 | }
--------------------------------------------------------------------------------
/ch2/part5/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat",
6 | "carr": "https://yandex.ru/images/search?text=cat",
7 | "cat": "https://yandex.ru/images/search?text=cat",
8 | "var": "https://yandex.ru/images/search?text=cat",
9 | "c": "https://yandex.ru/images/search?text=cat",
10 | "catt": "https://yandex.ru/images/search?text=cat"
11 | }
--------------------------------------------------------------------------------
/ch2/part6/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat",
6 | "carr": "https://yandex.ru/images/search?text=cat",
7 | "cat": "https://yandex.ru/images/search?text=cat",
8 | "var": "https://yandex.ru/images/search?text=cat",
9 | "c": "https://yandex.ru/images/search?text=cat",
10 | "catt": "https://yandex.ru/images/search?text=cat"
11 | }
--------------------------------------------------------------------------------
/ch2/part7/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat",
6 | "carr": "https://yandex.ru/images/search?text=cat",
7 | "cat": "https://yandex.ru/images/search?text=cat",
8 | "var": "https://yandex.ru/images/search?text=cat",
9 | "c": "https://yandex.ru/images/search?text=cat",
10 | "catt": "https://yandex.ru/images/search?text=cat"
11 | }
--------------------------------------------------------------------------------
/ch2/part3/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | this.status = status;
4 | this.message = message;
5 | }
6 | }
7 |
8 | class BadRequestError extends BaseError {
9 | constructor(message) {
10 | super(400, message);
11 | }
12 | }
13 |
14 | class NotFoundError extends BaseError {
15 | constructor(message) {
16 | super(404, message);
17 | }
18 | }
19 |
20 | module.exports = {
21 | BadRequestError,
22 | NotFoundError
23 | };
--------------------------------------------------------------------------------
/ch2/part4/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | super(message);
4 |
5 | this.status = status;
6 | }
7 | }
8 |
9 | class BadRequestError extends BaseError {
10 | constructor(message) {
11 | super(400, message);
12 | }
13 | }
14 |
15 | class NotFoundError extends BaseError {
16 | constructor(message) {
17 | super(404, message);
18 | }
19 | }
20 |
21 | module.exports = {
22 | BadRequestError,
23 | NotFoundError
24 | };
--------------------------------------------------------------------------------
/ch2/part5/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | super(message);
4 |
5 | this.status = status;
6 | }
7 | }
8 |
9 | class BadRequestError extends BaseError {
10 | constructor(message) {
11 | super(400, message);
12 | }
13 | }
14 |
15 | class NotFoundError extends BaseError {
16 | constructor(message) {
17 | super(404, message);
18 | }
19 | }
20 |
21 | module.exports = {
22 | BadRequestError,
23 | NotFoundError
24 | };
--------------------------------------------------------------------------------
/ch2/part6/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | super(message);
4 |
5 | this.status = status;
6 | }
7 | }
8 |
9 | class BadRequestError extends BaseError {
10 | constructor(message) {
11 | super(400, message);
12 | }
13 | }
14 |
15 | class NotFoundError extends BaseError {
16 | constructor(message) {
17 | super(404, message);
18 | }
19 | }
20 |
21 | module.exports = {
22 | BadRequestError,
23 | NotFoundError
24 | };
--------------------------------------------------------------------------------
/ch2/part7/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | super(message);
4 |
5 | this.status = status;
6 | }
7 | }
8 |
9 | class BadRequestError extends BaseError {
10 | constructor(message) {
11 | super(400, message);
12 | }
13 | }
14 |
15 | class NotFoundError extends BaseError {
16 | constructor(message) {
17 | super(404, message);
18 | }
19 | }
20 |
21 | module.exports = {
22 | BadRequestError,
23 | NotFoundError
24 | };
--------------------------------------------------------------------------------
/ch2/part8/server/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | super(message);
4 |
5 | this.status = status;
6 | }
7 | }
8 |
9 | class BadRequestError extends BaseError {
10 | constructor(message) {
11 | super(400, message);
12 | }
13 | }
14 |
15 | class NotFoundError extends BaseError {
16 | constructor(message) {
17 | super(404, message);
18 | }
19 | }
20 |
21 | module.exports = {
22 | BadRequestError,
23 | NotFoundError
24 | };
--------------------------------------------------------------------------------
/ch2/part9/server/modules/error.js:
--------------------------------------------------------------------------------
1 | class BaseError extends Error {
2 | constructor(status, message) {
3 | super(message);
4 |
5 | this.status = status;
6 | }
7 | }
8 |
9 | class BadRequestError extends BaseError {
10 | constructor(message) {
11 | super(400, message);
12 | }
13 | }
14 |
15 | class NotFoundError extends BaseError {
16 | constructor(message) {
17 | super(404, message);
18 | }
19 | }
20 |
21 | module.exports = {
22 | BadRequestError,
23 | NotFoundError
24 | };
--------------------------------------------------------------------------------
/ch2/part1/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { getByAlias } = require("../services/links");
2 |
3 | async function resolveAlias(request, response, next) {
4 | const { alias } = request.params;
5 |
6 | const longLink = await getByAlias(alias);
7 |
8 | if (!longLink) {
9 | return next();
10 | }
11 |
12 | if (process.env.NODE_ENV === 'production') {
13 | response.redirect(302, longLink);
14 | } else {
15 | response.send(longLink);
16 | }
17 | }
18 |
19 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part2/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const linksService = require("../services/links");
2 |
3 | async function resolveAlias(request, response, next) {
4 | const { alias } = request.params;
5 |
6 | const longLink = await linksService.getByAlias(alias);
7 |
8 | if (!longLink) {
9 | return next();
10 | }
11 |
12 | if (process.env.NODE_ENV === 'production') {
13 | response.redirect(302, longLink);
14 | } else {
15 | response.send(longLink);
16 | }
17 | }
18 |
19 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part1/services/links.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const { dbPath } = require("../config");
4 |
5 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
6 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
7 |
8 | const linksFilePath =
9 | process.env.LINKS_TYPE === "prod" ? linksProdFilePath : linksDevFilePath;
10 |
11 | async function getByAlias(alias) {
12 | const links = require(linksFilePath);
13 |
14 | return links[alias];
15 | }
16 |
17 | module.exports = {
18 | getByAlias,
19 | };
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parts",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "cors": "^2.8.5",
14 | "express": "^4.18.1",
15 | "express-rate-limit": "^6.5.1",
16 | "express-slow-down": "^1.4.0",
17 | "helmet": "^5.1.1",
18 | "http-proxy-middleware": "^2.0.6",
19 | "morgan": "^1.10.0",
20 | "ws": "^8.8.1"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ch2/part1/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { ping } = require("./controllers/ping");
5 | const { notFound } = require("./middlewares/notFound");
6 | const { urlLogger } = require("./middlewares/urlLogger");
7 |
8 | const app = express();
9 |
10 | app.use(urlLogger);
11 |
12 | app.get("/ping", ping);
13 | app.get("/:alias", resolveAlias);
14 |
15 | app.use(notFound);
16 |
17 | const PORT = 3000;
18 |
19 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
20 |
--------------------------------------------------------------------------------
/ch2/part9/server/ws.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require('ws');
2 | const { wsClients } = require('./modules/wsClients');
3 |
4 | function upgradeWithWs(server) {
5 | const wsServer = new WebSocket.Server({ server });
6 |
7 | wsServer.on('connection', async (ws, req) => {
8 | if (req.url === '/online-alias') {
9 | wsClients.add(ws);
10 |
11 | ws.on('error', () => {
12 | ws.close();
13 | });
14 |
15 | ws.on('close', () => {
16 | wsClients.remove(ws);
17 | });
18 | }
19 | });
20 | };
21 |
22 | module.exports = { upgradeWithWs }
--------------------------------------------------------------------------------
/ch2/part5/utils/dumpDatabase.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const { dbPath } = require("../config");
3 | const { compressFile } = require("../utils/compressFile");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | function dumpDatabase() {
9 | // better use https://www.npmjs.com/package/cron
10 | setInterval(() => {
11 | compressFile(linksFilePath, path.resolve(dbPath, "dumps"), "db-dump.json");
12 |
13 | console.log('Database dump was created.');
14 | }, 10000);
15 | }
16 |
17 | module.exports = { dumpDatabase };
18 |
--------------------------------------------------------------------------------
/ch2/part6/utils/dumpDatabase.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const { dbPath } = require("../config");
3 | const { compressFile } = require("../utils/compressFile");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | function dumpDatabase() {
9 | // better use https://www.npmjs.com/package/cron
10 | setInterval(() => {
11 | compressFile(linksFilePath, path.resolve(dbPath, "dumps"), "db-dump.json");
12 |
13 | console.log('Database dump was created.');
14 | }, 10000);
15 | }
16 |
17 | module.exports = { dumpDatabase };
18 |
--------------------------------------------------------------------------------
/ch2/part7/utils/dumpDatabase.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const { dbPath } = require("../config");
3 | const { compressFile } = require("../utils/compressFile");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | function dumpDatabase() {
9 | // better use https://www.npmjs.com/package/cron
10 | setInterval(() => {
11 | compressFile(linksFilePath, path.resolve(dbPath, "dumps"), "db-dump.json");
12 |
13 | console.log('Database dump was created.');
14 | }, 10000);
15 | }
16 |
17 | module.exports = { dumpDatabase };
18 |
--------------------------------------------------------------------------------
/ch2/part8/server/utils/dumpDatabase.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const { dbPath } = require("../config");
3 | const { compressFile } = require("../utils/compressFile");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | function dumpDatabase() {
9 | // better use https://www.npmjs.com/package/cron
10 | setInterval(() => {
11 | compressFile(linksFilePath, path.resolve(dbPath, "dumps"), "db-dump.json");
12 |
13 | console.log('Database dump was created.');
14 | }, 10000);
15 | }
16 |
17 | module.exports = { dumpDatabase };
18 |
--------------------------------------------------------------------------------
/ch2/part9/server/utils/dumpDatabase.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const { dbPath } = require("../config");
3 | const { compressFile } = require("../utils/compressFile");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | function dumpDatabase() {
9 | // better use https://www.npmjs.com/package/cron
10 | setInterval(() => {
11 | compressFile(linksFilePath, path.resolve(dbPath, "dumps"), "db-dump.json");
12 |
13 | console.log('Database dump was created.');
14 | }, 60000);
15 | }
16 |
17 | module.exports = { dumpDatabase };
18 |
--------------------------------------------------------------------------------
/ch2/part9/server/modules/wsClients.js:
--------------------------------------------------------------------------------
1 | class WsClients {
2 | constructor() {
3 | this.clients = [];
4 | }
5 |
6 | add(ws) {
7 | this.clients.push(ws);
8 |
9 | this.logClientsCount();
10 | }
11 |
12 | remove(ws) {
13 | this.clients = this.clients.filter((client) => client !== ws);
14 |
15 | this.logClientsCount();
16 | }
17 |
18 | forEach(callback) {
19 | this.logClientsCount();
20 |
21 | this.clients.forEach((client) => callback(client));
22 | }
23 |
24 | logClientsCount() {
25 | console.log(`ws clients count: ${this.clients.length}`);
26 | }
27 | }
28 |
29 | module.exports = { wsClients: new WsClients() };
30 |
--------------------------------------------------------------------------------
/ch2/part8/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/ch2/part9/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/ch2/part5/utils/compressFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const zlib = require("zlib");
4 |
5 | function compressFile(
6 | inputFilePath,
7 | outputFolder,
8 | resultFilename
9 | ) {
10 | return new Promise((resolve, reject) => {
11 | const stream = fs.createReadStream(inputFilePath);
12 |
13 | stream
14 | .pipe(zlib.createGzip())
15 | .pipe(
16 | fs.createWriteStream(path.resolve(outputFolder, `${Date.now()}_${resultFilename}.gz`), {
17 | flags: "a",
18 | })
19 | )
20 | .on("error", reject)
21 | .on("finish", resolve);
22 | });
23 | }
24 |
25 | module.exports = { compressFile };
26 |
--------------------------------------------------------------------------------
/ch2/part6/utils/compressFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const zlib = require("zlib");
4 |
5 | function compressFile(
6 | inputFilePath,
7 | outputFolder,
8 | resultFilename
9 | ) {
10 | return new Promise((resolve, reject) => {
11 | const stream = fs.createReadStream(inputFilePath);
12 |
13 | stream
14 | .pipe(zlib.createGzip())
15 | .pipe(
16 | fs.createWriteStream(path.resolve(outputFolder, `${Date.now()}_${resultFilename}.gz`), {
17 | flags: "a",
18 | })
19 | )
20 | .on("error", reject)
21 | .on("finish", resolve);
22 | });
23 | }
24 |
25 | module.exports = { compressFile };
26 |
--------------------------------------------------------------------------------
/ch2/part7/utils/compressFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const zlib = require("zlib");
4 |
5 | function compressFile(
6 | inputFilePath,
7 | outputFolder,
8 | resultFilename
9 | ) {
10 | return new Promise((resolve, reject) => {
11 | const stream = fs.createReadStream(inputFilePath);
12 |
13 | stream
14 | .pipe(zlib.createGzip())
15 | .pipe(
16 | fs.createWriteStream(path.resolve(outputFolder, `${Date.now()}_${resultFilename}.gz`), {
17 | flags: "a",
18 | })
19 | )
20 | .on("error", reject)
21 | .on("finish", resolve);
22 | });
23 | }
24 |
25 | module.exports = { compressFile };
26 |
--------------------------------------------------------------------------------
/ch2/part8/server/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat",
6 | "carr": "https://yandex.ru/images/search?text=cat",
7 | "cat": "https://yandex.ru/images/search?text=cat",
8 | "var": "https://yandex.ru/images/search?text=cat",
9 | "c": "https://yandex.ru/images/search?text=cat",
10 | "catt": "https://yandex.ru/images/search?text=cat",
11 | "random": "https://yandex.ru/dwadawdaw",
12 | "random1": "https://yandex.ru/dwadawdaw",
13 | "random2": "https://yandex.ru/dwadawdaw",
14 | "random6": "https://yandex.ru/dwadawdaw"
15 | }
--------------------------------------------------------------------------------
/ch2/part9/server/db/links.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru",
3 | "map": "https://yandex.ru/maps/",
4 | "tr": "https://translate.yandex.ru",
5 | "cats": "https://yandex.ru/images/search?text=cat",
6 | "carr": "https://yandex.ru/images/search?text=cat",
7 | "cat": "https://yandex.ru/images/search?text=cat",
8 | "var": "https://yandex.ru/images/search?text=cat",
9 | "c": "https://yandex.ru/images/search?text=cat",
10 | "catt": "https://yandex.ru/images/search?text=cat",
11 | "random": "https://yandex.ru/dwadawdaw",
12 | "random1": "https://yandex.ru/dwadawdaw",
13 | "random2": "https://yandex.ru/dwadawdaw",
14 | "random6": "https://yandex.ru/dwadawdaw"
15 | }
--------------------------------------------------------------------------------
/ch2/part8/server/utils/compressFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const zlib = require("zlib");
4 |
5 | function compressFile(
6 | inputFilePath,
7 | outputFolder,
8 | resultFilename
9 | ) {
10 | return new Promise((resolve, reject) => {
11 | const stream = fs.createReadStream(inputFilePath);
12 |
13 | stream
14 | .pipe(zlib.createGzip())
15 | .pipe(
16 | fs.createWriteStream(path.resolve(outputFolder, `${Date.now()}_${resultFilename}.gz`), {
17 | flags: "a",
18 | })
19 | )
20 | .on("error", reject)
21 | .on("finish", resolve);
22 | });
23 | }
24 |
25 | module.exports = { compressFile };
26 |
--------------------------------------------------------------------------------
/ch2/part9/server/utils/compressFile.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const zlib = require("zlib");
4 |
5 | function compressFile(
6 | inputFilePath,
7 | outputFolder,
8 | resultFilename
9 | ) {
10 | return new Promise((resolve, reject) => {
11 | const stream = fs.createReadStream(inputFilePath);
12 |
13 | stream
14 | .pipe(zlib.createGzip())
15 | .pipe(
16 | fs.createWriteStream(path.resolve(outputFolder, `${Date.now()}_${resultFilename}.gz`), {
17 | flags: "a",
18 | })
19 | )
20 | .on("error", reject)
21 | .on("finish", resolve);
22 | });
23 | }
24 |
25 | module.exports = { compressFile };
26 |
--------------------------------------------------------------------------------
/ch2/part2/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { addAlias } = require("./controllers/addAlias");
5 | const { ping } = require("./controllers/ping");
6 | const { notFound } = require("./middlewares/notFound");
7 | const { urlLogger } = require("./middlewares/urlLogger");
8 |
9 | const app = express();
10 |
11 | app.use(express.json());
12 |
13 | app.use(urlLogger);
14 |
15 | app.get("/ping", ping);
16 | app.get("/:alias", resolveAlias);
17 | app.post("/alias", addAlias);
18 |
19 | app.use(notFound);
20 |
21 | const PORT = 3000;
22 |
23 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
24 |
--------------------------------------------------------------------------------
/ch2/part6/utils/monitorProcess.js:
--------------------------------------------------------------------------------
1 | const { exec: execOnCallbacks } = require("child_process");
2 | const util = require("util");
3 | const fs = require("fs/promises");
4 | const path = require("path");
5 |
6 | const exec = util.promisify(execOnCallbacks);
7 |
8 | async function monitorProcess() {
9 | setInterval(async () => {
10 | const { pid } = process;
11 |
12 | const { stdout } = await exec(
13 | `ps -p ${pid} -o pid,vsz=MEMORY,pcpu -o comm,args=ARGS`
14 | );
15 |
16 | const log = `${new Date()}\n${stdout}`;
17 |
18 | await fs.writeFile(path.resolve(__dirname, "../cpu-memory.log"), log, {
19 | flag: "a",
20 | });
21 | }, 2000);
22 | }
23 |
24 | module.exports = { monitorProcess };
25 |
--------------------------------------------------------------------------------
/ch2/part7/utils/monitorProcess.js:
--------------------------------------------------------------------------------
1 | const { exec: execOnCallbacks } = require("child_process");
2 | const util = require("util");
3 | const fs = require("fs/promises");
4 | const path = require("path");
5 |
6 | const exec = util.promisify(execOnCallbacks);
7 |
8 | async function monitorProcess() {
9 | setInterval(async () => {
10 | const { pid } = process;
11 |
12 | const { stdout } = await exec(
13 | `ps -p ${pid} -o pid,vsz=MEMORY,pcpu -o comm,args=ARGS`
14 | );
15 |
16 | const log = `${new Date()}\n${stdout}`;
17 |
18 | await fs.writeFile(path.resolve(__dirname, "../cpu-memory.log"), log, {
19 | flag: "a",
20 | });
21 | }, 2000);
22 | }
23 |
24 | module.exports = { monitorProcess };
25 |
--------------------------------------------------------------------------------
/ch2/part8/server/utils/monitorProcess.js:
--------------------------------------------------------------------------------
1 | const { exec: execOnCallbacks } = require("child_process");
2 | const util = require("util");
3 | const fs = require("fs/promises");
4 | const path = require("path");
5 |
6 | const exec = util.promisify(execOnCallbacks);
7 |
8 | async function monitorProcess() {
9 | setInterval(async () => {
10 | const { pid } = process;
11 |
12 | const { stdout } = await exec(
13 | `ps -p ${pid} -o pid,vsz=MEMORY,pcpu -o comm,args=ARGS`
14 | );
15 |
16 | const log = `${new Date()}\n${stdout}`;
17 |
18 | await fs.writeFile(path.resolve(__dirname, "../cpu-memory.log"), log, {
19 | flag: "a",
20 | });
21 | }, 2000);
22 | }
23 |
24 | module.exports = { monitorProcess };
25 |
--------------------------------------------------------------------------------
/ch2/part9/client/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { BrowserRouter, Route, Routes } from "react-router-dom";
3 | import ReactDOM from "react-dom/client";
4 | import { ChakraProvider } from "@chakra-ui/react";
5 | import { Home } from "./Home";
6 | import { Online } from "./Online";
7 | import "./index.css";
8 |
9 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
10 |
11 |
12 |
13 |
14 | } />
15 | } />
16 |
17 |
18 |
19 |
20 | );
21 |
--------------------------------------------------------------------------------
/ch2/part9/server/utils/monitorProcess.js:
--------------------------------------------------------------------------------
1 | const { exec: execOnCallbacks } = require("child_process");
2 | const util = require("util");
3 | const fs = require("fs/promises");
4 | const path = require("path");
5 |
6 | const exec = util.promisify(execOnCallbacks);
7 |
8 | async function monitorProcess() {
9 | setInterval(async () => {
10 | const { pid } = process;
11 |
12 | const { stdout } = await exec(
13 | `ps -p ${pid} -o pid,vsz=MEMORY,pcpu -o comm,args=ARGS`
14 | );
15 |
16 | const log = `${new Date()}\n${stdout}`;
17 |
18 | await fs.writeFile(path.resolve(__dirname, "../cpu-memory.log"), log, {
19 | flag: "a",
20 | });
21 | }, 2000);
22 | }
23 |
24 | module.exports = { monitorProcess };
25 |
--------------------------------------------------------------------------------
/ch2/part8/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@chakra-ui/react": "^2.2.4",
17 | "@emotion/react": "^11.9.3",
18 | "@emotion/styled": "^11.9.3",
19 | "@types/react": "^18.0.15",
20 | "@types/react-dom": "^18.0.6",
21 | "@vitejs/plugin-react": "^2.0.0",
22 | "framer-motion": "^6.5.1",
23 | "react-hook-form": "^7.33.1",
24 | "typescript": "^4.6.4",
25 | "vite": "^3.0.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ch2/part9/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0"
14 | },
15 | "devDependencies": {
16 | "@chakra-ui/react": "^2.2.4",
17 | "@emotion/react": "^11.9.3",
18 | "@emotion/styled": "^11.9.3",
19 | "@types/react": "^18.0.15",
20 | "@types/react-dom": "^18.0.6",
21 | "@vitejs/plugin-react": "^2.0.0",
22 | "framer-motion": "^6.5.1",
23 | "react-hook-form": "^7.33.1",
24 | "react-router-dom": "^6.3.0",
25 | "typescript": "^4.6.4",
26 | "vite": "^3.0.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ch2/part3/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { addAlias } = require("./controllers/addAlias");
5 | const { ping } = require("./controllers/ping");
6 | const { notFound } = require("./middlewares/notFound");
7 | const { urlLogger } = require("./middlewares/urlLogger");
8 | const { errorHandler } = require("./middlewares/errorHandler");
9 |
10 | const app = express();
11 |
12 | app.use(express.json());
13 |
14 | app.use(urlLogger);
15 |
16 | app.get("/ping", ping);
17 | app.get("/:alias", resolveAlias);
18 | app.post("/alias", addAlias);
19 |
20 | app.use(notFound);
21 |
22 | app.use(errorHandler);
23 |
24 | const PORT = 3000;
25 |
26 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
27 |
--------------------------------------------------------------------------------
/ch2/part5/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const { BadRequestError } = require("../modules/error");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | async function getByAlias(alias) {
9 | const links = require(linksFilePath);
10 |
11 | return links[alias];
12 | }
13 |
14 | async function addAlias(alias, link) {
15 | const links = require(linksFilePath);
16 |
17 | if (links[alias]) {
18 | throw new BadRequestError('alias-already-exists');
19 | }
20 |
21 | links[alias] = link;
22 |
23 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
24 |
25 | return links[alias];
26 | }
27 |
28 | module.exports = {
29 | getByAlias,
30 | addAlias
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part6/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const { BadRequestError } = require("../modules/error");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | async function getByAlias(alias) {
9 | const links = require(linksFilePath);
10 |
11 | return links[alias];
12 | }
13 |
14 | async function addAlias(alias, link) {
15 | const links = require(linksFilePath);
16 |
17 | if (links[alias]) {
18 | throw new BadRequestError('alias-already-exists');
19 | }
20 |
21 | links[alias] = link;
22 |
23 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
24 |
25 | return links[alias];
26 | }
27 |
28 | module.exports = {
29 | getByAlias,
30 | addAlias
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part7/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const { BadRequestError } = require("../modules/error");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | async function getByAlias(alias) {
9 | const links = require(linksFilePath);
10 |
11 | return links[alias];
12 | }
13 |
14 | async function addAlias(alias, link) {
15 | const links = require(linksFilePath);
16 |
17 | if (links[alias]) {
18 | throw new BadRequestError('alias-already-exists');
19 | }
20 |
21 | links[alias] = link;
22 |
23 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
24 |
25 | return links[alias];
26 | }
27 |
28 | module.exports = {
29 | getByAlias,
30 | addAlias
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part8/server/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const { BadRequestError } = require("../modules/error");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | async function getByAlias(alias) {
9 | const links = require(linksFilePath);
10 |
11 | return links[alias];
12 | }
13 |
14 | async function addAlias(alias, link) {
15 | const links = require(linksFilePath);
16 |
17 | if (links[alias]) {
18 | throw new BadRequestError('alias-already-exists');
19 | }
20 |
21 | links[alias] = link;
22 |
23 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
24 |
25 | return links[alias];
26 | }
27 |
28 | module.exports = {
29 | getByAlias,
30 | addAlias
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part9/server/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const { BadRequestError } = require("../modules/error");
4 | const { getDatabaseFilePath } = require("../utils/getDatabaseFilePath");
5 |
6 | const linksFilePath = getDatabaseFilePath();
7 |
8 | async function getByAlias(alias) {
9 | const links = require(linksFilePath);
10 |
11 | return links[alias];
12 | }
13 |
14 | async function addAlias(alias, link) {
15 | const links = require(linksFilePath);
16 |
17 | if (links[alias]) {
18 | throw new BadRequestError('alias-already-exists');
19 | }
20 |
21 | links[alias] = link;
22 |
23 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
24 |
25 | return links[alias];
26 | }
27 |
28 | module.exports = {
29 | getByAlias,
30 | addAlias
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part4/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { addAlias } = require("./controllers/addAlias");
5 | const { ping } = require("./controllers/ping");
6 | const { notFound } = require("./middlewares/notFound");
7 | const { errorHandler } = require("./middlewares/errorHandler");
8 | const { accessLogs } = require("./middlewares/accessLogs");
9 |
10 | const app = express();
11 |
12 | app.use(express.json());
13 |
14 | app.use(accessLogs());
15 | app.use(accessLogs(true));
16 |
17 | app.get("/ping", ping);
18 | app.get("/:alias", resolveAlias);
19 | app.post("/alias", addAlias);
20 |
21 | app.use(notFound);
22 |
23 | app.use(errorHandler);
24 |
25 | const PORT = 3000;
26 |
27 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
28 |
--------------------------------------------------------------------------------
/ch2/part2/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 | const { dbPath } = require("../config");
5 |
6 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
7 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
8 |
9 | const linksFilePath =
10 | process.env.LINKS_TYPE === "prod" ? linksProdFilePath : linksDevFilePath;
11 |
12 | async function getByAlias(alias) {
13 | const links = require(linksFilePath);
14 |
15 | return links[alias];
16 | }
17 |
18 | async function addAlias(alias, link) {
19 | const links = require(linksFilePath);
20 |
21 | links[alias] = link;
22 |
23 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
24 |
25 | return links[alias];
26 | }
27 |
28 | module.exports = {
29 | getByAlias,
30 | addAlias
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part3/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const linksService = require("../services/links");
3 |
4 | async function resolveAlias(request, response, next) {
5 | try {
6 | const { alias } = request.params;
7 |
8 | if (/^[a-zA-Z0-9]+$/.test(alias) === false) {
9 | return next();
10 | }
11 |
12 | const longLink = await linksService.getByAlias(alias);
13 |
14 | if (!longLink) {
15 | throw new NotFoundError(`Alias "${alias}" was not found...`);
16 | }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | response.redirect(302, longLink);
20 | } else {
21 | response.send(longLink);
22 | }
23 | } catch (err) {
24 | next(err);
25 | }
26 | }
27 |
28 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch1/part4/script.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs").promises;
2 | const path = require("path");
3 |
4 | const linksDevFilePath = path.resolve(__dirname, "./links.dev.txt");
5 | const linksProdFilePath = path.resolve(__dirname, "./links.prod.txt");
6 |
7 | const linksFilePath =
8 | process.env.LINKS_TYPE === "prod" ? linksProdFilePath : linksDevFilePath;
9 |
10 | async function printLinkByAlias(alias) {
11 | const linksFileContent = await fs.readFile(linksFilePath, "utf-8");
12 |
13 | const links = linksFileContent
14 | .split("\n") // get rows
15 | .filter((str) => !!str) // or just .filter(Boolean);
16 | .map((row) => row.split(" ")) // split alias from full link
17 | .reduce((acc, curr) => ({ ...acc, [curr[0]]: curr[1] }), {}); // construct links object
18 |
19 | console.log(links[alias]);
20 | }
21 |
22 | const alias = process.argv[2];
23 |
24 | printLinkByAlias(alias);
25 |
--------------------------------------------------------------------------------
/ch2/part4/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const linksService = require("../services/links");
3 |
4 | async function resolveAlias(request, response, next) {
5 | try {
6 | const { alias } = request.params;
7 |
8 | if (alias.length === 0 || /^[a-zA-Z0-9]+$/.test(alias) === false) {
9 | return next();
10 | }
11 |
12 | const longLink = await linksService.getByAlias(alias);
13 |
14 | if (!longLink) {
15 | throw new NotFoundError(`Alias "${alias}" was not found...`);
16 | }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | response.redirect(302, longLink);
20 | } else {
21 | response.send(longLink);
22 | }
23 | } catch (err) {
24 | next(err);
25 | }
26 | }
27 |
28 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part5/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const linksService = require("../services/links");
3 |
4 | async function resolveAlias(request, response, next) {
5 | try {
6 | const { alias } = request.params;
7 |
8 | if (alias.length === 0 || /^[a-zA-Z0-9]+$/.test(alias) === false) {
9 | return next();
10 | }
11 |
12 | const longLink = await linksService.getByAlias(alias);
13 |
14 | if (!longLink) {
15 | throw new NotFoundError(`Alias "${alias}" was not found...`);
16 | }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | response.redirect(302, longLink);
20 | } else {
21 | response.send(longLink);
22 | }
23 | } catch (err) {
24 | next(err);
25 | }
26 | }
27 |
28 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part6/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const linksService = require("../services/links");
3 |
4 | async function resolveAlias(request, response, next) {
5 | try {
6 | const { alias } = request.params;
7 |
8 | if (alias.length === 0 || /^[a-zA-Z0-9]+$/.test(alias) === false) {
9 | return next();
10 | }
11 |
12 | const longLink = await linksService.getByAlias(alias);
13 |
14 | if (!longLink) {
15 | throw new NotFoundError(`Alias "${alias}" was not found...`);
16 | }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | response.redirect(302, longLink);
20 | } else {
21 | response.send(longLink);
22 | }
23 | } catch (err) {
24 | next(err);
25 | }
26 | }
27 |
28 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part7/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const linksService = require("../services/links");
3 |
4 | async function resolveAlias(request, response, next) {
5 | try {
6 | const { alias } = request.params;
7 |
8 | if (alias.length === 0 || /^[a-zA-Z0-9]+$/.test(alias) === false) {
9 | return next();
10 | }
11 |
12 | const longLink = await linksService.getByAlias(alias);
13 |
14 | if (!longLink) {
15 | throw new NotFoundError(`Alias "${alias}" was not found...`);
16 | }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | response.redirect(302, longLink);
20 | } else {
21 | response.send(longLink);
22 | }
23 | } catch (err) {
24 | next(err);
25 | }
26 | }
27 |
28 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part8/server/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const linksService = require("../services/links");
3 |
4 | async function resolveAlias(request, response, next) {
5 | try {
6 | const { alias } = request.params;
7 |
8 | if (alias.length === 0 || /^[a-zA-Z0-9]+$/.test(alias) === false) {
9 | return next();
10 | }
11 |
12 | const longLink = await linksService.getByAlias(alias);
13 |
14 | if (!longLink) {
15 | throw new NotFoundError(`Alias "${alias}" was not found...`);
16 | }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | response.redirect(302, longLink);
20 | } else {
21 | response.send(longLink);
22 | }
23 | } catch (err) {
24 | next(err);
25 | }
26 | }
27 |
28 | module.exports = { resolveAlias };
--------------------------------------------------------------------------------
/ch2/part9/client/src/Online.tsx:
--------------------------------------------------------------------------------
1 | import { Container, Stat, StatLabel, StatNumber } from "@chakra-ui/react";
2 | import { useEffect, useState } from "react";
3 | import { useParams } from "react-router-dom";
4 |
5 | export const Online = () => {
6 | const params = useParams<{ alias: string }>();
7 | const [count, setCount] = useState(0);
8 |
9 | useEffect(() => {
10 | const ws = new WebSocket('ws://localhost:3000/online-alias');
11 |
12 | ws.onmessage = (event) => {
13 | if (event.data === params.alias) {
14 | setCount(count => count + 1);
15 | }
16 | };
17 |
18 | return () => {
19 | ws.close();
20 | };
21 | }, []);
22 |
23 | return (
24 |
25 |
26 | Opened "{params.alias}"
27 | {count}
28 |
29 |
30 | );
31 | };
32 |
--------------------------------------------------------------------------------
/ch2/part5/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { addAlias } = require("./controllers/addAlias");
5 | const { ping } = require("./controllers/ping");
6 | const { notFound } = require("./middlewares/notFound");
7 | const { errorHandler } = require("./middlewares/errorHandler");
8 | const { accessLogs } = require("./middlewares/accessLogs");
9 | const { dumpDatabase } = require("./utils/dumpDatabase");
10 |
11 | const app = express();
12 |
13 | app.use(express.json());
14 |
15 | app.use(accessLogs());
16 | app.use(accessLogs(true));
17 |
18 | app.get("/ping", ping);
19 | app.get("/:alias", resolveAlias);
20 | app.post("/alias", addAlias);
21 |
22 | app.use(notFound);
23 |
24 | app.use(errorHandler);
25 |
26 | const PORT = 3000;
27 |
28 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
29 |
30 | dumpDatabase();
31 |
--------------------------------------------------------------------------------
/ch2/part6/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { addAlias } = require("./controllers/addAlias");
5 | const { ping } = require("./controllers/ping");
6 | const { notFound } = require("./middlewares/notFound");
7 | const { errorHandler } = require("./middlewares/errorHandler");
8 | const { accessLogs } = require("./middlewares/accessLogs");
9 | const { dumpDatabase } = require("./utils/dumpDatabase");
10 | const { monitorProcess } = require("./utils/monitorProcess");
11 |
12 | const app = express();
13 |
14 | app.use(express.json());
15 |
16 | app.use(accessLogs());
17 | app.use(accessLogs(true));
18 |
19 | app.get("/ping", ping);
20 | app.get("/:alias", resolveAlias);
21 | app.post("/alias", addAlias);
22 |
23 | app.use(notFound);
24 |
25 | app.use(errorHandler);
26 |
27 | const PORT = 3000;
28 |
29 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
30 |
31 | dumpDatabase();
32 | monitorProcess();
--------------------------------------------------------------------------------
/ch2/part3/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 | const { dbPath } = require("../config");
5 | const { BadRequestError } = require("../modules/error");
6 |
7 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
8 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
9 |
10 | const linksFilePath =
11 | process.env.LINKS_TYPE === "prod" ? linksProdFilePath : linksDevFilePath;
12 |
13 | async function getByAlias(alias) {
14 | const links = require(linksFilePath);
15 |
16 | return links[alias];
17 | }
18 |
19 | async function addAlias(alias, link) {
20 | const links = require(linksFilePath);
21 |
22 | if (links[alias]) {
23 | throw new BadRequestError('alias-already-exists');
24 | }
25 |
26 | links[alias] = link;
27 |
28 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
29 |
30 | return links[alias];
31 | }
32 |
33 | module.exports = {
34 | getByAlias,
35 | addAlias
36 | };
37 |
--------------------------------------------------------------------------------
/ch2/part4/services/links.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 | const { dbPath } = require("../config");
5 | const { BadRequestError } = require("../modules/error");
6 |
7 | const linksDevFilePath = path.resolve(dbPath, "./links.dev.json");
8 | const linksProdFilePath = path.resolve(dbPath, "./links.prod.json");
9 |
10 | const linksFilePath =
11 | process.env.LINKS_TYPE === "prod" ? linksProdFilePath : linksDevFilePath;
12 |
13 | async function getByAlias(alias) {
14 | const links = require(linksFilePath);
15 |
16 | return links[alias];
17 | }
18 |
19 | async function addAlias(alias, link) {
20 | const links = require(linksFilePath);
21 |
22 | if (links[alias]) {
23 | throw new BadRequestError('alias-already-exists');
24 | }
25 |
26 | links[alias] = link;
27 |
28 | await fs.writeFile(linksFilePath, JSON.stringify(links, null, 2), "utf-8");
29 |
30 | return links[alias];
31 | }
32 |
33 | module.exports = {
34 | getByAlias,
35 | addAlias
36 | };
37 |
--------------------------------------------------------------------------------
/ch2/part9/server/controllers/resolveAlias.js:
--------------------------------------------------------------------------------
1 | const { NotFoundError } = require("../modules/error");
2 | const { wsClients } = require("../modules/wsClients");
3 | const linksService = require("../services/links");
4 |
5 | async function resolveAlias(request, response, next) {
6 | try {
7 | const { alias } = request.params;
8 |
9 | if (alias.length === 0 || /^[a-zA-Z0-9]+$/.test(alias) === false) {
10 | return next();
11 | }
12 |
13 | const longLink = await linksService.getByAlias(alias);
14 |
15 | if (!longLink) {
16 | throw new NotFoundError(`Alias "${alias}" was not found...`);
17 | }
18 |
19 | wsClients.forEach((wsClient) => {
20 | if (wsClient.readyState === 1) {
21 | wsClient.send(alias);
22 | }
23 | });
24 |
25 | if (process.env.NODE_ENV === "production") {
26 | response.redirect(302, longLink);
27 | } else {
28 | response.send(longLink);
29 | }
30 | } catch (err) {
31 | next(err);
32 | }
33 | }
34 |
35 | module.exports = { resolveAlias };
36 |
--------------------------------------------------------------------------------
/ch2/part7/server.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const { resolveAlias } = require("./controllers/resolveAlias");
4 | const { addAlias } = require("./controllers/addAlias");
5 | const { ping } = require("./controllers/ping");
6 | const { notFound } = require("./middlewares/notFound");
7 | const { errorHandler } = require("./middlewares/errorHandler");
8 | const { accessLogs } = require("./middlewares/accessLogs");
9 | const { dumpDatabase } = require("./utils/dumpDatabase");
10 | const { monitorProcess } = require("./utils/monitorProcess");
11 | const { secure } = require("./middlewares/security");
12 |
13 | const app = express();
14 |
15 | secure(app);
16 |
17 | app.use(express.json());
18 |
19 | app.use(accessLogs());
20 | app.use(accessLogs(true));
21 |
22 | app.get("/ping", ping);
23 | app.get("/:alias", resolveAlias);
24 | app.post("/alias", addAlias);
25 |
26 | app.use(notFound);
27 |
28 | app.use(errorHandler);
29 |
30 | const PORT = 3000;
31 |
32 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
33 |
34 | dumpDatabase();
35 | monitorProcess();
--------------------------------------------------------------------------------
/ch2/part8/server/server.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const express = require("express");
4 | const { createProxyMiddleware } = require("http-proxy-middleware");
5 |
6 | const { resolveAlias } = require("./controllers/resolveAlias");
7 | const { addAlias } = require("./controllers/addAlias");
8 | const { ping } = require("./controllers/ping");
9 | const { notFound } = require("./middlewares/notFound");
10 | const { errorHandler } = require("./middlewares/errorHandler");
11 | const { accessLogs } = require("./middlewares/accessLogs");
12 | const { dumpDatabase } = require("./utils/dumpDatabase");
13 | const { monitorProcess } = require("./utils/monitorProcess");
14 | const { secure } = require("./middlewares/security");
15 |
16 | const app = express();
17 |
18 | secure(app);
19 |
20 | app.use(express.json());
21 |
22 | app.use(accessLogs());
23 | app.use(accessLogs(true));
24 |
25 | app.get("/ping", ping);
26 | app.get("/:alias", resolveAlias);
27 | app.post("/alias", addAlias);
28 |
29 | app.use(
30 | process.env.NODE_ENV === "production"
31 | ? express.static(path.resolve(__dirname, "../client/dist"))
32 | : createProxyMiddleware({
33 | target: "http://localhost:3001",
34 | changeOrigin: true,
35 | })
36 | );
37 |
38 | app.use(notFound);
39 |
40 | app.use(errorHandler);
41 |
42 | const PORT = 3000;
43 |
44 | app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
45 |
46 | dumpDatabase();
47 | monitorProcess();
48 |
--------------------------------------------------------------------------------
/ch1/part5/script.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 | const http = require("http");
4 |
5 | const linksDevFilePath = path.resolve(__dirname, "./links.dev.txt");
6 | const linksProdFilePath = path.resolve(__dirname, "./links.prod.txt");
7 |
8 | const linksFilePath =
9 | process.env.NODE_ENV === "production" ? linksProdFilePath : linksDevFilePath;
10 |
11 | async function printLinkByAlias(alias) {
12 | const linksFileContent = await fs.readFile(linksFilePath, "utf-8");
13 |
14 | const links = linksFileContent
15 | .split("\n") // get rows
16 | .filter((str) => !!str) // or just .filter(Boolean);
17 | .map((row) => row.split(" ")) // split alias from full link
18 | .reduce((acc, curr) => ({ ...acc, [curr[0]]: curr[1] }), {}); // construct links object
19 |
20 | return links[alias];
21 | }
22 |
23 | const server = http.createServer((request, response) => {
24 | console.log(request.url);
25 |
26 | const alias = request.url.slice(1);
27 |
28 | printLinkByAlias(alias).then((longLink) => {
29 | if (!longLink) {
30 | response.statusCode = 404;
31 | return response.end('not-found');
32 | }
33 |
34 | if (process.env.NODE_ENV === 'production') {
35 | response.setHeader('location', longLink);
36 | response.statusCode = 302;
37 |
38 | response.end();
39 | } else {
40 | response.end(longLink);
41 | }
42 | });
43 | });
44 |
45 | server.listen(3000, () => console.log("Server started on port 3000"));
46 |
--------------------------------------------------------------------------------
/ch1/part4/links.prod.txt:
--------------------------------------------------------------------------------
1 | music https://music.yandex.ru/album/7375892/track/52396212
2 | map https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13
3 | tr https://translate.yandex.ru/?lang=en-ru&text=hello%20world
4 | video1 https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8
5 | video2 https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw
6 |
--------------------------------------------------------------------------------
/ch1/part5/links.prod.txt:
--------------------------------------------------------------------------------
1 | music https://music.yandex.ru/album/7375892/track/52396212
2 | map https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13
3 | tr https://translate.yandex.ru/?lang=en-ru&text=hello%20world
4 | video1 https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8
5 | video2 https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw
6 |
--------------------------------------------------------------------------------
/ch2/part9/server/server.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const http = require('http');
3 |
4 | const express = require("express");
5 |
6 | const { resolveAlias } = require("./controllers/resolveAlias");
7 | const { addAlias } = require("./controllers/addAlias");
8 | const { ping } = require("./controllers/ping");
9 | const { notFound } = require("./middlewares/notFound");
10 | const { errorHandler } = require("./middlewares/errorHandler");
11 | const { accessLogs } = require("./middlewares/accessLogs");
12 | const { dumpDatabase } = require("./utils/dumpDatabase");
13 | const { monitorProcess } = require("./utils/monitorProcess");
14 | const { secure } = require("./middlewares/security");
15 | const { upgradeWithWs } = require("./ws");
16 |
17 | const app = express();
18 |
19 | secure(app);
20 |
21 | app.use(express.json());
22 |
23 | app.use(accessLogs());
24 | app.use(accessLogs(true));
25 |
26 | app.get("/ping", ping);
27 | app.get("/:alias", resolveAlias);
28 | app.post("/alias", addAlias);
29 |
30 | app.use(express.static(path.resolve(__dirname, "../client/dist")));
31 |
32 | app.use((request, response) => {
33 | response.sendFile(path.resolve(__dirname, "../client/dist/index.html"));
34 | });
35 |
36 | app.use(notFound);
37 |
38 | app.use(errorHandler);
39 |
40 | const server = http.createServer(app);
41 |
42 | upgradeWithWs(server);
43 |
44 | const PORT = 3000;
45 |
46 | server.listen(PORT, () => console.log(`Server started on port ${PORT}`));
47 |
48 | if (process.env.NODE_ENV === 'production') {
49 | dumpDatabase();
50 | monitorProcess();
51 | }
52 |
--------------------------------------------------------------------------------
/ch2/part1/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part2/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part3/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part4/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part5/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part6/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part7/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part8/server/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch2/part9/server/db/links.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "music": "https://music.yandex.ru/album/7375892/track/52396212",
3 | "map": "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | "tr": "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | "video1": "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | "video2": "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw"
7 | }
8 |
--------------------------------------------------------------------------------
/ch1/part1/script.js:
--------------------------------------------------------------------------------
1 | const links = {
2 | music: "https://music.yandex.ru/album/7375892/track/52396212",
3 | map: "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
4 | tr: "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
5 | video1: "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
6 | video2: "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw",
7 | };
8 |
9 | const alias = 'map';
10 |
11 | console.log(links[alias]);
12 |
--------------------------------------------------------------------------------
/ch1/part2/script.js:
--------------------------------------------------------------------------------
1 | const links =
2 | process.env.LINKS_TYPE === "prod"
3 | ? {
4 | music: "https://music.yandex.ru/album/7375892/track/52396212",
5 | map: "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
6 | tr: "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
7 | video1:
8 | "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
9 | video2:
10 | "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw",
11 | }
12 | : {
13 | music: "https://music.yandex.ru",
14 | map: "https://yandex.ru/maps/",
15 | tr: "https://translate.yandex.ru",
16 | };
17 |
18 | const alias = 'map';
19 |
20 | console.log(process.env.LINKS_TYPE);
21 | console.log(links[alias]);
22 |
--------------------------------------------------------------------------------
/ch1/part3/script.js:
--------------------------------------------------------------------------------
1 | const links =
2 | process.env.LINKS_TYPE === "prod"
3 | ? {
4 | music: "https://music.yandex.ru/album/7375892/track/52396212",
5 | map: "https://yandex.ru/maps/org/yandeks/1124715036/?ll=37.570552%2C55.738210&mode=search&sctx=ZAAAAAgBEAAaKAoSCeUn1T4dz0JAEYNqgxPR4UtAEhIJU%2BdR8X9H%2Bj8RjbeVXpsN4z8iBgABAgMEBSgKOABAAUgBYiZyZWxldl9pcnJlbF9maWx0ZXI9aXJyZWxfZm1sODYxODE3X2V4cGIrcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9FbmFibGVCZWF1dHlGaWx0ZXI9MWI2cmVhcnI9c2NoZW1lX0xvY2FsL0dlby9Qb3N0ZmlsdGVyL05ld1JlbGV2QmVydFRocj0wLjAwagJydZ0BzcxMPaABAKgBAL0BqtRcd8IBkAGclKeYBLPFr7HYA4jV%2BZkEw%2FbJhS3Hi7ia7wKdnNru0QKqz8e7sQLDpObjlwO65oOD0wTPiObJqwWnsdS9oAHH5%2B7K7wP4lKvl3QSinfCJwwGgkOqk%2FgS80af07ATMstfRPZbN2%2FGmBvvk6KWDBu2H3JsrjMvo87sC%2F4Pjma4B%2F5nv3bcG4Jruk6cDrPXfoHHqAQDyAQD4AQCCAgzRj9C90LTQtdC60YGKAgCSAgCaAgxkZXNrdG9wLW1hcHM%3D&sll=37.570552%2C55.738210&sspn=0.124641%2C0.045214&text=%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&z=13",
6 | tr: "https://translate.yandex.ru/?lang=en-ru&text=hello%20world",
7 | video1:
8 | "https://yandex.ru/video/preview/?filmId=198484335193438218&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8",
9 | video2:
10 | "https://yandex.ru/video/preview/?filmId=2479178741132479613&reqid=1658097906196960-7557307180056272063-sas3-0732-e22-sas-l7-balancer-8080-BAL-7048&suggest_reqid=202606689162876927279060549798666&text=%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE+%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81+%D1%88%D1%80%D0%B8&url=http%3A%2F%2Ffrontend.vh.yandex.ru%2Fplayer%2Fvi1tqpQxcVAw",
11 | }
12 | : {
13 | music: "https://music.yandex.ru",
14 | map: "https://yandex.ru/maps/",
15 | tr: "https://translate.yandex.ru",
16 | };
17 |
18 | console.log(process.argv);
19 |
20 | const alias = process.argv[2];
21 |
22 | console.log(links[alias]);
23 |
--------------------------------------------------------------------------------
/ch2/part7/middlewares/security.js:
--------------------------------------------------------------------------------
1 | const { disablePoweredBy } = require("./disablePoweredBy");
2 |
3 | const cors = require("cors");
4 | const helmet = require("helmet");
5 | const rateLimiter = require("express-rate-limit");
6 | const slowDown = require("express-slow-down");
7 |
8 | function secure(app) {
9 | app.use(disablePoweredBy);
10 |
11 | app.use(
12 | cors({
13 | origin: ["https://example.ru", "http://localhost:3000"],
14 | })
15 | );
16 |
17 | app.use(
18 | helmet({
19 | contentSecurityPolicy: {
20 | useDefaults: true,
21 | directives: {
22 | scriptSrc: [
23 | "'self'",
24 | "'unsafe-inline'",
25 | "https://cdn.jsdelivr.net",
26 | "https://code.jquery.com",
27 | ],
28 | },
29 | },
30 | })
31 | );
32 |
33 | // app.use(helmet.contentSecurityPolicy());
34 | // app.use(helmet.crossOriginEmbedderPolicy());
35 | // app.use(helmet.crossOriginOpenerPolicy());
36 | // app.use(helmet.crossOriginResourcePolicy());
37 | // app.use(helmet.dnsPrefetchControl());
38 | // app.use(helmet.expectCt());
39 | // app.use(helmet.frameguard());
40 | // app.use(helmet.hidePoweredBy());
41 | // app.use(helmet.hsts());
42 | // app.use(helmet.ieNoOpen());
43 | // app.use(helmet.noSniff());
44 | // app.use(helmet.originAgentCluster());
45 | // app.use(helmet.permittedCrossDomainPolicies());
46 | // app.use(helmet.referrerPolicy());
47 | // app.use(helmet.xssFilter());
48 |
49 | const limiter = rateLimiter({
50 | windowMs: 1 * 60 * 1000,
51 | max: 120, // limit each IP to 120 requests per minute
52 | });
53 |
54 | const speedLimiter = slowDown({
55 | windowMs: 1 * 60 * 1000,
56 | delayAfter: 100, // allow 100 requests per minute,
57 | delayMs: 1000, // adding 1000ms of delay per request above 100
58 | // request # 101 is delayed by 1000ms
59 | // request # 102 is delayed by 2000ms
60 | });
61 |
62 | app.use(speedLimiter);
63 | app.use(limiter);
64 | }
65 |
66 | module.exports = { secure };
67 |
--------------------------------------------------------------------------------
/ch2/part8/server/middlewares/security.js:
--------------------------------------------------------------------------------
1 | const { disablePoweredBy } = require("./disablePoweredBy");
2 |
3 | const cors = require("cors");
4 | const helmet = require("helmet");
5 | const rateLimiter = require("express-rate-limit");
6 | const slowDown = require("express-slow-down");
7 |
8 | function secure(app) {
9 | app.use(disablePoweredBy);
10 |
11 | app.use(
12 | cors({
13 | origin: ["https://example.ru", "http://localhost:3001"],
14 | })
15 | );
16 |
17 | app.use(
18 | helmet({
19 | contentSecurityPolicy: {
20 | useDefaults: true,
21 | directives: {
22 | scriptSrc: [
23 | "'self'",
24 | "'unsafe-inline'",
25 | "https://cdn.jsdelivr.net",
26 | "https://code.jquery.com",
27 | ],
28 | },
29 | },
30 | })
31 | );
32 |
33 | // app.use(helmet.contentSecurityPolicy());
34 | // app.use(helmet.crossOriginEmbedderPolicy());
35 | // app.use(helmet.crossOriginOpenerPolicy());
36 | // app.use(helmet.crossOriginResourcePolicy());
37 | // app.use(helmet.dnsPrefetchControl());
38 | // app.use(helmet.expectCt());
39 | // app.use(helmet.frameguard());
40 | // app.use(helmet.hidePoweredBy());
41 | // app.use(helmet.hsts());
42 | // app.use(helmet.ieNoOpen());
43 | // app.use(helmet.noSniff());
44 | // app.use(helmet.originAgentCluster());
45 | // app.use(helmet.permittedCrossDomainPolicies());
46 | // app.use(helmet.referrerPolicy());
47 | // app.use(helmet.xssFilter());
48 |
49 | const limiter = rateLimiter({
50 | windowMs: 1 * 60 * 1000,
51 | max: 120, // limit each IP to 120 requests per minute
52 | });
53 |
54 | const speedLimiter = slowDown({
55 | windowMs: 1 * 60 * 1000,
56 | delayAfter: 100, // allow 100 requests per minute,
57 | delayMs: 1000, // adding 1000ms of delay per request above 100
58 | // request # 101 is delayed by 1000ms
59 | // request # 102 is delayed by 2000ms
60 | });
61 |
62 | app.use(speedLimiter);
63 | app.use(limiter);
64 | }
65 |
66 | module.exports = { secure };
67 |
--------------------------------------------------------------------------------
/ch2/part9/server/middlewares/security.js:
--------------------------------------------------------------------------------
1 | const { disablePoweredBy } = require("./disablePoweredBy");
2 |
3 | const cors = require("cors");
4 | const helmet = require("helmet");
5 | const rateLimiter = require("express-rate-limit");
6 | const slowDown = require("express-slow-down");
7 |
8 | function secure(app) {
9 | app.use(disablePoweredBy);
10 |
11 | app.use(
12 | cors({
13 | origin: ["https://example.ru", "http://localhost:3001"],
14 | })
15 | );
16 |
17 | app.use(
18 | helmet({
19 | contentSecurityPolicy: {
20 | useDefaults: true,
21 | directives: {
22 | scriptSrc: [
23 | "'self'",
24 | "'unsafe-inline'",
25 | "https://cdn.jsdelivr.net",
26 | "https://code.jquery.com",
27 | ],
28 | },
29 | },
30 | })
31 | );
32 |
33 | // app.use(helmet.contentSecurityPolicy());
34 | // app.use(helmet.crossOriginEmbedderPolicy());
35 | // app.use(helmet.crossOriginOpenerPolicy());
36 | // app.use(helmet.crossOriginResourcePolicy());
37 | // app.use(helmet.dnsPrefetchControl());
38 | // app.use(helmet.expectCt());
39 | // app.use(helmet.frameguard());
40 | // app.use(helmet.hidePoweredBy());
41 | // app.use(helmet.hsts());
42 | // app.use(helmet.ieNoOpen());
43 | // app.use(helmet.noSniff());
44 | // app.use(helmet.originAgentCluster());
45 | // app.use(helmet.permittedCrossDomainPolicies());
46 | // app.use(helmet.referrerPolicy());
47 | // app.use(helmet.xssFilter());
48 |
49 | const limiter = rateLimiter({
50 | windowMs: 1 * 60 * 1000,
51 | max: 120, // limit each IP to 120 requests per minute
52 | });
53 |
54 | const speedLimiter = slowDown({
55 | windowMs: 1 * 60 * 1000,
56 | delayAfter: 100, // allow 100 requests per minute,
57 | delayMs: 1000, // adding 1000ms of delay per request above 100
58 | // request # 101 is delayed by 1000ms
59 | // request # 102 is delayed by 2000ms
60 | });
61 |
62 | app.use(speedLimiter);
63 | app.use(limiter);
64 | }
65 |
66 | module.exports = { secure };
67 |
--------------------------------------------------------------------------------
/ch2/part9/client/src/Home.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Button,
3 | Container,
4 | FormControl,
5 | FormErrorMessage,
6 | FormLabel,
7 | Heading,
8 | Input,
9 | Stack,
10 | useToast,
11 | } from "@chakra-ui/react";
12 | import { useCallback } from "react";
13 | import { useForm } from "react-hook-form";
14 |
15 | interface ShortenerInfo {
16 | alias: string;
17 | link: string;
18 | }
19 |
20 | export function Home() {
21 | const {
22 | handleSubmit,
23 | register,
24 | reset,
25 | formState: { errors, isSubmitting },
26 | } = useForm();
27 | const toast = useToast();
28 |
29 | const onSubmit = useCallback(async (values: ShortenerInfo) => {
30 | const response = await fetch("http://localhost:3000/alias", {
31 | method: "POST",
32 | headers: {
33 | Accept: "application/json",
34 | "Content-Type": "application/json",
35 | },
36 | body: JSON.stringify({ alias: values.alias, link: values.link }),
37 | });
38 |
39 | if (response.ok) {
40 | reset();
41 |
42 | toast({
43 | title: "Alias created!",
44 | description: `Alias "${values.alias}" now redirects to ${values.link}`,
45 | status: "success",
46 | duration: 3000,
47 | isClosable: true,
48 | });
49 | } else {
50 | toast({
51 | title: "Error",
52 | description: await response.text() || 'Unknown error...',
53 | status: "error",
54 | duration: 3000,
55 | isClosable: true,
56 | });
57 | }
58 | }, []);
59 |
60 | return (
61 |
62 |
106 |
107 | );
108 | }
109 |
--------------------------------------------------------------------------------
/ch2/part8/client/src/App.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Button,
3 | Container,
4 | FormControl,
5 | FormErrorMessage,
6 | FormLabel,
7 | Heading,
8 | Input,
9 | Stack,
10 | useToast,
11 | } from "@chakra-ui/react";
12 | import { useCallback } from "react";
13 | import { useForm } from "react-hook-form";
14 |
15 | interface ShortenerInfo {
16 | alias: string;
17 | link: string;
18 | }
19 |
20 | function App() {
21 | const {
22 | handleSubmit,
23 | register,
24 | reset,
25 | formState: { errors, isSubmitting },
26 | } = useForm();
27 | const toast = useToast();
28 |
29 | const onSubmit = useCallback(async (values: ShortenerInfo) => {
30 | const response = await fetch("http://localhost:3000/alias", {
31 | method: "POST",
32 | headers: {
33 | Accept: "application/json",
34 | "Content-Type": "application/json",
35 | },
36 | body: JSON.stringify({ alias: values.alias, link: values.link }),
37 | });
38 |
39 | if (response.ok) {
40 | reset();
41 |
42 | toast({
43 | title: "Alias created!",
44 | description: `Alias "${values.alias}" now redirects to ${values.link}`,
45 | status: "success",
46 | duration: 3000,
47 | isClosable: true,
48 | });
49 | } else {
50 | toast({
51 | title: "Error",
52 | description: await response.text() || 'Unknown error...',
53 | status: "error",
54 | duration: 3000,
55 | isClosable: true,
56 | });
57 | }
58 | }, []);
59 |
60 | return (
61 |
62 |
106 |
107 | );
108 | }
109 |
110 | export default App;
111 |
--------------------------------------------------------------------------------