Небольшая AWS Lambda, которая пересылает GraphQL-запросы в GitHub API. Нужна, когда сервер не может достучаться до api.github.com напрямую.
Релей работает только на чтение. GitHub-токен хранится в переменных окружения функции, вызывающая сторона его не видит.
ваш сервер ──► Lambda Function URL ──► api.github.com/graphql
x-relay-token: <токен> Authorization: bearer <GITHUB_PAT>
- Принимается только
POST /graphql, на всё остальное ответ404. - Без верного
x-relay-tokenответ403({"error":"forbidden"}). Сам токен в GitHub не уходит. - Запросы с
mutationотклоняются с403({"error":"read-only relay"}). Словоmutationвнутри строк и комментариев не мешает. - Тело больше 256 КБ получает
413, невалидный JSON или тело безqueryполучают400. - Тело уходит в GitHub без изменений, а статус и тело ответа возвращаются как есть. Из заголовков ответа остаются только
content-typeиx-ratelimit-*. - Адрес фиксированный (
https://api.github.com/graphql), путь и параметры запроса на него не влияют, поэтому открытым прокси релей не станет. - Тела запросов не логируются и не сохраняются.
-
Создайте Lambda-функцию:
- runtime: Node.js 24 (
nodejs24.x) - handler:
index.handler - memory: 128 MB
- timeout: 30 s
GitHub не ограничивает доступ по стране, поэтому регион подойдёт любой.
- runtime: Node.js 24 (
-
Загрузите код:
npm run package aws lambda update-function-code --function-name github-relay --zip-file fileb://function.zip
-
Добавьте Function URL с auth type
NONEи invoke modeRESPONSE_STREAM. -
Задайте переменные окружения (см. ниже).
| Переменная | Значение |
|---|---|
GITHUB_PAT |
Токен GitHub только на чтение |
RELAY_TOKENS |
Список допустимых токенов релея через запятую |
RELAY_TOKEN |
Один токен релея |
Выдайте каждому клиенту свой токен. Тогда одного клиента можно отключить, убрав его токен, и остальных это не затронет. Токен можно сгенерировать так:
openssl rand -hex 32Все переменные задаются одной командой. Она заменяет все переменные функции целиком. Из-за запятых в RELAY_TOKENS значение передаётся в формате JSON:
aws lambda update-function-configuration --function-name github-relay \
--environment '{"Variables":{"GITHUB_PAT":"<токен GitHub>","RELAY_TOKENS":"<токен1>,<токен2>"}}'Lambda шифрует переменные окружения через KMS, но любой, у кого есть доступ к функции в консоли AWS, увидит их значения.
Создайте fine-grained PAT: GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens.
- Repository access: только нужные репозитории.
- Permissions → Repository → Discussions: Read-only (Metadata: Read-only добавится сам).
Глобальный search по дискуссиям в чужих публичных репозиториях fine-grained токен может не покрыть. Тогда подойдёт classic PAT с одним скоупом read:discussion (и public_repo, если без него поиск не работает). Не выдавайте токену прав на запись.
curl -s -H "x-relay-token: $RELAY_TOKEN" \
-d '{"query":"query{viewer{login}}"}' \
https://<id>.lambda-url.<region>.on.aws/graphqlОжидаемый ответ: {"data":{"viewer":{"login":"..."}}}.
Неверный токен даёт 403:
curl -s -o /dev/null -w '%{http_code}\n' -H "x-relay-token: wrong" \
-d '{"query":"query{viewer{login}}"}' https://<id>.lambda-url.<region>.on.aws/graphqlМутация тоже даёт 403:
curl -s -H "x-relay-token: $RELAY_TOKEN" \
-d '{"query":"mutation{addStar(input:{starrableId:\"x\"}){clientMutationId}}"}' \
https://<id>.lambda-url.<region>.on.aws/graphqlcurl -d отправляет Content-Type: application/x-www-form-urlencoded, но релею это не важно: тело всё равно разбирается как JSON, а в GitHub уходит Content-Type: application/json.
Function URL публичный, но без валидного токена он отвечает только 403. Токены и сам URL не публикуйте в репозиториях и логах. Чтобы отозвать токен, уберите его из RELAY_TOKENS: изменение применится к следующим вызовам.
npm testТесты работают с подменённым рантаймом Lambda и fetch, без сети.
MIT