API маршруты и серверная логика

Svelte позволяет разрабатывать фронтенд-приложения, но также предоставляет удобные механизмы для работы с серверной логикой через API маршруты. В отличие от традиционных фреймворков, таких как Next.js или Nuxt.js, которые обрабатывают серверные маршруты через специальные серверные компоненты, Svelte интегрирует серверную логику непосредственно в проект, используя специальные файлы, называемые эндпоинтами.

Структура API маршрутов

Для создания API маршрутов в Svelte используется папка src/routes, в которой можно определять как клиентские компоненты, так и серверные обработчики. Серверные маршруты определяются через создание файлов с расширением .js или .ts в той же структуре, что и обычные компоненты.

Пример структуры проекта:

src/
├── routes/
│   ├── api/
│   │   └── todos.js
│   └── index.svelte

В данном примере файл todos.js будет обрабатывать запросы к API маршруту /api/todos. Все серверные маршруты находятся внутри папки api/.

Создание простого API маршрута

Для создания простого API маршрута нужно создать файл в папке src/routes/api. Рассмотрим пример создания API для получения списка задач.

  1. Создадим файл src/routes/api/todos.js:
export async function get() {
    const todos = [
        { id: 1, task: 'Сделать домашку' },
        { id: 2, task: 'Купить продукты' },
    ];

    return {
        status: 200,
        body: { todos }
    };
}

В этом примере экспортируется асинхронная функция get(), которая обрабатывает GET-запросы на маршрут /api/todos. Функция возвращает объект с кодом статуса и телом ответа. Ответ может быть в формате JSON.

  1. Создадим компонент Svelte для отображения списка задач:
<script>
  let todos = [];

  async function fetchTodos() {
    const response = await fetch('/api/todos');
    const data = await response.json();
    todos = data.todos;
  }

  fetchTodos();
</script>

<ul>
  {#each todos as todo}
    <li>{todo.task}</li>
  {/each}
</ul>

Этот компонент использует функцию fetch() для получения данных с API маршрута /api/todos. Полученные данные отображаются в виде списка.

HTTP методы и обработка запросов

В Svelte можно обрабатывать различные HTTP методы для одного маршрута, например, GET, POST, PUT, DELETE. Каждый метод обрабатывается отдельной функцией в файле маршрута.

GET-запрос

GET-запрос используется для получения данных с сервера. В функции обработки GET-запроса обычно производится чтение данных из базы данных или других источников.

Пример:

export async function get() {
    const user = { id: 1, name: 'Иван' };
    
    return {
        status: 200,
        body: user
    };
}

POST-запрос

POST-запрос используется для отправки данных на сервер. В Svelte это реализуется через экспорт функции post(). В теле запроса могут передаваться данные, которые затем обрабатываются на сервере.

Пример:

export async function post(request) {
    const { name, email } = await request.json();
    
    // Допустим, данные сохраняются в базе данных
    const newUser = { id: 2, name, email };
    
    return {
        status: 201,
        body: newUser
    };
}

Здесь request.json() позволяет получить данные, отправленные в теле запроса.

PUT-запрос

PUT-запрос используется для обновления данных на сервере. В отличие от POST, PUT предполагает полное обновление ресурса.

Пример:

export async function put(request) {
    const { id, name, email } = await request.json();
    
    // Обновляем данные пользователя
    const updatedUser = { id, name, email };
    
    return {
        status: 200,
        body: updatedUser
    };
}

DELETE-запрос

DELETE-запрос используется для удаления данных на сервере. Пример:

export async function del(request) {
    const { id } = await request.json();
    
    // Удаляем пользователя из базы данных
    return {
        status: 204
    };
}

Валидация данных

При работе с API маршрутом часто возникает необходимость валидировать входящие данные. Это можно сделать непосредственно в обработчиках маршрутов. Например, для валидации можно использовать простые проверки или сторонние библиотеки, такие как zod или joi.

Пример простой валидации:

export async function post(request) {
    const { name, email } = await request.json();
    
    if (!name || !email) {
        return {
            status: 400,
            body: { error: 'Имя и email обязательны' }
        };
    }
    
    const newUser = { id: 2, name, email };
    
    return {
        status: 201,
        body: newUser
    };
}

Работа с файлами и асинхронными операциями

В API маршрутах Svelte можно также обрабатывать асинхронные операции, такие как загрузка файлов или взаимодействие с внешними API. Пример загрузки файла:

export async function post(request) {
    const formData = await request.formData();
    const file = formData.get('file');
    
    // Здесь можно обработать файл (сохранить на сервере или передать в облако)
    
    return {
        status: 200,
        body: { message: 'Файл успешно загружен' }
    };
}

Обработка ошибок

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

Пример обработки ошибок:

export async function get() {
    try {
        const data = await fetchData();
        return {
            status: 200,
            body: data
        };
    } catch (error) {
        return {
            status: 500,
            body: { error: 'Внутренняя ошибка сервера' }
        };
    }
}

В данном примере, если возникнет ошибка при получении данных, сервер вернёт код 500 с соответствующим сообщением.

Работа с сессиями и авторизацией

Иногда для API маршрутов требуется поддержка сессий или авторизации. В Svelte можно использовать встроенные механизмы для работы с сессиями, такие как cookies.

Пример использования cookies для хранения сессии:

export async function get({ request }) {
    const cookie = request.headers.get('cookie');
    const userId = cookie ? parseCookie(cookie).userId : null;
    
    if (!userId) {
        return {
            status: 401,
            body: { error: 'Пользователь не авторизован' }
        };
    }
    
    const user = await getUserFromDatabase(userId);
    return {
        status: 200,
        body: user
    };
}

Здесь происходит проверка авторизации пользователя с использованием данных из cookies.

Заключение

API маршруты в Svelte обеспечивают мощный инструмент для обработки серверной логики прямо внутри приложения. Используя стандартные HTTP методы, можно легко строить RESTful API с поддержкой различных операций (GET, POST, PUT, DELETE). Благодаря асинхронности и интеграции с файловой системой и внешними сервисами, Svelte предоставляет гибкость для решения множества задач, связанных с серверной логикой, без необходимости внедрения сложных внешних решений.