Mga HTTP method: GET, POST, PUT, PATCH, DELETE at iba pa
Walo ang HTTP method sa RFC 9110, hindi lima. Alamin kung kailan GET o POST, kailan PUT o PATCH, para saan ang HEAD at OPTIONS, at paano sila limitahan sa nginx.
Ilan ba talaga ang HTTP methods?
Walo ang HTTP methods na tinukoy ng RFC 9110: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS at TRACE. Wala sa listahang iyon ang PATCH, dahil galing ito sa hiwalay na dokumento, ang RFC 5789. Kaya kulang ang "limang HTTP methods" na madalas ituro. GET, POST, PUT, PATCH at DELETE lang ang laman niyon: ang mga method na ginagamit ng karamihan ng REST API para sa CRUD (create, read, update, delete).
Kung GET at POST lang ang nagamit mo sa capstone o sa unang API project mo, normal iyon. Pero kapag may sarili ka nang server, puwede mong makita sa logs ang iba pang method. Halimbawa, HEAD mula sa curl -I, o OPTIONS mula sa browser bago ang isang cross-origin na API call. Ipapaliwanag ng gabay na ito ang bawat isa, gamit ang nginx server na ikaw mismo ang nagpapatakbo. Kung bago pa sa iyo ang web server at kung ano ang ginagawa nito, doon ka muna magsimula.
Saan nakasulat ang method sa isang HTTP request?
Ang method ang unang salita ng request line. Sa HTTP/1.1, ganito ang ayos ayon sa RFC 9112: method, space, request-target, space, at HTTP version.
POST /api/items HTTP/1.1Dito, POST ang method at /api/items ang request-target. Ang HTTP/1.1 ang version. Case-sensitive ang method, kaya magkaiba ang get at GET. Para sa buong anyo ng request at response, pati ang mga status code, basahin ang paliwanag kung ano ang HTTP at paano ito gumagana. Hindi na namin iyon uulitin dito.
Safe at idempotent: ang dalawang salitang dapat mong kabisaduhin
Dalawang katangian ang naghihiwalay sa mga method. Kapag naintindihan mo ang dalawang ito, madali nang pumili ng tamang method para sa bawat endpoint.
Safe ang method kapag read-only ang kahulugan nito. Ayon sa RFC 9110, hindi humihingi at hindi umaasa ang client ng anumang pagbabago ng state sa server kapag safe na method ang gamit. Safe ang GET, HEAD, OPTIONS at TRACE.
May ginagawa pa rin ang server kahit safe ang method. Binanggit mismo ng RFC 9110 na karamihan ng server ay nagdadagdag ng linya sa access log pagkatapos ng bawat response, anuman ang method. Ang "safe" ay tungkol lamang sa hinihingi ng client.
Idempotent ang method kapag pareho ang intended na epekto sa server ng isang request at ng maraming magkakaparehong kopya nito. Idempotent ang PUT at ang DELETE, pati ang lahat ng safe na method. Wala ang POST sa listahang iyon. Ang PATCH naman ay sinabi ng RFC 5789 na hindi safe at hindi rin idempotent.
Ito ang buod:
- GET: safe, idempotent
- HEAD: safe, idempotent
- OPTIONS: safe, idempotent
- TRACE: safe, idempotent
- PUT: hindi safe, idempotent
- DELETE: hindi safe, idempotent
- POST: hindi safe, hindi nakalistang idempotent
- CONNECT: hindi safe, hindi nakalistang idempotent
- PATCH (galing sa RFC 5789): hindi safe, hindi idempotent
May isa pang patakaran sa RFC 9110 na dapat mong malaman. Lahat ng general-purpose na server ay MUST na sumuporta sa GET at HEAD. Optional ang lahat ng iba pa.
GET vs POST: bakit hindi dapat GET ang form na nagbabago ng data
Halimbawa, inventory system para sa isang sari-sari store ang capstone mo. May link sa admin page na ganito: /items/delete?id=42. GET ito, kaya mabubura ang item 42 sa sandaling may magbukas ng link.
Mali ito dahil safe ang GET ayon sa depinisyon. Ang program na sumusunod lang sa mga link, gaya ng crawler, ay malayang magpadala ng GET dahil inaasahan nitong walang mababago. Kapag sinundan ng isang bot ang mga link sa page na iyon, bawat link na sinundan nito ay isang delete. Makikita mo sa access log kung may bot na pumapasok sa server mo, at may hiwalay na gabay tungkol sa pag-block ng AI crawlers sa server mo.
Pangalawang problema: napupunta sa log ang buong URL. Sa nginx, ang $request ay ang buong orihinal na request line, kasama ang query string. Kaya kung GET ang login form mo, ganito ang puwedeng lumabas sa access log:
203.0.113.25 - - [24/Oct/2026:09:14:03 +0800] "GET /login?user=juan&password=sikreto123 HTTP/1.1" 200 512 "-" "Mozilla/5.0"Nakasulat na ngayon ang password sa isang file na nababasa ng sinumang may access sa logs. Sa POST, nasa body ang form data, at walang variable para sa body sa default na combined format. Pero nababasa pa rin ang body habang bumibiyahe kung plain HTTP ang gamit mo, kaya basahin din ang HTTP vs HTTPS sa sarili mong server.
Pangatlo: ayon sa RFC 9110, walang pangkalahatang kahulugan ang content sa isang GET request. Kaya huwag magpadala ng JSON body sa GET at umasang babasahin ito ng bawat server o proxy sa daan. Ilagay sa query string ang mga filter. Gamitin ang POST, PUT, PATCH o DELETE kapag may babaguhin.
Ang patakaran: kapag may nababago sa database, hindi GET ang method.
PUT vs PATCH vs POST: alin ang para sa update?
Dito madalas magkamali sa API project. Magkakaiba ang ibig sabihin ng mga method na ito.
POST ay humihiling sa target resource na iproseso ang ipinadalang representation ayon sa sarili nitong patakaran. Malawak ang kahulugang ito. Sa karamihan ng REST API, POST /api/items ang paraan para gumawa ng bagong item, at ang server ang pumipili ng ID nito.
PUT ay humihiling na gawin o palitan ang state ng target resource gamit ang state na nasa request. Buong record ang ipinapadala mo.
curl -i -X PUT https://api.example.com/api/items/42 \
-H 'Content-Type: application/json' \
-d '{"name": "Sardinas 155g", "price": 24, "stock": 30}'Dahil "palitan" ang kahulugan, kung {"price": 25} lang ang ipadala mo sa PUT, ang tamang basa ng server ay ito na ang buong item. Mawawala ang name at stock sa server na sumusunod dito. Idempotent ang PUT. Ipadala mo man ito nang isang beses o sampung beses, iisa ang huling state ng item 42.
PATCH ay para sa bahagyang pagbabago. Ito mismo ang dahilan kung bakit isinulat ang RFC 5789. Pinapalitan ng PUT ang buong resource, kaya hindi ito magagamit para sa partial na update.
curl -i -X PATCH https://api.example.com/api/items/42 \
-H 'Content-Type: application/json' \
-d '{"price": 25}'Hindi idempotent ang PATCH ayon sa RFC 5789. Tingnan ang isang PATCH na ganito ang laman: {"stock_add": 5}. Kapag naipadala ito nang dalawang beses, madadagdagan ng 10 ang stock, hindi 5. Ang {"price": 25} naman ay pareho ang resulta kahit ilang beses ipadala, pero desisyon iyon ng app mo. Hindi ito ipinapangako ng spec, kaya hindi ito puwedeng asahan ng client.
DELETE ay humihiling sa server na tanggalin ang ugnayan ng target resource sa kasalukuyan nitong functionality. Sa praktika, burahin ang item. Idempotent ito. Pagkatapos ng unang DELETE, wala na ang item, at hindi na iyon nagbabago sa pangalawa. Puwedeng magkaiba ang status code ng dalawang sagot. Ayos lang iyon, dahil ang idempotency ay tungkol sa epekto sa server.
Bakit puwedeng magdoble ang record kapag na-retry ang POST?
Isipin ang order button sa mobile app mo. Mahina ang signal. Ipinadala ng app ang POST /api/orders, natanggap ito ng server, at nag-save ito ng order. Pero hindi nakabalik ang response sa phone. Nag-timeout ang app at nag-retry. Dalawa na ngayon ang order.
Nangyari ito dahil hindi idempotent ang POST, kaya bawat kopya ay bagong order. Ito ang dahilan kung bakit sinasabi ng RFC 9110 na hindi dapat awtomatikong mag-retry ang client ng request na may non-idempotent na method, maliban kung may paraan itong malaman na idempotent pala ang semantics ng request. Kapag nangyari ito sa server mo, makikita mo sa access log ang dalawang magkaparehong POST /api/orders na halos sabay ang oras.
Dalawa ang karaniwang solusyon. Una, huwag i-retry nang awtomatiko ang POST sa frontend code. Pangalawa, magpadala ang client ng sariling unique na ID sa bawat order para matanggihan ng server ang duplicate. Sa PUT, hindi problema ang retry, dahil iisa ang resulta.
HEAD: ang ipinapadala ng curl -I
Ang HEAD ay kapareho ng GET, maliban na MUST NOT magpadala ang server ng content sa response. Headers lang ang babalik. Kapaki-pakinabang ito kapag gusto mo lang malaman kung buhay ang page, o kapag headers lang ang kailangan mo, nang hindi dina-download ang buong file.
Ang curl -I, o ang mahabang anyo nitong --head, ay nagpapadala ng HEAD:
curl -I https://example.com/Huwag gamitin ang curl -X HEAD para dito. Ayon sa curl man page, pinapalitan lang ng -X ang salitang nakasulat sa request. Hindi nito binabago ang kilos ng curl, kaya hindi iyon sapat para sa tamang HEAD request. Ang --head ang gamitin.
Kung may uptime monitor kang naka-set up, alamin kung HEAD o GET ang ipinapadala nito. Tingnan ang docs ng monitor. Mas mabilis pa, hanapin ang user agent nito sa access log mo at basahin ang method sa simula ng request line.
Dahil MUST na suportahan ng general-purpose server ang HEAD, huwag itong i-block nang hindi sinasadya. Sa nginx, awtomatikong pinapayagan ang HEAD kapag pinayagan mo ang GET sa limit_except, gaya ng makikita sa ibaba.
OPTIONS at ang CORS preflight
Ipagpalagay na nasa https://app.example.com ang frontend mo at nasa https://api.example.com ang API. Cross-origin ang bawat API call dito. Bago ang ilang ganitong call, nagpapadala muna ang browser ng preflight. Isa itong OPTIONS request na may Access-Control-Request-Method header, at nasa header na iyon ang method na balak gamitin ng browser. Ayon sa Fetch Standard, ito ang paraan ng browser para alamin kung naiintindihan ng server ang CORS (cross-origin resource sharing) protocol.
GET, HEAD at POST lang ang mga CORS-safelisted method. Ang request na gumagamit ng ibang method, halimbawa PUT, PATCH o DELETE, ay puwedeng mangailangan ng preflight. Puwede ring kailanganin ito ng POST kapag may header itong wala sa safelist. Kaya kapag binuksan mo ang Network tab ng DevTools habang nagse-save ng item, puwede kang makakita ng OPTIONS bago ang totoong PUT.
Mas madaling i-debug ang preflight kapag ginaya mo ito gamit ang curl:
curl -i -X OPTIONS https://api.example.com/api/items/42 \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: PUT'Basahin mo mismo ang status line at ang mga Access-Control-Allow-* header sa sagot. Depende ang laman nito sa app at config mo, kaya walang iisang tamang output na maipapakita rito. Ihambing ang sagot sa origin at method na talagang ipinapadala ng frontend mo.
Saan makikita ang method sa nginx access log?
Ito ang predefined na combined format ng nginx. Laging kasama ito sa configuration, kaya huwag mo na itong idagdag sa config mo:
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';Ang $request ang buong orihinal na request line. Kaya ang unang salita sa loob ng unang pares ng double quotes ang method. Para malaman kung saan isinusulat ang log sa server mo, hanapin ang access_log directive:
sudo nginx -T 2>/dev/null | grep access_logTine-test ng nginx -T ang config at ipinapakita ang buong laman nito. Bawat access_log na lalabas ay may path ng log file, at kung meron, ang pangalan ng format. Kapag custom ang format at hindi combined, puwedeng nasa ibang puwesto ang $request.
Bilangin ang mga method sa log. Palitan ang path ng nakita mo sa itaas:
LOG=/var/log/nginx/access.log
sudo awk -F'"' '{print $2}' "$LOG" | cut -d' ' -f1 | sort | uniq -c | sort -rnHinahati ng awk -F'"' ang bawat linya sa mga double quote, kaya ang $2 ay ang request line. Kinukuha ng cut ang unang salita nito, ang method. Bawat linya ng output ay isang bilang at isang method. Kung may method kang makita na hindi ginagamit ng app mo, tingnan ang mga linyang iyon:
sudo grep '"OPTIONS ' "$LOG" | tail -n 5Paano limitahan ang methods gamit ang limit_except ng nginx?
Inilalagay ang limit_except sa loob ng isang location block. Ililista mo ang mga method na papayagan. Ang mga directive sa loob ng block, gaya ng allow at deny mula sa access module o ng auth_basic, ay ilalapat sa lahat ng ibang method. Kapag pinayagan mo ang GET, pinapayagan na rin ang HEAD.
Para sa static site na walang tinatanggap na form:
location / {
limit_except GET {
deny all;
}
}GET at HEAD lang ang dadaan dito nang walang paghihigpit. Sakop ng deny all ang lahat ng ibang method.
Para sa API sa likod ng reverse proxy, kung saan para lang sa admin mula sa isang IP ang ibang pagbabago ng data:
location /api/ {
limit_except GET POST {
allow 203.0.113.10;
deny all;
}
proxy_pass http://127.0.0.1:8000;
}Malayang dadaan ang GET, HEAD at POST. Ang PUT, PATCH, DELETE at OPTIONS ay papayagan lang mula sa 203.0.113.10. Palitan iyon ng sarili mong IP. Kung bago sa iyo ang proxy_pass, basahin ang paliwanag ng nginx reverse proxy config.
Bantayan ang epekto nito sa CORS. Wala ang OPTIONS sa listahan, kaya sakop din ng deny all ang preflight ng browser na galing sa ibang IP. Kung may cross-origin na frontend kang gumagamit ng PUT sa API na ito, buksan ang Network tab at tingnan kung ano ang nangyari sa OPTIONS request.
Bukod sa GET, HEAD, POST, PUT, DELETE at OPTIONS, tumatanggap din ang limit_except ng PATCH at ng ilang WebDAV method gaya ng MKCOL at PROPFIND.
I-test ang config at i-reload ang nginx:
sudo nginx -t
sudo systemctl reload nginxDapat sabihin ng nginx -t na syntax is ok at test is successful. Kung hindi, basahin ang error at ang line number na binanggit nito bago mag-reload.
Pagkatapos, mula sa ibang makina na hindi 203.0.113.10:
curl -i -X DELETE https://api.example.com/api/items/42Basahin mo mismo ang status line at ang headers. Hindi namin isusulat dito ang inaasahang output. Subukan mo at tingnan. Pagkatapos, hanapin ang parehong request sa access log para makita ang method at status code na itinala ng nginx.
Isang layer lang ang limit_except sa harap ng app mo. Hindi nito pinapalitan ang authorization sa loob ng app. Dapat tumanggi pa rin ang app sa DELETE mula sa user na walang permiso.
405 o 501: ano ang sinasabi ng spec?
May dalawang status code na binabanggit ang RFC 9110 para sa method na hindi tinatanggap.
- 405 Method Not Allowed: kilala ng origin server ang method, pero hindi ito suportado ng target resource. MUST na may kasamang
Allowheader ang 405 response. Nakalista roon ang mga method na kasalukuyang suportado ng resource. - 501 Not Implemented: SHOULD itong isagot ng origin server kapag hindi nito kilala o hindi ipinatupad ang method.
Kung sumasagot ang sarili mong API ng 405, tingnan kung may Allow header:
curl -i -X PATCH https://api.example.com/api/itemsKapag 405 ang status at walang Allow sa headers, hindi sumusunod ang app mo sa RFC 9110, at madali itong ayusin sa code. Hindi sinasabi ng gabay na ito kung alin sa dalawa ang isinasagot ng nginx o ng framework mo. Iyan mismo ang ipapakita ng curl sa server mo.
Subukan ang bawat method sa sarili mong server
Huwag subukan ang PUT, PATCH o DELETE sa production database. Gumamit ng test API, o gumawa ng mock gamit ang gabay sa self-hosted na API testing at mocking. Ito ang buong set, isang method bawat linya:
curl -i https://api.example.com/api/items
curl -I https://api.example.com/api/items
curl -i -X POST https://api.example.com/api/items -H 'Content-Type: application/json' -d '{"name": "Kape 3-in-1", "price": 8, "stock": 100}'
curl -i -X PUT https://api.example.com/api/items/42 -H 'Content-Type: application/json' -d '{"name": "Sardinas 155g", "price": 24, "stock": 30}'
curl -i -X PATCH https://api.example.com/api/items/42 -H 'Content-Type: application/json' -d '{"price": 25}'
curl -i -X DELETE https://api.example.com/api/items/42
curl -i -X OPTIONS https://api.example.com/api/itemsIpinapakita ng -i ang response headers kasama ng body. Pagkatapos ng bawat command, tingnan ang status code, at hanapin ang linya nito sa access log.
Isang babala tungkol sa -X. Kapag ginamit mo ito kasama ng --location (-L), gagamitin ng curl ang parehong method sa bawat redirect na susundan nito. Binabanggit ng man page na puwede itong magdulot ng hindi inaasahang epekto. Kaya kapag nag-redirect ang server, halimbawa mula HTTP papuntang HTTPS, ilagay na lang ang tamang URL sa command sa halip na magdagdag ng -L.
FAQ
Ilan ang HTTP methods, lima ba o walo?
Walo ang tinukoy ng RFC 9110: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS at TRACE. Ang PATCH ay galing sa hiwalay na RFC 5789 mula Marso 2010. Ang "limang method" na itinuturo sa maraming tutorial ay ang GET, POST, PUT, PATCH at DELETE, ang subset na ginagamit para sa CRUD sa REST API.
Ano ang pagkakaiba ng PUT at PATCH?
Ginagawa o pinapalitan ng PUT ang buong state ng resource gamit ang ipinadala mo. Idempotent ito, kaya walang dagdag na epekto kapag naulit. Ang PATCH ay para sa bahagyang pagbabago, at ayon sa RFC 5789, hindi ito safe at hindi rin idempotent. Gamitin ang PUT kapag buong record ang ipinapadala mo, at PATCH kapag ilang field lang ang babaguhin.
Bakit may OPTIONS request sa log ko bago ang PUT o DELETE?
CORS preflight iyon. GET, HEAD at POST lang ang CORS-safelisted method. Bago ang cross-origin na request na gumagamit ng ibang method, puwedeng magpadala muna ang browser ng OPTIONS na may Access-Control-Request-Method header. Kung naglagay ka ng limit_except sa nginx na hindi kasama ang OPTIONS, sakop din ng mga rule nito ang preflight.
Bakit hindi dapat GET ang form na nagbubura o nagse-save ng data?
Safe ang GET ayon sa RFC 9110, kaya ang mga program na sumusunod lang sa link ay malayang magpadala nito. Kung may binabago ang GET mo, bawat pagsunod sa link ay pagbabago sa database. Isinusulat din ng nginx ang buong request line sa access log, kasama ang query string, kaya mapupunta sa log ang anumang form data sa URL. Gamitin ang POST, PUT, PATCH o DELETE para sa anumang nagbabago ng data.
Paano ko malalaman kung anong method ang ipinapadala ng uptime monitor ko?
Tingnan ang access log ng server. Sa combined format, ang unang salita sa loob ng unang pares ng double quotes ang method, kaya hanapin ang linya na may user agent ng monitor. Kung HEAD ang lumabas, headers lang ang hinihingi nito. Para sa sarili mong check mula sa terminal, curl -I ang nagpapadala ng tamang HEAD request.