bondarenko_max_lab_3 is done

This commit is contained in:
maxnes3 2024-11-25 02:10:37 +04:00
parent 131dc39f6c
commit 9ff5b267bc
19 changed files with 691 additions and 0 deletions

View File

@ -0,0 +1,2 @@
# Лабораторная работа 3 - REST API, Gateway и синхронный обмен между микросервисами
### ПИбд-42 || Бондаренко Максим

View File

@ -0,0 +1 @@
PORT=3000

View File

@ -0,0 +1,20 @@
# Используем базовый образ Node.js
FROM node:14
# Создаем рабочую директорию в контейнере
WORKDIR /app
# Копируем package.json и package-lock.json
COPY package*.json ./
# Устанавливаем зависимости
RUN npm install
# Копируем исходный код
COPY . .
# Указываем порт, который будет слушать приложение
EXPOSE 3000
# Команда для запуска приложения
CMD ["npm", "start"]

View File

@ -0,0 +1,14 @@
{
"name": "authors",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js"
},
"dependencies": {
"express": "^4.17.1",
"swagger-jsdoc": "^6.1.0",
"swagger-ui-express": "^4.3.0",
"uuid": "^8.3.2"
}
}

View File

@ -0,0 +1,50 @@
const { Author, authors } = require('../models/authorModel');
const getAuthors = (req, res) => {
res.json(authors);
};
const getAuthorById = (req, res) => {
const author = authors.find(a => a.uuid === req.params.uuid);
if (author) {
res.json(author);
} else {
res.status(404).send('Author not found');
}
};
const createAuthor = (req, res) => {
const { name, birthdate } = req.body;
const newAuthor = new Author(name, birthdate);
authors.push(newAuthor);
res.status(201).json(newAuthor);
};
const updateAuthor = (req, res) => {
const author = authors.find(a => a.uuid === req.params.uuid);
if (author) {
author.name = req.body.name || author.name;
author.birthdate = req.body.birthdate || author.birthdate;
res.json(author);
} else {
res.status(404).send('Author not found');
}
};
const deleteAuthor = (req, res) => {
const authorIndex = authors.findIndex(a => a.uuid === req.params.uuid);
if (authorIndex !== -1) {
authors.splice(authorIndex, 1);
res.status(204).send();
} else {
res.status(404).send('Author not found');
}
};
module.exports = {
getAuthors,
getAuthorById,
createAuthor,
updateAuthor,
deleteAuthor
};

View File

@ -0,0 +1,15 @@
const express = require('express');
const bodyParser = require('body-parser');
const authorRoutes = require('./routes/authorRoutes');
const setupSwagger = require('./swagger');
const app = express();
const port = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use('/authors', authorRoutes);
setupSwagger(app);
app.listen(port, () => {
console.log(`Authors service is running on port ${port}`);
});

View File

@ -0,0 +1,16 @@
const { v4: uuidv4 } = require('uuid');
class Author {
constructor(name, birthdate) {
this.uuid = uuidv4();
this.name = name;
this.birthdate = birthdate;
}
}
const authors = [];
module.exports = {
Author,
authors
};

View File

