[Node.JS, Serverless] Запускаем приложение на Express.js в Yandex Cloud Functions
    
    
        
    
    
    
    
            
    
        
            
                
                                    
                
                                    
                
                    
                
            
        
    
    
        
            
                
                
                    
                         
                         
                       
                    
                        Автор 
                        Сообщение 
                    
                                        
                        
                            
                                
                                
                                                                                                            news_bot ®
                                                                        
                                                                                                                                                
                                                                            
                                                                                                                
                                            Стаж: 7 лет 8 месяцев                                        
                                                                                                                
                                            Сообщений: 27286                                        
                                                                                                                                                
                                                             
                            
                                
                             
                         
                        
                            
                                
                                    
                                        
                                        
 
Node.js — удобная масштабируемая серверная платформа для работы с JavaScript. С помощью нее и различных поддерживаемых фреймворков, таких как Express, Connect или Koa, можно создавать полноценные приложения.   Если идти по пути упрощения администрирования, возникает желание загрузить приложение в Yandex Cloud Functions и вызывать его из облака. К сожалению, пока нельзя просто так взять и запустить в облаке приложение, написанное на любом популярном node.js-фреймворке. Фреймворки пишут ответ в сокет HTTP(S). Рантайм функций ожидает получить от пользовательского кода функции объект определенного содержания.   
{
    "statusCode": <HTTP код ответа>,
    "headers": <словарь со строковыми значениями HTTP-заголовков>,
    "multiValueHeaders": <словарь со списками значений HTTP-заголовков>,
    "body": "<содержимое ответа>",
    "isBase64Encoded": <true или false>
}
«Из коробки» это работать не будет, но можно научить приложение возвращать ответ в ожидаемом формате. Разберем, как это сделать, на примере приложения Express.js с двумя эндпоинтами.  Создаем и запускаем новый проектСоздаем новую директорию и инициируем в ней новый проект:  
mkdir sample-app && cd sample-app
npm init -y
npm install express
touch 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 есть свой плагин, который позволяет деплоить функции. Из него пока нельзя развернуть еще один ключевой компонент системы — Yandex API Gateway, мы чуть позже сделаем это вручную через консоль. Устанавливаем Serverless Framework и плагин к нему: 
npm i -g serverless serverless-yandex-cloud
Далее создаем в проекте файл serverless.yaml с содержимым:   
service: sample-app
frameworkVersion: ">=1.1.0"
configValidationMode: off
provider:
  name: yandex-cloud
  runtime: nodejs12-preview
plugins:
  - serverless-yandex-cloud
package:
  exclude:
    - ./**
  include:
    - ./package.json
    - ./**/*.js
functions:
  express:
    # this is formatted as <FILENAME>.<HANDLER>
    handler: index.handler
    memory: 128
    timeout: 5
Деплоим функцию командой: 
serverless deploy 
Если сделать функцию публичной и вызвать ее по предложенному URL, передав путь /api/info , то в ответ мы получим следующую ошибку: 
$ curl 'https://functions.yandexcloud.net/%function-id%/api/info'
{"errorCode":400,"errorMessage":"Invalid functionID: /%function-id%/api/info",
"errorType":"ProxyIntegrationError"}
 необходима настройка API Gateway.  Создание API Gateway 
Спецификация должна соответствовать стандарту OpenAPI 3.0, для нашего простого API ее можно написать руками: 
openapi: 3.0.0
info:
  title: Sample API
  version: 1.0.0
paths:
  /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"}
