HTTP POST & Mengirim Data
Kirim data ke API: login, tambah produk, dengan body JSON.
Kenapa Ada POST Kalau Sudah Ada GET?
GET itu untuk mengambil data, dan datanya nempel di URL. Coba bayangkan login pakai GET: https://api.contoh.com/login?email=x&password=rahasia123. Password-mu nyangkut di log server, history browser, dan bisa diintip siapa saja yang melihat URL itu. POST mengirim data di body request, bukan di URL, jadi aman untuk kredensial. Selain itu server tahu request ini bermaksud mengubah sesuatu: membuat user, menambah produk, memproses pembayaran.
Aturan praktis: GET tidak boleh mengubah data di server, POST boleh. Itu kenapa browser memperingatkanmu saat me-refresh halaman hasil POST, tapi tidak untuk GET.
Contoh 1: POST JSON Sederhana
Future<bool> tambahProduk(String nama, int harga) async {
final res = await http.post(
Uri.parse('https://api.contoh.com/produk'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'nama': nama, 'harga': harga}),
);
return res.statusCode == 201;
}Jangan lupa header Content-Type: application/json (tanpanya server bisa menolak dengan error 415) dan jsonEncode untuk mengubah Map jadi string JSON. Status sukses "data berhasil dibuat" biasanya 201, bukan 200.
Contoh 2: Login Lengkap dengan Penanganan Error
Future<String> login(String email, String password) async {
final res = await http.post(
Uri.parse('https://api.contoh.com/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'email': email, 'password': password}),
).timeout(const Duration(seconds: 10));
switch (res.statusCode) {
case 200:
final data = jsonDecode(res.body) as Map<String, dynamic>;
final token = data['token'] as String?;
if (token == null) throw Exception('Respons server tidak valid');
return token;
case 401:
throw Exception('Email atau password salah');
case 422:
final data = jsonDecode(res.body) as Map<String, dynamic>;
throw Exception(data['message'] ?? 'Data tidak valid');
default:
throw Exception('Login gagal (${res.statusCode})');
}
}Setiap status code diterjemahkan jadi pesan yang dimengerti pengguna; jangan tampilkan "401" mentah. Status 422 (validation error) juga umum: server menolak format data yang salah dan biasanya menyertakan pesan di body.
Mengirim Token di Request Berikutnya
Setelah login, endpoint yang butuh autentikasi menerima token lewat header:
final res = await http.get(
Uri.parse('https://api.contoh.com/profil'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
);Catatan teknis: Jangan hardcode token di kode. Setelah login berhasil, simpan token di
flutter_secure_storage(terenkripsi di device), lalu baca saat aplikasi dibuka untuk request yang butuh autentikasi.
Format Body Lain: Form dan Upload File
Tidak semua API menerima JSON. Tiga format umum yang wajib kamu kenal:
// 1. Form-urlencoded (API lama / endpoint token OAuth):
final res = await http.post(
Uri.parse('https://api.contoh.com/token'),
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: {'grant_type': 'password', 'username': email, 'password': password},
);
// 2. Multipart (upload foto + data teks sekaligus):
final req = http.MultipartRequest(
'POST',
Uri.parse('https://api.contoh.com/produk'),
);
req.fields['nama'] = 'Kopi Susu';
req.files.add(await http.MultipartFile.fromPath('foto', pathFile));
final streamed = await req.send();
final uploadOk = streamed.statusCode == 201;Untuk form-urlencoded, http menerima Map langsung tanpa jsonEncode. Untuk upload file, pakai MultipartRequest lalu send(), dan ingat responsnya berupa StreamedResponse yang status codenya tetap bisa dibaca.
Edge Case dan Best Practice
- Cegah double-submit. Nonaktifkan tombol saat request berjalan; kalau tidak, pengguna bisa menekan dua kali dan produk terbuat dua kali.
- Jangan retry POST sembarangan. GET aman diulang, tapi mengulang POST pembayaran bisa menagih dua kali. Kalau butuh retry, pastikan API mendukung idempotency key.
- Validasi dulu di client. Cek email kosong atau password terlalu pendek sebelum request dikirim, supaya tidak buang-buang request dan pengguna dapat feedback instan.
- Timeout tetap wajib. Sama seperti GET, POST tanpa timeout bisa menggantung selamanya di jaringan buruk.
Kapan JANGAN Pakai POST
- Untuk mengambil data, pakai GET. POST untuk membaca data merusak konvensi REST dan membuat response tidak bisa di-cache oleh sistem.
- Untuk update sebagian atau hapus, pakai method yang semestinya (PATCH, PUT, DELETE) kalau API-mu mendukungnya. POST serba-bisa itu tanda API yang malas didesain, tapi kalau memang begitu API yang kamu hadapi, ikuti saja dokumentasinya.
Tantangan
POST produk baru
Buat fungsi tambahProduk(nama, harga) yang POST JSON ke https://jsonplaceholder.typicode.com/posts dan return true jika status 201.