@ -0,0 +1,166 @@
const express = require('express');
const {
getAuthors,
getAuthorById,
createAuthor,
updateAuthor,
deleteAuthor
} = require('../controllers/authorController');
const router = express.Router();
/**
* @swagger
* components:
* schemas:
* Author:
* type: object
* required:
* - name
* - birthdate
* properties:
* uuid:
* type: string
* description: The auto-generated UUID of the author
* name:
* type: string
* description: The name of the author
* birthdate:
* type: string
* format: date
* description: The birthdate of the author
* example:
* uuid: d5fE_asz
* name: J.K. Rowling
* birthdate: 1965-07-31
*/
/**
* @swagger
* tags:
* name: Authors
* description: The authors managing API
*/
/**
* @swagger
* /authors:
* get:
* summary: Returns the list of all the authors
* tags: [Authors]
* responses:
* 200:
* description: The list of the authors
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/Author'
*/
router.get('/', getAuthors);
/**
* @swagger
* /authors/{uuid}:
* get:
* summary: Get the author by id
* tags: [Authors]
* parameters:
* - in: path
* name: uuid
* schema:
* type: string
* required: true
* description: The author id
* responses:
* 200:
* description: The author description by id
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Author'
* 404:
* description: The author was not found
*/
router.get('/:uuid', getAuthorById);
/**
* @swagger
* /authors:
* post:
* summary: Create a new author
* tags: [Authors]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Author'
* responses:
* 201:
* description: The author was successfully created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Author'
* 500:
* description: Some server error
*/
router.post('/', createAuthor);
/**
* @swagger
* /authors/{uuid}:
* put:
* summary: Update the author by the id
* tags: [Authors]
* parameters:
* - in: path
* name: uuid
* schema:
* type: string
* required: true
* description: The author id
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Author'
* responses:
* 200:
* description: The author was updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Author'
* 404:
* description: The author was not found
* 500:
* description: Some error happened
*/
router.put('/:uuid', updateAuthor);
/**
* @swagger
* /authors/{uuid}:
* delete:
* summary: Remove the author by id
* tags: [Authors]
* parameters:
* - in: path
* name: uuid
* schema:
* type: string
* required: true
* description: The author id
* responses:
* 204:
* description: The author was deleted
* 404:
* description: The author was not found
*/
router.delete('/:uuid', deleteAuthor);
module.exports = router;

View File

@ -0,0 +1,22 @@
const swaggerJSDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'Authors API',
version: '1.0.0',
description: 'API for managing authors',
},
},
apis: ['./src/routes/*.js'],
};
const swaggerSpec = swaggerJSDoc(options);
const setupSwagger = (app) => {
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
};
module.exports = setupSwagger;

View File

@ -0,0 +1 @@
PORT=3001

View File

@ -0,0 +1,20 @@
# Используем базовый образ Node.js
FROM node:14
# Создаем рабочую директорию в контейнере
WORKDIR /app
# Копируем package.json и package-lock.json
COPY package*.json ./
# Устанавливаем зависимости
RUN npm install
# Копируем исходный код
COPY . .
# Указываем порт, который будет слушать приложение
EXPOSE 3001
# Команда для запуска приложения
CMD ["npm", "start"]

View File

@ -0,0 +1,16 @@
{
"name": "books",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js"
},
"dependencies": {
"express": "^4.17.1",
"swagger-jsdoc": "^6.1.0",
"swagger-ui-express": "^4.3.0",
"axios": "^0.21.1",
"uuid": "^8.3.2"
}
}

View File

@ -0,0 +1,72 @@
const axios = require('axios');
const { Book, books } = require('../models/bookModel');
const getBooks = (req, res) => {
res.json(books);
};
const getBookById = async (req, res) => {
const book = books.find(b => b.uuid === req.params.uuid);
if (book) {
try {
const authorResponse = await axios.get(`http://authors:3000/authors/${book.authorUuid}`);
book.authorInfo = authorResponse.data;
res.json(book);
} catch (error) {
res.status(500).send('Error fetching author information');
}
} else {
res.status(404).send('Book not found');
}
};
const createBook = async (req, res) => {
const { author, title, year, authorUuid } = req.body;
try {
const authorResponse = await axios.get(`http://authors:3000/authors/${authorUuid}`);
if (!authorResponse.data) {
return res.status(404).send('Author not found');
}
const newBook = new Book(author, title, year, authorUuid);
books.push(newBook);
res.status(201).json(newBook);
} catch (error) {
if (error.response && error.response.status === 404) {
res.status(404).send('Author not found');
} else {
res.status(500).send('Error creating book');
}
}
};
const updateBook = (req, res) => {
const book = books.find(b => b.uuid === req.params.uuid);
if (book) {
book.author = req.body.author || book.author;
book.title = req.body.title || book.title;
book.year = req.body.year || book.year;
book.authorUuid = req.body.authorUuid || book.authorUuid;
res.json(book);
} else {
res.status(404).send('Book not found');
}
};
const deleteBook = (req, res) => {
const bookIndex = books.findIndex(b => b.uuid === req.params.uuid);
if (bookIndex !== -1) {
books.splice(bookIndex, 1);
res.status(204).send();
} else {
res.status(404).send('Book not found');
}
};
module.exports = {
getBooks,
getBookById,
createBook,
updateBook,
deleteBook
};

