Введение: почему Swift для REST API?
Swift — это не только язык для мобильных приложений. Благодаря фреймворкам, таким как Vapor и Kitura, вы можете создавать полноценные REST API для серверной части. Это особенно полезно, если ваше iOS-приложение уже использует Swift: вы можете писать и клиент, и сервер на одном языке, сокращая время разработки и упрощая поддержку кода.
В этой статье мы создадим простой REST API на Swift с помощью фреймворка Vapor — самого популярного решения для серверной разработки на Swift. Мы настроим сервер, добавим маршруты для CRUD-операций и протестируем его. Весь процесс займёт не более 30 минут.
Требования: macOS или Linux, установленный Swift 5.8+ (или новее), базовое понимание HTTP и JSON.
Шаг 1: Установка и настройка проекта Vapor
Vapor предоставляет удобный CLI-инструмент для быстрого старта. Установите его через Homebrew:
brew install vapor
Затем создайте новый проект:
vapor new MyAPI --template=api
cd MyAPI
Флаг --template=api создаёт заготовку с минимальной структурой для REST API. После создания проекта откройте его в Xcode (или любом редакторе):
open Package.swift
Структура проекта включает:
Sources/App/— основная логика (маршруты, контроллеры, модели).Sources/App/routes.swift— регистрация маршрутов.Sources/App/configure.swift— конфигурация приложения.Package.swift— зависимости (Vapor уже включён).
Если вы используете Xcode, он автоматически загрузит зависимости. В терминале выполните vapor build для сборки.
Шаг 2: Создание модели данных и базы
Для REST API нам нужна модель. Создадим простую модель Task (задача) с полями: id, title, completed. В Vapor модели обычно наследуются от Model (Fluent ORM).
Создайте файл Sources/App/Models/Task.swift:
import Fluent
import Vapor
final class Task: Model, Content {
static let schema = "tasks"
@ID(key: .id)
var id: UUID?
@Field(key: "title")
var title: String
@Field(key: "completed")
var completed: Bool
init() {}
init(id: UUID? = nil, title: String, completed: Bool = false) {
self.id = id
self.title = title
self.completed = completed
}
}
Теперь создадим миграцию для таблицы в базе данных. Создайте файл Sources/App/Migrations/CreateTask.swift:
import Fluent
struct CreateTask: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema("tasks")
.id()
.field("title", .string, .required)
.field("completed", .bool, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema("tasks").delete()
}
}
Добавьте миграцию в configure.swift:
app.migrations.add(CreateTask())
По умолчанию Vapor использует SQLite (файл в папке проекта). Если хотите PostgreSQL или MySQL — измените настройки в configure.swift, но для быстрого старта SQLite отлично подходит.
Шаг 3: Регистрация маршрутов REST API
Теперь создадим контроллер для обработки запросов. Создайте файл Sources/App/Controllers/TaskController.swift:
import Vapor
import Fluent
struct TaskController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
let tasks = routes.grouped("tasks")
tasks.get(use: index) // GET /tasks
tasks.post(use: create) // POST /tasks
tasks.group(":id") { task in
task.get(use: show) // GET /tasks/:id
task.put(use: update) // PUT /tasks/:id
task.delete(use: delete) // DELETE /tasks/:id
}
}
// GET /tasks — получить все задачи
func index(req: Request) async throws -> [Task] {
try await Task.query(on: req.db).all()
}
// POST /tasks — создать задачу
func create(req: Request) async throws -> Task {
let task = try req.content.decode(Task.self)
try await task.save(on: req.db)
return task
}
// GET /tasks/:id — получить задачу по ID
func show(req: Request) async throws -> Task {
guard let task = try await Task.find(req.parameters.get("id"), on: req.db) else {
throw Abort(.notFound)
}
return task
}
// PUT /tasks/:id — обновить задачу
func update(req: Request) async throws -> Task {
guard let task = try await Task.find(req.parameters.get("id"), on: req.db) else {
throw Abort(.notFound)
}
let updatedTask = try req.content.decode(Task.self)
task.title = updatedTask.title
task.completed = updatedTask.completed
try await task.save(on: req.db)
return task
}
// DELETE /tasks/:id — удалить задачу
func delete(req: Request) async throws -> HTTPStatus {
guard let task = try await Task.find(req.parameters.get("id"), on: req.db) else {
throw Abort(.notFound)
}
try await task.delete(on: req.db)
return .ok
}
}
Зарегистрируйте контроллер в routes.swift:
import Vapor
func routes(_ app: Application) throws {
try app.register(collection: TaskController())
}
Теперь у нас есть полноценный REST API с поддержкой CRUD. Обратите внимание на использование async/await — Swift 5.5+ делает код чистым и безопасным.
Шаг 4: Запуск и тестирование API
Запустите сервер:
vapor run
Сервер будет доступен по адресу http://127.0.0.1:8080. Протестируем API с помощью curl или Postman:
- Создать задачу (POST):
curl -X POST http://127.0.0.1:8080/tasks \ -H "Content-Type: application/json" \ -d '