Рубрики
Uncategorized

«И для этого интервью создайте мне пользовательский маршрутизатор REST-API для веб-применения»

Ладони потные, слабые колени, руки тяжелые, на его патагуччи уже рвота Это т … Tagged с узлом, AWS, Terraform, DevOps.

Ладони потные, слабые колени, руки тяжелые,

У его Патагуччи уже есть рвота

Это те виды технических вопросов интервью, которые мои друзья говорили мне о том, что это заставило бы меня заморозить. То, как его сформулировано, кажется такой большой работой и скрытой сложности. И я уверен, что есть — если вы действительно хотели выбить его из парка — но сегодня, примерно через 4 часа в задаче, которая я нашел более раздражающим, чем сложным, я понял, что сделаю именно это (вроде как , на очень низком уровне).

Источник изображения заголовка

T, почему вы создали пользовательский маршрутизатор?

Это великий Вопрос, я рад, что вы спросили 🕺🏽.

ТАК

В настоящее время я работаю над проектом, где мы создаем кучу детских API для CRUD (создать, извлекать, обновить, удалить) некоторые вещи из таблиц DynamoDB. Из кучи причин, не в последнюю очередь, включая тот факт, что Я единственный инженер В этом проекте — я пытаюсь Выиграйте продажи, зарабатывайте бонусы и зарабатывайте деньги Двигайтесь быстро и поддерживайте как можно меньше «живой инфраструктуры».

Из -за этого я пришел к следующим выводам/решениям о том, как я буду продолжать:

Устал 😰

  • Запуск node.js WebServer (и связанный с этим инфраю и управление) для эффективного брокера CRUD запросы в DynamoDB?

Проводной ☕

  • Настройка шлюза AWS API, который запустил бы лямбду, чтобы разорвать необходимые вещи из DynamoDB Проводной Мы $ erverle $$ baaaabyyyyyyyyyyyyyyyyyyyyyy

Вдохновлен ✨

В любом случае, TL: DR на этом состоит в том, что будет Gateway API, который получает HTTP -запросы, а затем отправляет их на функцию лямбды, которая решает, как справиться с запросом, прежде чем поднять взаимодействие с DynamoDB.

У меня есть один набор ресурсов Проекты Это существует в таблице DynamoDB (в одном Проекты ), и моя лямбда должна быть в состоянии прослушать запрос и получить вещи от DynamoDB.

От съемки моего оригинального синего отпечатка выше, вы можете подумать:

Это кажется достаточно легко.

И ты был бы прав, Если Мне когда -либо приходилось иметь дело с одной сущностью проекты . По мере продолжения проекта, теперь у меня есть вторая организация, чтобы иметь дело с: Статус (es?) И еще больше скоро появится.

Первоначально я подумал:

1 лямбда на ресурс. /ресурсы пойдет в Ресурсы-ламбда и /статус пойдет в Статус-ламбда Анкет

Однако этот подход приводит к нескольким вопросам:

  • Для каждой конечной точки/лямбда вам необходимо создать 3x ссылки на шлюз API
  • Для каждой конечной точки/лямбды вам нужно сделать больше жилья.
  • Развертывания будут раздражать, потому что мне нужно было бы обновить конкретную лямбду или несколько лямбдас для реализации одной функции в будущем (то есть, если мне нужно было добавить новое поле в статус , который использует проекты )

В конечном итоге я решил:

Нет, мы собираемся попросить API Gateway отправить все (прокси) трафик в один лямбда 1 лямбда, чтобы управлять ими всеми (как прокси -ресурс), а затем Lambda может решить, как с этим справиться.

Вот почему мне нужно было создать маршрутизатор, чтобы моя функция Lambda могла выяснить, что его просят сделать, прежде чем выполнять соответствующий ответ. Например, это должно было бы справиться:

  • Получить/проекты — Получите мне все проекты в базе данных.
  • Get/Projects: имя — Получите мне подробности об одном проекте.
  • Get/status — Получите мне все записи статуса в базе данных.
  • Get/status/: имя — Получите мне статус одного проекта в базе данных.

Работая с узлом (и специально выражающим) раньше, я знал, что существует способ указать такие маршруты :

app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params)
})

И аналогично Lambda, для этого случая, казалось, существовал определенный модуль узлов:

AWS-Lambda-Router

import * as router from 'aws-lambda-router'

export const handler = router.handler({
    proxyIntegration: {
        routes: [
            {
                // request-path-pattern with a path variable:
                path: '/article/:id',
                method: 'GET',
                // we can use the path param 'id' in the action call:
                action: (request, context) => {
                    return "You called me with: " + request.paths.id;
                }
            },
            {
                // request-path-pattern with a path variable in Open API style:
                path: '/section/{id}',
                method: 'GET',
                // we can use the path param 'id' in the action call:
                action: (request, context) => {
                    return "You called me with: " + request.paths.id;
                }
            }
        ]
    }
})

