AWS, serverless redirects
+
+
Итак, редиректы без сервера, как это можно сделать с помощью сервисов AWS?
Для начала, давайте определимся, зачем это вообще может понадобиться. У меня возникла довольно простая с точки зрения бизнеса задача - настроить редиректы на региональные домены.
К примеру: mysite.customerdomain.com -> mysite.location.customerdomain.com. Делается это элементарно, с помощью rewrite-правил или того-же mod_alias для Apache HTTPD, если сайты работают на одном веб-сервере. В нашем же случае это несколько статических веб-приложений в S3 + CDN и бекэнд в виде микро-сервисов. Поэтому добавлять еще один веб-сервер и усложнять автоматизацию при работе с CloudFormation и Route53 не очень-то и хотелось.
Варианты
Для начала посмотрим на ситуацию в целом, для решения поставленной задачи есть несколько подходов:
- Стандартный с помощью DNS, Web-server’a и редиректов
- Использовать AWS сервисы и совсем немного JavaScript
Option 1: Old-style
Вариант довольно стандартный, работает на любой инфраструктуре и практически с любым DNS провайдером.
Рецепт:
- Поднимаем VM или контейнер и конфигурируем веб-сервер
- Настраиваем правила для редиректов: Nginx, Apache HTTPD попроще, Apache HTTPD посложнее
- Делаем CNAME для основных доменов на наш вновь-созданный application-router или redirect-service, кому как больше нравится
- Создаем новые DNS записи для текущих приложений
- Проверяем :)
На выходе имеем полноценные редиректы, которые возможно конфигурировать довольно сложным образом, при необходимости, и при этом у нас не возникает vendor-lock’a.
Давайте посмотрим как подобное можно сделать только средствами AWS.
Option 2: Serverless approach
Подобное? Именно, потому, что этот вариант будет работать только в браузерах с включенной поддержкой JavaScript. Нас это ограничение полностью устраивало, так как весь бэк-энд будет работать напрямую с новыми ссылками, а редиректы нужны были для старых ссылок пользователей, поэтому вариант с выключенным JavaScript в принципе не рассматривался.
Начнем мы с краткого обзора решений, которые предлагает AWS, а также причины, по которым они нам не подходят:
-
Is there a way to redirect a domain to another domain using Amazon Route 53?
В чем проблема?
Note: The sites must be HTTP, because the redirect cannot connect to S3 over HTTPS.
-
Configure a Bucket for Website Hosting
Описание возможностей редиректов для S3-bucket, широкие возможности, но из-за отсутствия поддержки HTTPS ситуацию не спасает.
-
Amazon S3 - HTTPS/SSL - Is it possible? [closed]
Интересный вопрос, на StackOverflow, в котором была копия официально ответа из отдела поддержки AWS, а также ссылка на официальное решение проблемы от AWS.
-
Официальный ответ Amazon, по решению проблемы SSL для Static-Site hosting + S3 - CloudFront CDN и custom SNI certificates.
Собственно, исходя из всего вышеперечисленного для редиректа пользователей у нас остается JavaScript.
Идея заключается в том, чтобы в корзину положить единственный index.html, вот такого содержания:
<html>
<body>
<script>
location.host = "mysite.location.customerdomain.com";
</script>
</body>
</html>
Работать это будет следующим образом:
- Пользователь запрашивает URL: http://mysite.customerdomain.com
- CDN сразу делает редирект на: https://mysite.customerdomain.com
- Браузер загружает
index.htmlи отправляет пользователя на https://mysite.location.customerdomain.com
JavaScript, MDN, Location
Все казалось бы просто, но не тут то было.
Технические подробности
Первый нюанс, это то, что нам обязательно нужно поставить параметр Default Root Object равным index.html, чтобы по умолчанию нам возвращалась наша страничка, даже если пользователь просто обратиться к корневому пути: / (https://mysite.customerdomain.com/).
AWS Console -> CloudFront -> Distribution settings -> General -> Edit:

Далее, возникает вопрос, а что делать со ссылками, к примеру: https://mysite.customerdomain.com/password-reset ? Нам же нужно сохранять и путь, и параметры.
В дефолтной конфигурации, CDN Вам либо ответит:
404 Not Found403 Not Authorized, в зависимости от конфигурации policy S3-bucket.
К счастью для нас, у CloudFront CDN есть возможность сделать персонализированные странички для ошибок(AWS Console -> CloudFront -> Distribution settings -> Error Pages) и что более важно выбрать каким HTTP-кодом отвечать браузеру.
Выглядит это так:

Идея в том, чтобы при ошибке, мы все равно попадали на index.html, c полным URL, который потом сделает нужный редирект.
Теперь, при запросах вида: http://mysite.customerdomain.com/password-reset будет происходить редирект на https://mysite.location.customerdomain.com/password-reset , что позволит нам сохранить совместимость со всеми старыми ссылками.
Немного о конфигурации S3-bucket
Есть 3 основные вещи, которые нужно сделать:
- Загрузить
index.htmlc содержимым выше - Включить Static Website Hosting

- Настроить S3-Bucket Policy
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "custom1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CustomCloudFrontUser"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::website-bucket-name/*"
}
]
}
Итого
При использовании CDN и JavaScript для редиректов, мягко говоря возникает вопрос резонности и целесообразности, а также стоимости такого решения.
Так как это бизнес требование, то предлагаю начать с цен:
-
Request Pricing for All HTTP Methods (per 10,000)
| United States | Canada | Europe | Hong Kong, Philippines, S. Korea, Singapore & Taiwan | Japan | South America | Australia | India | Reserved Capacity Pricing | |
|---|---|---|---|---|---|---|---|---|---|
| HTTP requests | $0.0075 | $0.0075 | $0.0090 | $0.0090 | $0.0090 | $0.0160 | $0.0090 | $0.0090 | Contact Us |
| HTTPS requests | $0.0100 | $0.0100 | $0.0120 | $0.0120 | $0.0120 | $0.0220 | $0.0125 | $0.0120 | Contact Us |
-
GET and all other Requests $0.01 per 10,000 requests
При самых грубых подсчетах: $0.0075 + $0.01 = $0.0175 за 10 000 запросов. При том, что минимум за EC2 Instance мы будем платить от ~$10-15 в месяц.
Но, несмотря на все это, у решения есть недостатки:
- это не полноценный редирект и рассчитан только для работы в современных браузерах
- CloudFront ведет себя довольно непредсказуемо при первоначальной настройке и загрузке страницы, уходило какое-то время(несколько часов), пока он нормально кешировал этот объект(возможно из-за редиректов)
- Downtime, при изменение DNS, а с учетом DNS-кэша у пользователей могут возникать странные ошибки
В нашем случае этот вариант полностью нас устраивал и имел существенные преимущества в плане экономии времени разработки и внедрения, т.к. интеграция нового сервиса в CloudFormation, скрипты и Continuos Delviery процесс, а также их тестирование было бы мягко говоря длительным и трудоемким, а необходимость в поддержке этих редиректов - временная.
В целом используя возможности AWS-платформы и стандартный функционал JavaScript мы оригинально решили поставленную задачу.
Спасибо за внимание.