Кстати, к API Gateway можно привязать свой домен. Как приязать домен — читайте в этом посте.  Новый параметр API Gateway Совсем недавно в API Gateway появилась возможность указать параметр вида {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 (строки 13–19 в примере ниже). 
 
 Пример готового скрипта можно скачать.  
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 на Yandex Cloud Functions по программе free tier: сервис не тарифицирует первый миллион вызовов функций и первые 10 ГБ×час выполнения функций. А любые вопросы о работе сервисов можно обсудить как с их пользователями, так и с их создателями в чате Yandex Serverless Ecosystem.  
===========
 Источник:
habr.com
===========
Похожие новости:
- [JavaScript, Angular, ReactJS] Only 39% of the functions in node_modules are unique in the default Angular project (перевод)
 
- [JavaScript, Angular, ReactJS] Только 39% функций в node_modules уникальны в дефолтном Angular проекте
 
- [JavaScript, Google Chrome, API, Google API] Content Indexing API: страницы, доступные в offline. Доклад с RamblerFront #9
 
- [Разработка веб-сайтов, JavaScript, Программирование, Совершенный код] Как выдать Золушку за принца и не сойти с ума. Паттерн Декоратор
 
- [JavaScript, Программирование, Go, TypeScript] Обзор Prisma ORM
 
- [CMS, Ненормальное программирование, JavaScript, API, Тестирование веб-сервисов] AEM Test Automation — Create Pages via HTTP Requests
 
- [JavaScript, Node.JS, TypeScript] Yarn 2  —  Устанавливаем и разбираемся
 
- [JavaScript, C, Rust, WebAssembly] Оптимизируем производительность: JavaScript (V8) vs AssemblyScript (WebAssembly) (перевод)
 
- [JavaScript, Разработка мобильных приложений, Разработка под Android, IT-компании] Google удалила IDE DroidScript из магазина Google Play якобы из-за зловреда и обвинила разработчиков в мошенничестве
 
- [Разработка веб-сайтов, JavaScript, VueJS] VueUse — обязательная библиотека для Vue 3
 
Теги для поиска: #_node.js, #_serverless, #_serverless, #_node.js, #_javascript, #_node.js, #_serverless
                                        
                                        
                                        
                                     
                                    
                                    
                                                                    
                                                                                             
                         
                        
                            
                                                                    
                                                             
                         
                    
                    
                
                
            
        
    
    
    
    
    
            
    
            
    
        
    
    
        
                        Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
    
    
        
        Текущее время: 04-Ноя 17:20
Часовой пояс: UTC + 5 
            
    
                
| Автор | Сообщение | 
|---|---|
| 
                                
                                
                                                                                                            news_bot ®
                                                                        
                                                                                                                                                 
                                                                            
                                                                                                                
                                            Стаж: 7 лет 8 месяцев                                          | 
                            |
                                ![]() Node.js — удобная масштабируемая серверная платформа для работы с JavaScript. С помощью нее и различных поддерживаемых фреймворков, таких как Express, Connect или Koa, можно создавать полноценные приложения. Если идти по пути упрощения администрирования, возникает желание загрузить приложение в Yandex Cloud Functions и вызывать его из облака. К сожалению, пока нельзя просто так взять и запустить в облаке приложение, написанное на любом популярном node.js-фреймворке. Фреймворки пишут ответ в сокет HTTP(S). Рантайм функций ожидает получить от пользовательского кода функции объект определенного содержания. { 
"statusCode": <HTTP код ответа>, "headers": <словарь со строковыми значениями HTTP-заголовков>, "multiValueHeaders": <словарь со списками значений HTTP-заголовков>, "body": "<содержимое ответа>", "isBase64Encoded": <true или false> } mkdir sample-app && cd sample-app 
npm init -y npm install express touch 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"} npm i --save serverless-http 
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); npm i -g serverless serverless-yandex-cloud 
service: sample-app 
frameworkVersion: ">=1.1.0" configValidationMode: off provider: name: yandex-cloud runtime: nodejs12-preview plugins: - serverless-yandex-cloud package: exclude: - ./** include: - ./package.json - ./**/*.js functions: express: # this is formatted as <FILENAME>.<HANDLER> handler: index.handler memory: 128 timeout: 5 serverless deploy  
$ curl 'https://functions.yandexcloud.net/%function-id%/api/info' 
{"errorCode":400,"errorMessage":"Invalid functionID: /%function-id%/api/info", "errorType":"ProxyIntegrationError"} ![]() Спецификация должна соответствовать стандарту OpenAPI 3.0, для нашего простого API ее можно написать руками: openapi: 3.0.0 
info: title: Sample API version: 1.0.0 paths: /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 $ curl 'https://%api-gw-id%.apigw.yandexcloud.net/api/info' 
{"application":"sample-app","version":"1"} 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 
 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); } =========== Источник: habr.com =========== Похожие новости: 
  | 
                        |
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
    Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 04-Ноя 17:20
Часовой пояс: UTC + 5