← Назад к вопросам

Какие запросы лежат в основе REST API?

2.0 Middle🔥 261 комментариев
#Сетевые протоколы и API

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные типы запросов (HTTP-методы) в REST API

REST API построен на принципах архитектуры REST (Representational State Transfer), где HTTP.методы играют ключевую роль в определении типа операции над ресурсом. Каждый метод имеет семантическое значение и должен использоваться идемпотентно и безопасно, где это определено спецификацией HTTP.

1. GET — Получение ресурса

Метод GET используется для чтения или получения представления ресурса. Он должен быть безопасным (safe), то есть не изменять состояние сервера, и идемпотентным (idempotent) — многократные одинаковые запросы дают тот же результат.

GET /api/users/123 HTTP/1.1
Host: example.com
// Ответ
{
    "id": 123,
    "name": "Иван Иванов",
    "email": "ivan@example.com"
}

2. POST — Создание нового ресурса

POST применяется для создания новых ресурсов. Сервер определяет URI созданного ресурса и возвращает его в заголовке Location. Метод не является идемпотентным — повторные одинаковые запросы могут создавать дубликаты.

POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json

{
    "name": "Мария Петрова",
    "email": "maria@example.com"
}
// Ответ с кодом 201 Created
{
    "id": 124,
    "name": "Мария Петрова",
    "email": "maria@example.com"
}

3. PUT — Полное обновление ресурса

PUT используется для полной замены ресурса по известному URI. Если ресурс существует — он обновляется, если нет — создается (хотя создание чаще относится к POST). Метод идемпотентен: многократное выполнение одного запроса дает одинаковый результат.

PUT /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json

{
    "name": "Иван Сидоров",
    "email": "ivan.sidorov@example.com"
}

4. PATCH — Частичное обновление ресурса

PATCH предназначен для частичного обновления ресурса. В отличие от PUT, передаются только изменяемые поля. Сложность заключается в формате описания изменений (JSON Patch, JSON Merge Patch и др.).

PATCH /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json-patch+json

[
    { "op": "replace", "path": "/email", "value": "new.email@example.com" }
]

5. DELETE — Удаление ресурса

DELETE используется для удаления ресурса по указанному URI. После успешного удаления последующие запросы должны возвращать 404 Not Found или 410 Gone. Метод идемпотентен.

DELETE /api/users/123 HTTP/1.1
Host: example.com

6. Дополнительные методы

HEAD

Аналогичен GET, но возвращает только заголовки без тела ответа. Полезен для проверки существования ресурса или получения метаданных.

HEAD /api/users/123 HTTP/1.1
Host: example.com

OPTIONS

Возвращает список поддерживаемых HTTP-методов для конкретного ресурса или всего сервера. Важен для CORS (Cross-Origin Resource Sharing).

OPTIONS /api/users HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Allow: GET, POST, PUT, DELETE, OPTIONS, HEAD

Ключевые принципы использования методов в REST

  • Идемпотентность: GET, PUT, DELETE, HEAD, OPTIONS — выполнение запроса несколько раз дает тот же эффект, что и однократное.
  • Безопасность: GET, HEAD, OPTIONS — не должны изменять состояние сервера.
  • Семантическая корректность: Использование методов согласно их назначению (не использовать GET для изменения данных).
  • Статус.коды ответа: Каждый метод предполагает определенные HTTP-статусы:
    • 200 OK для успешного GET, PUT, PATCH, DELETE
    • 201 Created для успешного POST
    • 204 No Content для успешного DELETE без возвращаемого тела
    • 404 Not Found если ресурс не существует
    • 405 Method Not Allowed если метод не поддерживается

Пример полного CRUD на Go с использованием стандартной библиотеки

package main

import (
    "encoding/json"
    "net/http"
    "strconv"
)

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

var users = map[int]User{}
var nextID = intervieweer

func main() {
    http.HandleFunc("/users", handleUsers)
    http.HandleFunc("/users/", handleUserByID)
    http.ListenAndServe(":8080", nil)
}

func handleUsers(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        // GET /users - список всех пользователей
        usersSlice := make([]User, 0, len(users))
        for _, user := range users {
            usersSlice = append(usersSlice, user)
        }
        json.NewEncoder(w).Encode(usersSlice)
        
    case http.MethodPost:
        // POST /users - создание нового пользователя
        var user User
        if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        
        user.ID = nextID
        nextID++
        users[user.ID] = user
        
        w.Header().Set("Location", "/users/"+strconv.Itoa(user.ID))
        w.WriteHeader(http.StatusCreated)
        json.NewEncoder(w).Encode(user)
        
    default:
        w.Header().Set("Allow", "GET, POST")
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

func handleUserByID(w http.ResponseWriter, r *http.Request) {
    idStr := r.URL.Path[len("/users/"):]
    id, err := strconv.Atoi(idStr)
    if err != nil {
        http.Error(w, "Invalid user ID", http.StatusBadRequest)
        return
    }
    
    user, exists := users[id]
    if !exists {
        http.Error(w, "User not found", http.StatusNotFound)
        return
    }
    
    switch r.Method {
    case http.MethodGet:
        // GET /users/{id} - получение пользователя
        json.NewEncoder(w).Encode(user)
        
    case http.MethodPut:
        // PUT /users/{id} - полное обновление
        var updatedUser User
        if err := json.NewDecoder(r.Body).Decode(&updatedUser); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        updatedUser.ID = id
        users[id] = updatedUser
        json.NewEncoder(w).Encode(updatedUser)
        
    case http.MethodDelete:
        // DELETE /users/{id} - удаление
        delete(users, id)
        w.WriteHeader(http.StatusNoContent)
        
    default:
        w.Header().Set("Allow", "GET, PUT, DELETE")
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

Правильное использование HTTP-методов — фундамент хорошо спроектированного REST API, обеспечивающий предсказуемость, масштабируемость и совместимость системы. В Go это достигается через четкую маршрутизацию и обработку методов в обработчиках http.HandleFunc.

Какие запросы лежат в основе REST API? | PrepBro