ArvanCloud Edge Computing: уникальный опыт скорости и безопасности
С ArvanCloud Edge Computing вы можете запускать свои скрипты и обрабатывать код для ваших онлайн-сервисов в ближайшей точке к пользователю без необходимости сервера, обеспечивая новый уровень скорости и безопасности.



Бесплатный SSL-сертификат
Все домены, добавленные на платформу Edge Computing, автоматически получают бесплатные SSL-сертификаты.
Быстрая и легкая настройка
С помощью панели ArvanCloud или CLI запускайте и разворачивайте свои онлайн-сервисы менее чем за 30 секунд.
Оптимизированная производительность
Весь ваш бизнес-код размещается на ArvanCloud CDN PoPs и выполняется из ближайшей точки к пользователю.
Высокая безопасность
Наслаждайтесь передовыми функциями безопасности CDN от ArvanCloud для разработки ваших сервисов в безопасной и надежной среде.
Развивайте свои услуги с помощью расширенных функций
Серверлесс решение
Вы можете разрабатывать свои онлайн-сервисы без необходимости облачного или виртуального сервера и запускать контент из ближайшей точки к пользователю.
Высокая масштабируемость
Используйте неограниченные ресурсы сети доставки контента без балансировки нагрузки сервера или распределяйте трафик между несколькими PoPs.
Развертывание одним кликом
С готовыми к использованию кодами и шаблонами вы можете развернуть свой сервис всего одним кликом и настроить функции в соответствии с вашими потребностями.
Экономичный
Развертывание приложений с ArvanCloud Edge Computing позволяет вам доставлять ваши сервисы пользователям по минимальной цене.
Отладка перед выпуском
Легко редактируйте и вылаживайте свои финальные версии с помощью Console Log перед запуском вашего сайта или приложения для публики.
Быстрые ответы
С ArvanCloud Edge Computing отвечайте на запросы пользователей из ближайшего местоположения и повышайте скорость доставки вашего сервиса.
Более 40
99.99%
500 миллионов
Разрабатывайте функциональные сервисы всего одним кликом
Балансировщик нагрузки Round Robin
Защита от горячих ссылок
Основная аутентификация
SSR HTMX
С балансировщиком нагрузки Round Robin ваши входящие запросы равномерно распределяются между несколькими серверами. Это обеспечивает сбалансированное распределение трафика и лучшую производительность, а также помогает вам оставаться доступным и стабильным в условиях высокой нагрузки.
Просмотр
'use strict';
// Upstream URLs
const UPSTREAM_URLS = [
new URL("http://localhost:4000"),
new URL("http://localhost:4001"),
new URL("http://localhost:4002"),
new URL("http://localhost:4003"),
];
let NEXT_UPSTREAM_INDEX = 0;
async function handleRequest(request) {
let upstreamIdx = NEXT_UPSTREAM_INDEX;
NEXT_UPSTREAM_INDEX = (NEXT_UPSTREAM_INDEX + 1) % UPSTREAM_URLS.length;
let upstream = UPSTREAM_URLS[upstreamIdx];
return await doRequest(request, upstream);
}
function doRequest(request, upstream) {
let newUrl = new URL(request.url);
newUrl.protocol = upstream.protocol;
newUrl.host = upstream.host;
let newReq = new Request(newUrl.toString(), request);
return fetch(newReq);
}
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
Включая защиту от горячих ссылок, вы можете защитить ваши изображения, видео и т.д. от неправильного использования на других сайтах. Это не только снижает потребление пропускной способности и затраты, но также улучшает безопасность вашего сервиса и защищает ваш контент.
Просмотр
'use strict';
// Your domains that is allowed to access hotlinks
const DOMAINS = ["time.ir", "fa.wikipedia.org"];
// Upstream url
const UPSTREAM_URL = "http://localhost:4000";
// File extensions that hotlink is against
const EXTENSIONS = ["jpg", "jpeg", "png", "ico", "gif"];
async function handleRequest(request) {
const fileExt = extractUrlFileExtension(request.url);
if (fileExt == null || !EXTENSIONS_SET.has(fileExt)) {
return await doRequest(request);
}
else {
return await checkReferrerAndDoRequest(request);
}
}
async function doRequest(request) {
let newUrl = new URL(request.url);
newUrl.protocol = UPSTREAM_PROTOCOL;
newUrl.host = UPSTREAM_HOST;
let newReq = new Request(newUrl.toString(), request);
return fetch(newReq);
}
async function checkReferrerAndDoRequest(request) {
let response;
const referrerHeader = request.headers.get("referer");
if (referrerHeader != null) {
let domain = extractDomainFromReferrer(referrerHeader);
if (domain == null || DOMAINS_SET.has(domain)) {
response = await doRequest(request);
}
else {
response = UNAUTHORIZED_RESPONSE;
}
}
else {
response = await doRequest(request);
}
return response;
}
function extractDomainFromReferrer(referrer) {
try {
return new URL(referrer).hostname;
}
catch (e) {
return null;
}
}
function extractUrlFileExtension(url) {
try {
let pathname = new URL(url).pathname;
let lastDotIdx = pathname.lastIndexOf(".");
if (lastDotIdx == -1) {
return null;
}
else {
return pathname.substring(1 + lastDotIdx);
}
}
catch (e) {
return null;
}
}
const DOMAINS_SET = (() => {
const set = new Set();
DOMAINS.forEach((i) => set.add(i));
return set;
})();
const EXTENSIONS_SET = (() => {
const set = new Set();
EXTENSIONS.forEach((i) => set.add(i));
return set;
})();
const UNAUTHORIZED_RESPONSE = new Response(null, {
status: 401,
});
const UPSTREAM_PROTOCOL = new URL(UPSTREAM_URL).protocol;
const UPSTREAM_HOST = new URL(UPSTREAM_URL).host;
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
Шаблон Basic Auth позволяет вам легко контролировать доступ к защищенным разделам вашего сайта с помощью простого имени пользователя и пароля. Этот скрипт быстро реализуется и отвечает базовым потребностям безопасности вашего сервиса.
Просмотр
'use strict';
// Credentials for users
const UserPassList = [{ user: "admin", pass: "adminpass" }];
// Upstream url
const UPSTREAM_URL = "http://localhost:4000";
async function handleRequest(request) {
const authHeader = request.headers.get("Authorization");
let response;
if (authHeader != null && authHeader.startsWith("Basic")) {
let encodedCredential = authHeader.substring(6);
if (CREDENTIALS.has(encodedCredential)) {
let newUrl = new URL(request.url);
newUrl.protocol = UPSTREAM_PROTOCOL;
newUrl.host = UPSTREAM_HOST;
let newReq = new Request(newUrl.toString(), request);
newReq.headers.delete("Authorization");
response = await fetch(newReq);
}
else {
response = UNAUTHORIZED_INVALID_CREDENTIALS_RESPONSE;
}
}
else {
response = UNAUTHORIZED_NEEDS_LOGIN_RESPONSE;
}
return response;
}
const UNAUTHORIZED_NEEDS_LOGIN_RESPONSE = new Response(null, {
//TODO: Add realm and/or charset if needed
headers: new Headers({
"WWW-Authenticate": "Basic",
}),
status: 401,
});
const UNAUTHORIZED_INVALID_CREDENTIALS_RESPONSE = new Response(null, {
status: 401,
});
// Key: Base64 encoded username:password
// Value: username
const CREDENTIALS = (() => {
const map = new Map();
for (let i of UserPassList) {
// TODO: this may not properly work with utf8
const encoded = btoa(`${i.user}:${i.pass}`);
map.set(encoded, i.user);
}
return map;
})();
const UPSTREAM_PROTOCOL = new URL(UPSTREAM_URL).protocol;
const UPSTREAM_HOST = new URL(UPSTREAM_URL).host;
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
С шаблоном Server-Side Rendering в HTMX вы можете динамически визуализировать веб-страницы с сервера и обновлять различные разделы без полной перезагрузки страницы. Это поможет улучшить скорость загрузки и пользовательский опыт.
Просмотр
'use strict';
const TODO_LIST = ["test"];
function createDb() {
return {
add: async (title) => {
TODO_LIST.push(title);
},
list: async () => TODO_LIST,
};
}
const DefaultDB = createDb();
var Index = "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n <title>Todo list</title>\n <script src=\"https://unpkg.com/htmx.org@1.9.5\"></script>\n <link rel=\"stylesheet\" href=\"/styles.css\">\n</head>\n\n<body>\n <div>\n <div>\n <h1>To-Do List</h1>\n </div>\n <form hx-post=\"/add\" hx-target=\"#list\" hx-swap=\"beforeend\">\n <div>\n <input type=\"text\" placeholder=\"Task title\" name=\"title\" required />\n <button type=\"submit\">Add</button>\n </div>\n </form>\n <div id=\"list\" hx-get=\"/list\" hx-trigger=\"load\"></div>\n </div>\n</body>\n\n</html>";
var Styles = "h1 {\n color: red;\n}\n";
async function handleRequest(request) {
// simple router:
let content = "";
const url = new URL(request.url);
switch (url.pathname) {
case "/":
content = Index;
break;
case "/styles.css":
return new Response(Styles, {
headers: { "Content-Type": "text/css" },
});
case "/add":
const data = await request.formData();
const title = data.get("title").toString();
await DefaultDB.add(title);
content = `<li>${title}</li>`;
break;
case "/list":
content = (await DefaultDB.list()).map((x) => `<li>${x}</li>`).join("");
break;
default:
content = "Not found :(";
}
if (request.url)
return new Response(content, {
headers: { "Content-Type": "text/html; charset=utf-8" },
});
}
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});