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 Found
403 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.html
c содержимым выше - Включить 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 мы оригинально решили поставленную задачу.
Спасибо за внимание.