Как работать с API Mailerlite через Cloudflare Workers
Для своей формы рассылки я использую сервис Mailerlite. Когда у меня была форма рассылки, я использовал сервис Mailerlite. Чтобы подключить форму к сайту, можно использовать виджет на основе Javascript, который доступен в настройках формы. Однако на моём сайте, построенном на Vue.js, форма отображалась только при первой загрузке страницы. Ну а так как я только учу Vue и просто хочу делать что-то классное вместо того, чтобы копаться в несовместимостях, я решил сделать свою собственную форму. Ведь API к сервису доступен.
Для использования API необходим секретный ключ, который нельзя встраивать в статический сайт, поэтому мне нужна была серверная часть. Тут-то и появляются Cloudflare Workers. Просто представьте: вы загружаете кусок Javascript кода, который начинает принимать запросы по указанному адресу как если бы вы настроили свой сервер. Только код работает в глобальной сети сервиса Cloudflare, не требует никакой инфраструктуры и это всё бесплатно. Ну как такое не использовать!
Фронтенд
Форма рассылки — это компонент Vue, который для отправки имейла обращается по адресу /api/subscribe
.
Бэкенд
Это код Javascript, который работает в среде Cloudflare Workers. Он мониторит POST
запросы по адресу /api/subscribe
и перенаправляет их в API сервиса Mailerlite.
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
const corsHeaders = {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Request-Method': 'POST, GET',
'Access-Control-Request-Headers': '*',
}
async function handleRequest(req) {
// OPTIONS request
if (req.method === 'OPTIONS') {
return new Response('OK', {headers: corsHeaders});
}
// POST /api/subscribe
if (req.method === 'POST' && /api\/subscribe$/.test(req.url)) {
// Parse request body as `FormData` instance
let fdata = await req.json();
const url = `https://api.mailerlite.com/api/v2/groups/${MAILERLITE_GROUP_ID}/subscribers`;
const resp = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-MailerLite-ApiKey': MAILERLITE_API_KEY
},
// cache: 'no-store',
body: JSON.stringify({
email: fdata.email || ''
})
});
const data = await resp.json();
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
...corsHeaders
}
});
}
// default response
return new Response(JSON.stringify('hi'), {
headers: {
"Content-Type": "application/json",
...corsHeaders
},
});
}
Документация по Workers просто замечательная и хорошо объясняет, как это все работает. Кроме того, там есть множество примеров. Но некоторые неочевидные моменты упомянуть стоит:
- Заголовки CORS необходимо добавлять к любому ответу из скрипта, в противном случае запрос типа
OPTIONS
работать не будет. - Кроме заголовков CORS, для обеспечения безопасности бэкенда хорошо подходит ограничение количества запросов в единицу времени, по крайней мере в данном случае. У Cloudflare есть и такая бесплатная опция.
- Скрипт использует несколько переменных окружения, которые должны быть определены в проекте Workers:
ALLOWED_ORIGIN
— домен, с которого форма рассылки шлет запросы.MAILERLITE_GROUP_ID
— идентификатор группы с подписчиками из аккаунта Mailerlite.MAILERLITE_API_KEY
— ключ API.
* * *
Теперь про фоновую картинку и про то, что я достиг в этот раз. Чтобы привнести что-то личное и сделать картинку по-настоящему уникальной, с помощью своего древнего планшета я написал "Dear Subscriber". Только вот поначалу результат был аховый. То ли это планшет очень старый, то ли что-то с драйверами, которые Windows ставит по умолчанию, то ли еще что-то, но линия дрожала и всё получалось каким-то угловатым. Но с помощью одной программы все-таки смог написать естественно. Это Lazy Nezumi: там совершенно дикое количество параметров и возможностей, но мне пригодился режим по умолчанию. Получилось действительно хорошо, на мой взгляд.
Посмотреть картинку: