Как написать REST API на Swift за 30 минут: для начинающих
Swift — это не только язык для создания мобильных приложений под iOS и macOS. С появлением фреймворка Vapor разработка серверных приложений на Swift стала доступной и удобной. В этой статье мы покажем, как написать простой REST API на Swift буквально за 30 минут. Вы узнаете основные принципы работы с Vapor, научитесь создавать маршруты, обрабатывать запросы и возвращать JSON-ответы.
Это руководство идеально подходит для начинающих, которые уже знакомы с основами Swift, но никогда не писали серверный код. Мы разберём процесс шаг за шагом, с примерами кода и пояснениями.
Что такое REST API и зачем он нужен?
REST (Representational State Transfer) — это архитектурный стиль взаимодействия компонентов распределённого приложения в сети. REST API позволяет клиентским приложениям (например, iOS-приложению) получать и отправлять данные на сервер через HTTP-запросы.
Основные методы HTTP, используемые в REST:
- GET — получение данных
- POST — создание нового ресурса
- PUT — обновление существующего ресурса
- DELETE — удаление ресурса
Для нашего примера мы создадим простое API для управления списком задач (Todo List). Оно будет поддерживать все четыре основные операции CRUD (Create, Read, Update, Delete).
Установка Vapor и создание проекта
Vapor — это самый популярный веб-фреймворк для Swift. Для начала работы установите Vapor Toolbox через Homebrew:
brew install vapor
После установки создайте новый проект:
vapor new TodoAPI
cd TodoAPI
Эта команда создаст структуру проекта с уже настроенным сервером. Откройте проект в Xcode:
open Package.swift
В Xcode вы увидите стандартную структуру Vapor-проекта. Основной код находится в папке Sources/App.
Создание модели данных
Для работы с задачами нам нужна модель. Создадим файл Todo.swift в папке Sources/App/Models:
import Vapor
import Fluent
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 для Swift, который работает с базами данных. В нашем примере будем использовать SQLite для простоты. Обратите внимание на протокол Content — он позволяет автоматически кодировать/декодировать модель в JSON.
Настройка миграции и базы данных
Теперь создадим миграцию для нашей модели. Добавьте файл CreateTodo.swift в папку Sources/App/Migrations:
import Fluent
struct CreateTodo: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema("todos")
.id()
.field("title", .string, .required)
.field("is_completed", .bool, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema("todos").delete()
}
}
В файле configure.swift добавьте регистрацию базы данных и миграции:
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)
}
Мы используем SQLite как файловую базу данных — это идеально для разработки и тестирования.
Создание маршрутов (Routes)
Теперь самое интересное — реализация API. Откройте файл routes.swift и замените его содержимое:
import Vapor
func routes(_ app: Application) throws {
let todoController = TodoController()
// Получить все задачи
app.get("todos") { req async throws -> [Todo] in
try await Todo.query(on: req.db).all()
}
// Получить задачу по ID
app.get("todos", ":id") { req async throws -> Todo in
guard let todo = try await Todo.find(req.parameters.get("id"), on: req.db) else {
throw Abort(.notFound)
}
return todo
}
// Создать новую задачу
app.post("todos") { req async throws -> Todo in
let todo = try req.content.decode(Todo.self)
try await todo.save(on: req.db)
return todo
}
// Обновить задачу
app.put("todos", ":id") { req async throws -> Todo in
guard let todo = try await Todo.find(req.parameters.get("id"), on: req.db) else {
throw Abort(.notFound)
}
let updatedTodo = try req.content.decode(Todo.self)
todo.title = updatedTodo.title
todo.isCompleted = updatedTodo.isCompleted
try await todo.save(on: req.db)
return todo
}
// Удалить задачу
app.delete("todos", ":id") { req async throws -> HTTPStatus in
guard let todo = try await Todo.find(req.parameters.get("id"), on: req.db) else {
throw Abort(.notFound)
}
try await todo.delete(on: req.db)
return .noContent
}
}
Обратите внимание на использование async/await — это современный подход к асинхронному программированию в Swift, который делает код более читаемым.
Тестирование API
Запустите сервер командой в терминале (из папки проекта):
vapor run
Сервер запустится на http://127.0.0.1:8080. Теперь вы можете тестировать API с помощью cURL или любого REST-клиента (например, Postman):
Создать задачу:
curl -X POST http://127.0.0.1:8080/todos \
-H "Content-Type: application/json" \
-d '{"title": "Изучить Swift", "isCompleted": false}'
Блоги
Рекомендаций по книгам
Читайте также
Кэширование в Kotlin: Redis, Memcached и встроенные решения
Что такое r#""# в Rust? Полный разбор магического оператора
Rust в 2025 году: полное руководство для начинающих с нуля
Companion object в Kotlin: замена Java static и производительность
Как получить enum из строки в Java: полный гайд для новичков