Однако, к сожалению, поддержка прокси -пути все еще остается WIP:( Казалось бы, это подразумевает, что ❌ я не смог бы получить на параметрах маршрута, как имя в Get/Projects/: имя Womp Womp

Также раздражает, что если вы используете пользовательские узлы-модулы, вам нужно загружать его как ZIP каждый раз (в отличие от возможности кодировать/тестировать в прямом эфире, если вы используете Native/Vanilla Node).

Ну, ЛАБДА, я думаю, что это только вы (-р параметры события) и я на данный момент.

Это просто означало бы, что мне нужно создать свой собственный маршрутизатор, и, к счастью, очевидно? , событие Полезная нагрузка, которая передается в функцию лямбды с помощью API Gateway Содержит всю информацию, которая нам может понадобиться.

В частности, все вы Действительно Потребность в маршрутизаторе — это три вещи (для начала);

  • Метод http: Получить , Пост так далее
  • Ресурс: Проекты
  • статус Params (a.k.a Keys):

Как только я извлек эти произведения из Lambda, выполнив следующее:

let method = event.httpMethod
let resource = event.path.split("/")[1]
let key = event.path.split("/")[2]

Фактическая логика маршрутизатора была не слишком сложной. И я думаю, как в техническом интервью — я придумал 2 «решения».

V1 — включите 1, добавьте больше деталей внутри

let method = event.httpMethod
let resource = event.path.split("/")[1]
let key = event.path.split("/")[2]

switch (resource) {
      case "projects":
        if (key == undefined) {
          body = await dynamo.scan({ TableName: PROJECTS_DB_TABLE }).promise();
        } else {
          let name = key;
          body = await db_get("projects",name)
        }
        break;
      case "status":
        break;
      default:
        body = {
          defaultCase: "true",
          path: event.path,
          resource: event.path.split("/")[1],
        };
        break;
    }

Этот подход был крутым, потому что он позволил мне использовать дорожка в качестве основного селектора, а затем кодируйте логику для необходимых методов по мере их появления.

Однако. Это не … Смотри Отлично. На первый взгляд он выглядит грубым, запутанным, и это просто с одним ресурсом и одним методом. Во -вторых, для любых новых инженеров, приходящих на борту — это не сразу кажется маршрутизатором по сравнению с любой предыдущей работой, которую они могли выполнить.

Возвращаясь к чертежной доске и желая приблизиться к «золотому стандарту», к которому я привык, как в Express-Router.

Я хотел придумать что -то, что просто указало:

  • Вот маршрут, с которым нам нужно справиться
    • Вот это связанный обработчик.

Имея это в виду, я придумал

V2 — Фильтр на 2 условиях, добавьте больше методов по мере их возникновения

let method = event.httpMethod
let resource = event.path.split("/")[1]
let key = event.path.split("/")[2]

 if (method == "GET" && resource == "projects") {
      body = await db_get(dynamo, "projects", key)
    }
else if (method == "GET" && resource == "status") {
    body = await db_get(dynamo, "status", key)
}
else {
  body = { method, resource, key, message: "not supported at this time" }
}

Мне это нравится, потому что это самое близкое, что я смог добраться до экспресс-маркировки:

app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params)
})

И имеет преимущество в том, чтобы быть кратким и гораздо более узнаваемым в качестве маршрутизатора на первом воздействии.

Вещи, которые я улучшаю

Я, вероятно, хотел бы сделать гораздо большую уборку для настоящего интервью «Real» маршрутизатора, но это было все еще крутое упражнение. Некоторые определенные вещи, которые я бы хотел добавить/обрабатывать:

  • Get-Me-All Корпус обрабатывается путем проверки неопределенного ключа. Это, вероятно, можно охранять к лучшему.
  • В настоящее время нет никакой защиты от кого -то, добавляющего более чем параметр 1 -го уровня (то есть /projects/name/something/else все равно будет отправлен в DB. Это не здорово.
  • Это все в гигантском заявлении IF-ELSE ?? Это не кажется великолепным.
  • Ограничения: нет способа сделать промежуточное программное обеспечение, аут, трассировку и кучу вещей, которые вы сможете сделать с экспресс-маршрутизатором (и другими маршрутизаторами)

Вывод

Маршрутизаторы-это просто гигантские заявления IF-ELSE? Idk — это было весело, хотя.

Оригинал: «https://dev.to/tratnayake/and-for-this-interview-build-me-a-custom-router-for-a-web-application-30l1»