Gửi POST bằng curl: JSON, form, file và retry an toàn
Thực hành ba kiểu curl POST—JSON, form-urlencoded và upload file—rồi kiểm tra header, status, response body, timeout, retry và idempotency với endpoint local placeholder.
Tác giảYiyao
Một yêu cầu POST bằng curl có thể gửi dữ liệu mới hoặc yêu cầu máy chủ thực hiện một hành động. Cú pháp chỉ vài dòng, nhưng một request đáng tin cậy phải nói rõ định dạng body, Content-Type, status code, response body và cách retry mà không vô tình tạo bản ghi trùng.
Bài này dùng http://localhost:3000/api/posts làm endpoint placeholder local để minh họa hình dạng lệnh; đây không phải API đã được xác nhận của Arcvenza. Nếu chỉ cần một website công khai để quan sát response, có thể dùng https://example.com/, nhưng đó là trang web chứ không phải POST endpoint có tài liệu và request có thể bị từ chối.
Bắt đầu bằng contract của request
Trước khi viết lệnh, hãy ghi lại method, URL, header bắt buộc, cấu trúc body, status thành công và cấu trúc lỗi. Tiêu chí nghiệm thu ở đây là: handler local nhận đúng field, trả về status 2xx theo contract và có response body đọc được dưới dạng JSON. Status 4xx hoặc 5xx vẫn là kết quả ứng dụng thất bại dù tiến trình curl có thể kết thúc với exit code bằng 0.
1. Gửi JSON với application/json
JSON phù hợp khi máy chủ cần object lồng nhau, boolean, số hoặc một API schema rõ ràng. Body được truyền như một chuỗi nên cần chú ý cách shell xử lý dấu ngoặc kép.
curl --request POST "http://localhost:3000/api/posts" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{"title":"curl demo","published":false}'
Input cần kiểm tra: máy chủ nhận một JSON object có title là curl demo và published là false. Output cần kiểm tra: status 2xx và response body tương tự {"id":"local-id","title":"curl demo","published":false}. Trường id chỉ là ví dụ của handler local, không phải lời khẳng định rằng Arcvenza có service như vậy.
2. Gửi field dạng form-urlencoded
Form URL encoded phù hợp với các field phẳng hoặc handler theo quy ước HTML form truyền thống. --data-urlencode mã hóa khoảng trắng và ký tự đặc biệt; ghi rõ header giúp nhìn thấy format trên wire.
curl --request POST "http://localhost:3000/api/posts" \
--header "Content-Type: application/x-www-form-urlencoded" \
--header "Accept: application/json" \
--data-urlencode "title=curl form demo" \
--data-urlencode "tag=developer tutorials"
Input cần kiểm tra: hai field có tên title và tag. Output cần kiểm tra: handler parse cả hai dưới dạng chuỗi rồi trả về response 2xx theo tài liệu. Nếu server yêu cầu JSON thì body này sai format dù URL và method đều đúng.
3. Upload file với multipart/form-data
Khi request có file, hãy dùng multipart form. curl tự tạo multipart boundary khi dùng -F; đừng tự viết boundary và đừng ghi đè Content-Type do curl tạo ra.
curl --request POST "http://localhost:3000/api/uploads" \
--header "Accept: application/json" \
--form "file=@./sample.txt;type=text/plain" \
--form "purpose=curl-post-tutorial"
Input cần kiểm tra: file local ./sample.txt có thể đọc được và có thêm field purpose. Output cần kiểm tra: máy chủ xác nhận field file, media type và kích thước file. Nếu file không tồn tại, curl sẽ lỗi trước khi gửi request; hãy kiểm tra path và quyền đọc.
Header, status code và response body
Content-Type mô tả format của request body; Accept mô tả format response mà client ưu tiên, nên hai header này không thay thế nhau. 201 Created thường cho biết resource đã được tạo, 200 OK là response bình thường, 400–499 cho biết request hoặc credential cần sửa, còn 500–599 cho thấy lỗi ở server hoặc dependency phía sau. Contract cụ thể của API vẫn là nguồn quyết định cuối cùng.
curl --request POST "http://localhost:3000/api/posts" \
--header "Content-Type: application/json" \
--data '{"title":"inspect response"}' \
--dump-header response.headers \
--output response.json \
--write-out "status=%{http_code}\ntime=%{time_total}s\n"
Cách nghiệm thu: response.headers lưu status và response headers; response.json lưu response body; dòng cuối trên terminal in ra status dạng số và tổng thời gian. Đừng xem một body không rỗng là thành công. Hãy kiểm tra status trước rồi mới xác thực các field nghiệp vụ.
Timeout và retry
Hãy đặt cả connection timeout và total timeout. --connect-timeout giới hạn thời gian chờ thiết lập kết nối; --max-time giới hạn toàn bộ lần truyền. Chỉ retry lỗi có thể lặp an toàn, chẳng hạn lỗi kết nối tạm thời hoặc trường hợp 429/5xx mà API ghi rõ là có thể retry.
curl --request POST "http://localhost:3000/api/posts" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: local-curl-demo-001" \
--data '{"title":"retry-aware demo"}' \
--connect-timeout 5 \
--max-time 20 \
--retry 3 \
--retry-delay 2 \
--retry-max-time 30
Idempotency-Key chỉ có ý nghĩa khi server có tài liệu và thực sự thực thi semantics idempotent. Nếu không có contract đó, timeout là trạng thái mơ hồ: server có thể đã tạo record nhưng client chưa nhận được response. Tránh dùng --retry-all-errors cho POST làm thay đổi trạng thái nếu chưa hiểu rõ side effect trùng lặp.
Bảng quyết định retry bằng lời
Lỗi truyền xảy ra trước khi server nhận body: thường có thể cân nhắc retry. Response 429 kèm Retry-After: chờ đúng khoảng thời gian, rồi retry nếu thao tác được phép lặp. Response 500 hoặc 503: chỉ retry khi API cho phép và request có tính idempotent. Response 400, 401, 403 hoặc 422: sửa request hoặc credential thay vì retry nguyên trạng. Timeout sau khi upload: dùng idempotency key hoặc token đối soát để kiểm tra kết quả trước khi gửi lại cùng POST.
Nghiệm thu trước khi kết nối service thật
Chạy cả ba lệnh JSON, form và file với handler local hoặc test service được cho phép. Kiểm tra Content-Type nhận được, field sau khi parse, metadata của file, status, response body và thời gian. Không đưa credential vào shell history và không chèn token thật vào tutorial. Khi muốn kết nối workflow này với Arcvenza, hãy bắt đầu từ hướng dẫn thật ở /documentation và /quick-start-guides; /products/crawler-console là trang sản phẩm, không phải bằng chứng về một POST API cụ thể.
Bạn có thể xem thêm documentation, quick-start guides của Arcvenza hoặc trang sản phẩm Crawler Console. Hãy xác nhận contract hiện tại trước khi thêm URL production.
