Можно ли отправить данные в теле DELETE-запроса из Flutter-приложения?

Ответ

Технически отправить тело в DELETE-запросе можно, но это противоречит общепринятой практике и может не поддерживаться сервером.

1. Использование пакета http:

import 'package:http/http.dart' as http;

Future<void> deleteWithBody() async {
  final response = await http.delete(
    Uri.parse('https://api.example.com/resource/123'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({'reason': 'obsolete', 'deletedBy': 'user123'}),
  );

  if (response.statusCode == 200) {
    print('Deleted successfully');
  }
}

2. Использование пакета dio (более гибкий):

import 'package:dio/dio.dart';

Future<void> deleteWithDio() async {
  final dio = Dio();
  final response = await dio.delete(
    'https://api.example.com/resource/123',
    data: {'reason': 'obsolete'},
    options: Options(contentType: Headers.jsonContentType),
  );
  print(response.data);
}

Проблемы и рекомендации:

  • Серверная поддержка: Многие фреймворки (Express.js, Spring) по умолчанию игнорируют тело DELETE-запроса
  • Прокси и кэши: Некоторые прокси-серверы могут удалять тело из DELETE-запросов
  • REST-практика: Согласно REST, идентификатор ресурса должен передаваться в URL, а дополнительные параметры — в query-параметрах

Альтернативные подходы:

// 1. Использование query-параметров (рекомендуется)
await http.delete(
  Uri.parse('https://api.example.com/resource/123?reason=obsolete&deletedBy=user123'),
);

// 2. Использование POST для операции удаления с телом
await http.post(
  Uri.parse('https://api.example.com/resource/123/delete'),
  body: jsonEncode({'reason': 'obsolete'}),
);

В Flutter-разработке лучше согласовать формат DELETE-запросов с бэкенд-командой и следовать их API-контракту.

Ответ 18+ 🔞

А, ну это же классика, блядь! Сидишь такой, пишешь на Flutter'е, всё красиво, а потом — бац! — нужно отправить DELETE с телом. И тут начинается ёперный театр.

Смотри, технически-то это сделать можно, ёпта. Взять пакет http и тупо сунуть body в delete(). Вот смотри, как просто:

import 'package:http/http.dart' as http;

Future<void> deleteWithBody() async {
  final response = await http.delete(
    Uri.parse('https://api.example.com/resource/123'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({'reason': 'obsolete', 'deletedBy': 'user123'}),
  );

  if (response.statusCode == 200) {
    print('Deleted successfully');
  }
}

Вроде бы логично: хочу удалить запись и передать причину. Но не всё так просто, чувак. Это как прийти в гости и начать выносить мебель, при этом ещё и объяснительную записку хозяину сувать в руки. Доверия ебать ноль, что он это правильно поймёт.

А если взять dio — там вообще красота, он более гибкий, как хитрая жопа:

import 'package:dio/dio.dart';

Future<void> deleteWithDio() async {
  final dio = Dio();
  final response = await dio.delete(
    'https://api.example.com/resource/123',
    data: {'reason': 'obsolete'},
    options: Options(contentType: Headers.jsonContentType),
  );
  print(response.data);
}

Но вот в чём прикол: сервер-то может быть консервативным, как мой дед. Многие фреймворки, типа Express.js или Spring, по умолчанию просто игнорируют тело в DELETE. Представь: ты принёс ему объяснительную, а он её в урну выкинул, даже не глянув. Волнение ебать — отправил ты там или нет?

И это ещё цветочки. Разные прокси-серверы или кэши могут посмотреть на такой запрос, сказать «ни хуя себе» и спокойно отрезать тело, оставив голый DELETE. И всё, приехали. Твоя причина удаления — накрылась медным тазом.

С точки зрения REST-практики — это вообще пиздопроебибна идея. Там чётко говорят: идентификатор — в URL, а всё остальное — либо в query-параметрах, либо вообще не надо. Правильнее будет вот так, без этих танцев с бубном:

// 1. Использование query-параметров (рекомендуется)
await http.delete(
  Uri.parse('https://api.example.com/resource/123?reason=obsolete&deletedBy=user123'),
);

// 2. Использование POST для операции удаления с телом
await http.post(
  Uri.parse('https://api.example.com/resource/123/delete'),
  body: jsonEncode({'reason': 'obsolete'}),
);

Второй вариант — это уже не DELETE, а какой-то кастомный эндпоинт. Но зато работает наверняка, без сюрпризов.

Так что главный совет, чувак: э бошка думай. Не лезь один на эту гору проблем. Иди к своим бэкендерам, спроси: «Мужики, а как у вас там с DELETE-запросами? Тело принимаете или я зря париться буду?». Согласуй API-контракт и делай как они скажут. Иначе получится, что ты ходишь по охуенно тонкому льду, а потом все упадут и будут искать виноватого. А виноват, как обычно, фронтенд.