Skip to content

Latest commit

 

History

History
233 lines (168 loc) · 9.47 KB

File metadata and controls

233 lines (168 loc) · 9.47 KB

Route Definition Language

Оглавление

Введение
Объявление маршрута
Переменные, типы, ошибки
Глобальная конфигурация
Перехватчики ошибок
Объекты и функции
Ошибки

Введение

Особенности языка:

  • Интерпретируемый. Парсер, лексер и интерпретатор написан на Rust;
  • Чувствителен к регистру;
  • Игнорирует пробелы;
  • ; обязательна;
  • Если у условного оператора if после окончания блока нет условия else или if else, то ; обязательна: if (a == "string") { };.

Язык всё ещё в разработке! Следите за обновлениями!

Объявление маршрута

Чтобы объявить маршрут используется ключевое слово route. Затем идёт маршрут, который будет обрабатывать сервер (с учётом регистра!). Далее тип запросов, которые он ждёт.

route "/users" GET {};

Переменные, типы, ошибки

  • Переменные можно объявить с помощью ключевых слов var или val:
val a = 1;
  • Язык имеет строковую типизацию - любое значение, которое может вернуть функция или введённое значение напрямую (val a = 2;) является строкой. То есть в примере выше a содержит не числовой тип 1, а строку "1";

  • У вас есть возможность обрабатывать ошибки двумя способами: локальный обработчик (обработка ошибок для конкретного блока) или глобальный обработчик (если нет локального обработчика, ошибки идут туда). Локальный обработчик имеет приоритет (т.е. если есть и глобальный, и локальный обработчик, то ошибка пойдёт в локальный).

Локальный обработчик:

route "/user/{id}" GET {
    val user = Request.get_params("id")?;
    // Если функция get_params закончится ошибкой (в пути нет {id}), код не пойдёт дальше, а перейдёт в блок обработки
    Response.body("Hello, " + user);
    Response.send();
} onError(e) { // (e) - переменная, в которую помещается ошибка (ошибка - строка)
    Response.status(500);
    Response.body("Error on get request params: " + e);
    Response.send();
}; // ';' обязательна после каждого блока (исколючение - окончание блока "else")!

Глобальный обработчик:

global_error_handler(e) {
    Response.status(500);
    Response.body("Server-side error: " + e);
    Response.headers("Content-Type", "text/html");
    Response.send();
};

route "/user" GET {
    val body = Request.body()?;
    // Если ошибка поймана (у запроса нет тела), выполнение перейдёт в global_error_handler
    Response.body(body);
    Response.send();
};

Циклы и условные конструкции

RDL поддерживает следующие конструкции:

  • Цикл for;
  • Цикл while;
  • Условие if

for

val mix = ["hello", "hey", 1, 2];
val body = "";
for (i in mix) {
    body += i;
    body += " ";
}; // body = "hello hey 1 2"

while

val a = 2;
val b = 15 - 3;
while (a != 5) {
    a += 1;
    b -= 2;
};
// a = 5
// b = 6

if

if (a == b) {
    ...
}; // `;` обязательна, если нет условия else:

if (a == b) {
    ...
} else {
    ...
}

Глобальная конфигурация

Существует 2 конфигурации, которые вы можете настроить: tls (настройка защиты соединения) и global_error_handler (глобальная обработка ошибок).

TLS:

tls {
    enabled = true;
    key = path/to/key;
    cert = path/to/cert;
}; // Если ошибок в этом блоке нет, все соединения будут проходить по https, а не http

Глобальный обработчик:

global_error_handler { // ошибку мы не сохраняем и воспользоваться ей не сможем
    Response.status(500);
    Response.send();
};

Перехватчики ошибок

Существует 2 способа перехватить ошибку: с помощью оператора ? (ловит ошибку, останавливает выполнение кода и переходит в обработчик) и !! (игнорирование возможной ошибки. Если она есть, пойдёт экстренное завершение кода (паника) ).

?:

val body = Request.body()?;

!!:

val body = Request.body()!!;

Если не установлен никакой оператор, выполнение идёт как !!.

Объекты и функции

Объекты:

  • Database: Данный объект даёт доступ к функциям работы с базой данных;
  • Request: Данный объект даёт доступ к функциям обработки запроса;
  • Response: Данный объект даёт доступ к функциям настройки ответа.

Глобальные функции

  • log_error(message): Логгирование ошибок;
  • log_info(message): Логгирование информации;
  • log_trace(message): Логгирование трейсов;
  • array_length(array): Возвращает длину указанного массива;
  • array_push(array, element): Добавляет элемент в указанный массив;
  • array_pop(array): Удаляет и возвращает последний элемент массива;
  • array_contains(array, element): Проверяет наличие элемента в массиве;
  • array_join(array, separator): Разделяет элементы массива с помощью указанного разделителя и возвращает получившуюся строку;

Функции объектов

Database:

  • get_all(): Получение всех записей из базы. Ошибки;
  • get(id): Получение записи по id. Ошибки;
  • check(id): Проверка наличия записи по id. Ошибки.

Request:

  • body(): Получение тела запроса. Ошибки;
  • get_params(): Получение параметров из маршрута (вставки {name_param} в пути: route "/user/{id}). Ошибки;
  • headers(): Получение заголовков из маршрута. Ошибки.

Response:

  • status(): Установка статус ответа;
  • body(): Установка тела ответа;
  • headers(): Установка заголовков ответа;
  • send(): Отправка собранного ответа;

FileSystem:

  • exists(path): Проверяет существует ли файл по указанному пути;
  • read_text(path): Возвращает содержимоое файлйа по указанному пути;
  • write_text(path, content): Записывает указанное содержимое в файл по указанному пути;
  • is_directory(path): Проверяет является ли путь директорией;
  • list_files(path): Возвращает все файлы в указанной директории;

Ошибки

Database

  • get_all(): В базе данных нет записей;
  • get(id): В базе данных не найдена запись с id;
  • check(id): В базе данных не найдена запись с id;

Request

  • body(): У запроса нет тела;
  • get_params(): У пути маршрута нет параметра с указаным id;
  • headers(): У запроса нет заголовков;

FileSystem

Каждая функция может вернуть множество ошибок, связанных с проблемами открытия файла, чтения, записи или нахождения.

Заключение

Если какие-то из этих функций работают некорректно, обязательно сообщите о баге в issue!