View File

@ -0,0 +1,15 @@
const express = require('express');
const bodyParser = require('body-parser');
const bookRoutes = require('./routes/bookRoutes');
const setupSwagger = require('./swagger');
const app = express();
const port = process.env.PORT || 3001;
app.use(bodyParser.json());
app.use('/books', bookRoutes);
setupSwagger(app);
app.listen(port, () => {
console.log(`Books service is running on port ${port}`);
});

View File

@ -0,0 +1,18 @@
const { v4: uuidv4 } = require('uuid');
class Book {
constructor(author, title, year, authorUuid) {
this.uuid = uuidv4();
this.author = author;
this.title = title;
this.year = year;
this.authorUuid = authorUuid;
}
}
const books = [];
module.exports = {
Book,
books
};

View File

@ -0,0 +1,175 @@
const express = require('express');
const {
getBooks,
getBookById,
createBook,
updateBook,
deleteBook
} = require('../controllers/bookController');
const router = express.Router();
/**
* @swagger
* components:
* schemas:
* Book:
* type: object
* required:
* - author
* - title
* - year
* - authorUuid
* properties:
* uuid:
* type: string
* description: The auto-generated UUID of the book
* author:
* type: string
* description: The author of the book
* title:
* type: string
* description: The title of the book
* year:
* type: integer
* description: The year the book was published
* authorUuid:
* type: string
* description: The UUID of the author
* example:
* uuid: d5fE_asz
* author: J.K. Rowling
* title: Harry Potter
* year: 1997
* authorUuid: d5fE_asz
*/
/**
* @swagger
* tags:
* name: Books
* description: The books managing API
*/
/**
* @swagger
* /books:
* get:
* summary: Returns the list of all the books
* tags: [Books]
* responses:
* 200:
* description: The list of the books
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/Book'
*/
router.get('/', getBooks);
/**
* @swagger
* /books/{uuid}:
* get:
* summary: Get the book by id
* tags: [Books]
* parameters:
* - in: path
* name: uuid
* schema:
* type: string
* required: true
* description: The book id
* responses:
* 200:
* description: The book description by id
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Book'
* 404:
* description: The book was not found
*/
router.get('/:uuid', getBookById);
/**
* @swagger
* /books:
* post:
* summary: Create a new book
* tags: [Books]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Book'
* responses:
* 201:
* description: The book was successfully created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Book'
* 500:
* description: Some server error
*/
router.post('/', createBook);
/**
* @swagger
* /books/{uuid}:
* put:
* summary: Update the book by the id
* tags: [Books]
* parameters:
* - in: path
* name: uuid
* schema:
* type: string
* required: true
* description: The book id
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Book'
* responses:
* 200:
* description: The book was updated
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Book'
* 404:
* description: The book was not found
* 500:
* description: Some error happened
*/
router.put('/:uuid', updateBook);
/**
* @swagger
* /books/{uuid}:
* delete:
* summary: Remove the book by id
* tags: [Books]
* parameters:
* - in: path
* name: uuid
* schema:
* type: string
* required: true
* description: The book id
* responses:
* 204:
* description: The book was deleted
* 404:
* description: The book was not found
*/
router.delete('/:uuid', deleteBook);
module.exports = router;

View File

@ -0,0 +1,22 @@
const swaggerJSDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'Books API',
version: '1.0.0',
description: 'API for managing books',
},
},
apis: ['./src/routes/*.js'],
};
const swaggerSpec = swaggerJSDoc(options);
const setupSwagger = (app) => {
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
};
module.exports = setupSwagger;

View File

@ -0,0 +1,21 @@
version: '3.7'
services:
authors:
build:
context: ./authors
ports:
- "3000:3000"
books:
build:
context: ./books
ports:
- "3001:3001"
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf

View File

@ -0,0 +1,25 @@
events {
worker_connections 1024;
}
http {
upstream authors_service {
server authors:3000;
}
upstream books_service {
server books:3001;
}
server {
listen 80;
location /authors {
proxy_pass http://authors_service;
}
location /books {
proxy_pass http://books_service;
}
}
}