Русский
Русский
English
Статистика
Реклама

Запускаемприложение наExpress.js вYandexCloudFunctions

Node.jsудобнаямасштабируемая сервернаяплатформа для работы сJavaScript. С помощьюнееи различных поддерживаемыхфреймворков,таких как Express, Connect или Koa, можно создавать полноценные приложения.

Еслиидтипо пути упрощенияадминистрирования, возникает желаниезагрузитьприложение вYandexCloudFunctionsи вызывать его из облака.Ксожалению,пока нельзяпросто так взять и запуститьв облакеприложение, написанное на любом популярномnode.js-фреймворке.Фреймворкипишут ответвсокетHTTP(S).Рантаймфункций ожидает получить от пользовательского кода функции объект определенного содержания.

{         "statusCode": <HTTP код ответа>,    "headers": <словарь со строковыми значениями HTTP-заголовков>,    "multiValueHeaders": <словарь со списками значений HTTP-заголовков>,    "body": "<содержимое ответа>",    "isBase64Encoded": <true или false> }

Из коробкиэто работать не будет, но можно научить приложение возвращать ответ в ожидаемом формате.Разберем,как это сделать,на примереприложенияExpress.jsс двумяэндпоинтами.

Создаем и запускаем новый проект

Создаемновую директорию и инициируем в ней новый проект:

mkdir sample-app && cd sample-appnpm init -ynpm install expresstouch index.js

Далее вindex.jsдобавляем следующий код:

const express = require('express');const app = express();app.use(express.urlencoded({ extended: true }));app.use(express.json());app.get('/api/info', (req, res) => {    res.send({ application: 'sample-app', version: '1.0' });});app.post('/api/v1/getback', (req, res) => {    res.send({ ...req.body });});app.listen(3000, () => console.log(`Listening on: 3000`)); 

Запускаем проект ипроверяем, чтоприходятожидаемые ответы:

$ curl 'http://localhost:3000/api/info'{"application":"sample-app","version":"1"}

АдаптируемпроектподServerless

Интегрируеммодуль serverless-http:

npm i --save serverless-http

Это универсальныйвраппер, онподдерживает не толькоExpress, но иConnect,Koa,restana, а также экспериментально другиефреймворки:Sails,Hapi,Fastify,Restify,PolkaиLoopBack.

Затеммодифицируем наш пример.Заменяемзапуск сервера напорте3000экспортом функции-обработчика, которая будет вызыватьсяserverless-рантаймомоблака:

const express = require('express');const app = express();const serverless = require('serverless-http');app.use(express.urlencoded({ extended: true }));app.use(express.json());app.get('/api/info', (req, res) => {    res.send({ application: 'sample-app', version: '1.0' });});app.post('/api/v1/getback', (req, res) => {    res.send({ ...req.body });});//app.listen(3000, () => console.log(`Listening on: 3000`)); module.exports.handler = serverless(app);

Теперь наше приложение готово к запуску воблаке.

Развертываем приложение в облаке

Для того чтобы развернуть код в облаке,проще всего воспользоваться утилитойserverless. УYandex.Cloudестьсвойплагин,который позволяетдеплоитьфункции.Из него пока нельзя развернуть еще один ключевой компонент системы YandexAPIGateway,мычуть позже сделаем это вручнуючерез консоль.

УстанавливаемServerlessFrameworkи плагин к нему:

npm i -g serverless serverless-yandex-cloud 

Далее создаем в проектефайлserverless.yamlс содержимым:

service: sample-appframeworkVersion: ">=1.1.0"configValidationMode: offprovider:  name: yandex-cloud  runtime: nodejs12-previewplugins:  - serverless-yandex-cloudpackage:  exclude:    - ./**  include:    - ./package.json    - ./**/*.jsfunctions:  express:    # this is formatted as <FILENAME>.<HANDLER>    handler: index.handler    memory: 128    timeout: 5

Деплоимфункцию командой:

serverlessdeploy

Еслисделатьфункцию публичной и вызвать ее по предложенному URL, передав путь/api/info , то в ответ мы получим следующую ошибку:

$ curl 'https://functions.yandexcloud.net/%function-id%/api/info'{"errorCode":400,"errorMessage":"Invalid functionID: /%function-id%/api/info","errorType":"ProxyIntegrationError"}

необходима настройка APIGateway.

Создание APIGateway

Спецификация должна соответствоватьстандартуOpenAPI3.0, для нашего простого APIееможнонаписатьруками:

openapi: 3.0.0info:  title: Sample API  version: 1.0.0paths:  /api/info:    get:      responses:        '200':          description: Ok      x-yc-apigateway-integration:        type: cloud_functions        function_id: %function_id%        tag: $latest        service_account_id: %service_account_id%  /api/v1/getback:    post:      responses:        '200':          description: Ok          content:            application/json:              schema:                $ref: '#/components/schemas/Test'      requestBody:        required: false        content:          application/json:            schema:              $ref: '#/components/schemas/Test'      x-yc-apigateway-integration:        type: cloud_functions        function_id: %function_id%        tag: $latest        service_account_id: %service_account_id%components:  schemas:    Test:      type: object

Не забудьтепоменять%function_id%и%service_account_id%на ваши значения. У сервисного аккаунта должна быть рольserverless.functions.invokerиливыше, если вы оставили функцию без публичного доступа.

Вболее сложныхслучаяхможно попробовать сгенерироватьспецификациюOpenAPIна основе уже имеющегося кода API. Для этогоподойдетexpress-oas-generator.

Теперь наше приложение работает идоступно по URL.

$ curl 'https://%api-gw-id%.apigw.yandexcloud.net/api/info'{"application":"sample-app","version":"1"}

Кстати,кAPIGatewayможно привязать свой домен.Какприязатьдоменчитайтев этомпосте.

Новый параметрAPIGateway

Совсем недавно вAPIGatewayпоявилась возможность указать параметр вида{param+}.Вэтом случае будутматчитьсяи вложенные пути.

paths:  /api/{proxy+}:    get:      x-yc-apigateway-integration:        type: cloud_functions        function_id: d4e***        tag: $latest        service_account_id: aje***      responses:        200:          description: Ok      parameters:        - explode: true          in: path          name: proxy          required: true          schema:            type: string          style: simple

Впервом параметре функцииeventвпропертиpathбудет лежатьзначениевида/api/%7Bproxy+%7Dи роутерExpress.jsбудет ломаться.

Решения как минимум два:

  • написать честныйproviderдляYandex.Cloudпо образу того,что сейчас есть дляAWS;

  • пропатчитьобъектevent, положив вpathзначение изurl(строки1319в примере ниже).

Пример готового скриптаможноскачать.

const express = require('express');const serverless = require('serverless-http');const app = express();app.use(express.urlencoded({ extended: true }));app.use(express.json());app.get('/api/info', (req, res) => {    res.send({ application: 'sample-app', version: '1.0' });});app.get('/api/pet/:name?', (req, res) => {    res.send({ ...req.params });});module.exports.handler = (event, context) => {    const patchedEvent = {        ...event,        path: event.url,        originalPath: event.path,    }    return serverless(app)(patchedEvent, context);}

Вы можете бесплатнопопробовать запустить приложений Express.js на YandexCloudFunctionsпо программеfreetier:сервис не тарифицируетпервыймиллионвызовов функций и первые 10ГБчасвыполнения функций.А любые вопросыоработесервисов можно обсудить как с их пользователями, так ис ихсоздателямивчате Yandex Serverless Ecosystem.

Источник: habr.com
К списку статей
Опубликовано: 01.05.2021 10:11:55
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Node.js

Serverless

Javascript

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru