Как написать REST API на Swift за 30 минут

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему REST API на Swift — это быстро и современно

Разработка мобильных приложений под iOS и macOS требует не только красивого интерфейса, но и надежного серверного бэкенда. REST API (Representational State Transfer) остается стандартом де-факто для обмена данными между клиентом и сервером. Если вы уже пишете на Swift для Apple-экосистемы, то создание API на том же языке — логичный шаг. Это позволяет переиспользовать модели данных, избегать дублирования кода и быстрее внедрять изменения.

В этой статье мы покажем, как написать полноценный REST API на Swift с использованием фреймворка Vapor — самого популярного веб-фреймворка для Swift. Вы узнаете, как настроить проект, создать маршруты, обрабатывать JSON и запустить сервер. Весь процесс займет не более 30 минут. Готовы? Поехали!

1. Подготовка окружения и установка Vapor

Прежде чем писать код, убедитесь, что у вас установлены необходимые инструменты. Для работы с Vapor потребуется Swift 5.9 или новее (рекомендуется Swift 6). Также вам понадобится терминал и редактор кода (Xcode или VS Code).

Установка Vapor Toolbox

Vapor Toolbox — это утилита командной строки, которая упрощает создание и управление проектами. Установите её через Homebrew:

brew install vapor

Если Homebrew не установлен, скачайте его с brew.sh. После установки проверьте версию:

vapor --version

Создание нового проекта

Откройте терминал и выполните команду:

vapor new MyAPI --template=api

Флаг --template=api создает базовую структуру для REST API без лишних файлов. Перейдите в папку проекта:

cd MyAPI

Теперь откройте проект в Xcode:

open Package.swift

Или используйте любой другой редактор. Готово! У вас есть чистый шаблон Vapor.

2. Базовая структура: модели, контроллеры и маршруты

Vapor использует архитектуру MVC (Model-View-Controller), адаптированную под серверную разработку. Мы создадим простое API для управления списком задач (To-Do list).

Создание модели

Модель — это структура, которая описывает данные. В папке Sources/App/Models/ создайте файл Todo.swift:

import Fluent
import Vapor

final class Todo: Model, Content {
    static let schema = "todos"
    
    @ID(key: .id)
    var id: UUID?
    
    @Field(key: "title")
    var title: String
    
    @Field(key: "is_completed")
    var isCompleted: Bool
    
    init() { }
    
    init(id: UUID? = nil, title: String, isCompleted: Bool = false) {
        self.id = id
        self.title = title
        self.isCompleted = isCompleted
    }
}

Мы используем Fluent — ORM от Vapor для работы с базами данных. Модель автоматически сериализуется в JSON благодаря протоколу Content.

Создание контроллера

Контроллер содержит логику обработки запросов. Создайте файл Sources/App/Controllers/TodoController.swift:

import Vapor
import Fluent

struct TodoController: RouteCollection {
    func boot(routes: RoutesBuilder) throws {
        let todos = routes.grouped("todos")
        todos.get(use: index)
        todos.post(use: create)
        todos.group(":todoID") { todo in
            todo.delete(use: delete)
        }
    }
    
    // GET /todos — получить все задачи
    func index(req: Request) async throws -> [Todo] {
        try await Todo.query(on: req.db).all()
    }
    
    // POST /todos — создать задачу
    func create(req: Request) async throws -> Todo {
        let todo = try req.content.decode(Todo.self)
        try await todo.save(on: req.db)
        return todo
    }
    
    // DELETE /todos/:id — удалить задачу
    func delete(req: Request) async throws -> HTTPStatus {
        guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
            throw Abort(.notFound)
        }
        try await todo.delete(on: req.db)
        return .ok
    }
}

Регистрация маршрутов

Откройте файл Sources/App/routes.swift и добавьте вызов контроллера:

import Vapor

func routes(_ app: Application) throws {
    try app.register(collection: TodoController())
}

Теперь ваше API имеет три эндпоинта: GET /todos, POST /todos и DELETE /todos/:id.

3. Настройка базы данных и миграции

Для хранения данных мы используем SQLite — легковесную базу, не требующую установки отдельного сервера. Vapor автоматически настраивает её в шаблоне, но нужно создать миграцию.

Создание миграции

Миграция описывает структуру таблицы. Создайте файл Sources/App/Migrations/CreateTodo.swift:

import Fluent
import Vapor

struct CreateTodo: AsyncMigration {
    func prepare(on database: Database) async throws {
        try await database.schema("todos")
            .id()
            .field("title", .string, .required)
            .field("is_completed", .bool, .required)
            .create()
    }
    
    func revert(on database: Database) async throws {
        try await database.schema("todos").delete()
    }
}

Теперь зарегистрируйте миграцию в файле Sources/App/configure.swift:

import Vapor
import Fluent
import FluentSQLiteDriver

public func configure(_ app: Application) throws {
    app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite)
    
    app.migrations.add(CreateTodo())
    
    try app.autoMigrate().wait()
    
    try routes(app)
}

При запуске сервера Vapor автоматически создаст таблицу todos в файле db.sqlite.

4. Запуск и тестирование API

Всё готово к запуску! Выполните в терминале:

vapor run

Сервер запустится на http://127.0.0.1:8080. Теперь протестируем эндпоинты с помощью cURL

Блоги

Рекомендаций по книгам