ด้วยซีแมนทิกส์การแคชที่ง่ายมาก: ถ้าพารามิเตอร์เหมือนกัน (และแน่นอนเหมือนกัน) จากนั้นก็ถือว่าเป็น Hit เป็นไปได้ไหม แนะนำ?
ด้วยซีแมนทิกส์การแคชที่ง่ายมาก: ถ้าพารามิเตอร์เหมือนกัน (และแน่นอนเหมือนกัน) จากนั้นก็ถือว่าเป็น Hit เป็นไปได้ไหม แนะนำ?
คำตอบ:
RFC 2616 ที่สอดคล้องกันในส่วน 9.5 (POST) อนุญาตให้แคชการตอบสนองต่อข้อความ POST หากคุณใช้ส่วนหัวที่เหมาะสม
การตอบสนองต่อวิธีนี้จะไม่สามารถแคชได้เว้นแต่ว่าการตอบกลับจะรวมถึงการควบคุมแคชหรือฟิลด์หมดอายุของส่วนหัวที่เหมาะสม อย่างไรก็ตามการตอบสนอง 303 (ดูอื่น ๆ ) สามารถใช้เพื่อกำหนดเอเจนต์ผู้ใช้เพื่อดึงทรัพยากรที่แคชได้
หมายเหตุว่า RFC เดียวกันระบุไว้อย่างชัดเจนในมาตรา 13 (แคชใน HTTP) ที่แคชต้องโมฆะนิติบุคคลที่สอดคล้องกันหลังจาก POST คำขอ
วิธีการ HTTP บางอย่างต้องทำให้แคชใช้งานไม่ได้ นี่เป็นเอนทิตีที่อ้างถึงโดย Request-URI หรือโดยส่วนหัว Location หรือ Content-Location (ถ้ามี) วิธีการเหล่านี้คือ:
- PUT - DELETE - POST
ยังไม่ชัดเจนสำหรับฉันว่าข้อกำหนดเหล่านี้ช่วยให้การแคชมีความหมายได้อย่างไร
สิ่งนี้ยังสะท้อนและชี้แจงเพิ่มเติมในRFC 7231 (มาตรา 4.3.3) ซึ่งล้าสมัย RFC 2616
การตอบสนองต่อคำขอ POST สามารถแคชได้เมื่อมี
ข้อมูลความสดใหม่ที่ชัดเจน (ดูหัวข้อ 4.2.1 จาก [RFC7234])
อย่างไรก็ตามการแคช POST ไม่ได้นำไปใช้อย่างกว้างขวาง สำหรับกรณีที่เซิร์ฟเวอร์ต้นทางต้องการให้ลูกค้าสามารถแคชผลลัพธ์ของ POST ด้วยวิธีที่สามารถนำกลับมาใช้ใหม่ในภายหลัง GET เซิร์ฟเวอร์ต้นทางอาจส่งการตอบสนอง 200 (OK) ที่มีผลลัพธ์และตำแหน่งเนื้อหา ฟิลด์ส่วนหัวที่มีค่าเดียวกับ URI คำขอที่มีประสิทธิภาพของ POST (ส่วน 3.1.4.2)
ตามนี้ผลลัพธ์ของ POST ที่ถูกแคช (หากความสามารถนี้ถูกระบุโดยเซิร์ฟเวอร์) สามารถนำมาใช้เป็นผลลัพธ์ของการร้องขอ GET สำหรับ URI เดียวกัน
ตามที่ RFC 2616 มาตรา 9.5:
"วิธีการตอบสนองต่อ POST ไม่สามารถแคชได้เว้นแต่จะมีคำตอบรวมถึงการควบคุมแคชหรือฟิลด์ส่วนหัวหมดอายุ"
ดังนั้นใช่คุณสามารถแคชคำขอการตอบสนอง POST แต่ถ้ามันมาพร้อมกับส่วนหัวที่เหมาะสม ในกรณีส่วนใหญ่คุณไม่ต้องการแคชการตอบสนอง แต่ในบางกรณี - เช่นถ้าคุณไม่ได้บันทึกข้อมูลใด ๆ บนเซิร์ฟเวอร์ - มันเหมาะสมอย่างยิ่ง
หมายเหตุอย่างไรก็ตามเบราว์เซอร์จำนวนมากรวมถึง Firefox 3.0.10 ปัจจุบันจะไม่แคชการตอบสนอง POST โดยไม่คำนึงถึงส่วนหัว IE ทำงานอย่างชาญฉลาดมากขึ้นในส่วนนี้
ตอนนี้ฉันต้องการขจัดความสับสนเกี่ยวกับ RFC 2616 S. 13.10 วิธีการโพสต์ใน URI ไม่ได้ "ทำให้ทรัพยากรสำหรับแคช" เป็นโมฆะตามที่บางคนระบุไว้ที่นี่ มันทำให้รุ่นที่แคชไว้ก่อนหน้านี้ของ URI เก่าถึงแม้ว่าส่วนหัวของการควบคุมแคชระบุความสดของระยะเวลานาน
GET
และPOST
คำขอเดียวกัน หากคุณเป็นแคชนั่งอยู่ระหว่างไคลเอนต์และเซิร์ฟเวอร์คุณจะเห็นGET /foo
และแคชการตอบสนอง ถัดไปคุณจะเห็นว่าPOST /foo
คุณจะต้องทำให้การตอบสนองที่แคชไว้GET /foo
ใช้POST
ไม่ได้แม้ว่าการตอบกลับจะไม่รวมส่วนหัวของการควบคุมแคชใด ๆเพราะเป็น URI เดียวกันดังนั้นถัดไปGET /foo
จะต้องทำการตรวจสอบความถูกต้องอีกครั้ง สด (หากคุณไม่ได้เห็นPOST /foo
คำขอ)
But in some cases - such as if you are not saving any data on the server - it's entirely appropriate.
. POST API นั้นมีจุดเริ่มต้นอย่างไร?
โดยรวม:
โดยทั่วไปโพสต์ไม่ได้ดำเนินการ idempotent ดังนั้นคุณไม่สามารถใช้แคชได้ GET ควรเป็นการดำเนินการ idempotent ดังนั้นจึงมักใช้สำหรับการแคช
โปรดดูมาตรา 9.1 ของHTTP 1.1 RFC 2616 เอส 9.1
นอกเหนือจากความหมายของวิธีการ GET:
วิธีการโพสต์ตัวเองมีความหมายหมายถึงการโพสต์บางสิ่งบางอย่างไปยังทรัพยากร POST ไม่สามารถแคชได้เพราะถ้าคุณทำบางสิ่งบางอย่างเมื่อเทียบกับสองครั้งเทียบกับสามครั้งแล้วคุณจะเปลี่ยนทรัพยากรของเซิร์ฟเวอร์ในแต่ละครั้ง คำขอแต่ละเรื่องมีความสำคัญและควรส่งไปยังเซิร์ฟเวอร์
วิธีการ PUT นั้นหมายถึงการใส่หรือสร้างทรัพยากร เป็นการดำเนินการ idempotent แต่จะไม่ใช้สำหรับการแคชเนื่องจากอาจมี DELETE เกิดขึ้นในระหว่างนี้
วิธีการลบเองนั้นหมายถึงความหมายในการลบทรัพยากร เป็นการดำเนินการ idempotent แต่จะไม่ถูกใช้สำหรับการแคชเนื่องจาก PUT อาจเกิดขึ้นในระหว่างนี้
เกี่ยวกับการแคชฝั่งไคลเอ็นต์:
เว็บเบราว์เซอร์จะส่งต่อคำขอของคุณเสมอแม้ว่าจะมีการตอบสนองจากการดำเนินการ POST ก่อนหน้า ตัวอย่างเช่นคุณอาจส่งอีเมลโดยใช้ Gmail แยกกันสองสามวัน อาจเป็นหัวเรื่องและเนื้อหาเดียวกัน แต่ควรส่งอีเมลทั้งสองฉบับ
เกี่ยวกับการแคชพร็อกซี:
พร็อกซีเซิร์ฟเวอร์ HTTP ที่ส่งต่อข้อความของคุณไปยังเซิร์ฟเวอร์จะไม่แคชอะไรเลยนอกจากคำขอ GET หรือ HEAD
เกี่ยวกับการแคชเซิร์ฟเวอร์:
เซิร์ฟเวอร์โดยค่าเริ่มต้นจะไม่จัดการคำขอ POST โดยอัตโนมัติผ่านการตรวจสอบแคช แต่แน่นอนว่าคำขอ POST สามารถส่งไปยังแอปพลิเคชันหรือ Add-in ของคุณและคุณสามารถมีแคชของคุณเองที่คุณอ่านเมื่อพารามิเตอร์เหมือนกัน
การทำให้ทรัพยากรใช้ไม่ได้:
การตรวจสอบHTTP 1.1 RFC 2616 S. 13.10แสดงว่าเมธอด POST ควรทำให้ทรัพยากรสำหรับการแคชใช้ไม่ได้
หากคุณแคชการตอบสนอง POST จะต้องเป็นไปตามทิศทางของเว็บแอปพลิเคชัน นี่คือสิ่งที่มีความหมายโดย "การตอบสนองต่อวิธีนี้จะไม่สามารถเข้าถึงได้เว้นแต่ว่าการตอบสนองจะรวมถึงฟิลด์ส่วนหัวการควบคุมแคชหรือการหมดอายุที่เหมาะสม"
หนึ่งสามารถสันนิษฐานได้อย่างปลอดภัยว่าแอปพลิเคชันซึ่งรู้ว่าผลลัพธ์ของ POST นั้นเป็น idempotent หรือไม่ตัดสินใจว่าจะแนบส่วนหัวควบคุมแคชที่จำเป็นและเหมาะสมหรือไม่ หากส่วนหัวที่แนะนำการแคชได้รับอนุญาตมีอยู่แอปพลิเคชันจะบอกคุณว่า POST คือ super-GET ในความเป็นจริง การใช้ POST นั้นจำเป็นเพียงเพราะปริมาณของข้อมูลที่ไม่จำเป็นและไม่เกี่ยวข้อง (สำหรับการใช้ URI เป็นคีย์แคช) ข้อมูลที่จำเป็นในการดำเนินการ idempotent
การติดตาม GET สามารถให้บริการได้จากแคชภายใต้สมมติฐานนี้
แอปพลิเคชันที่ล้มเหลวในการแนบส่วนหัวที่จำเป็นและถูกต้องเพื่อแยกความแตกต่างระหว่างการตอบสนอง POST ที่ถอดออกได้และไม่สามารถเข้าถึงได้เป็นความผิดสำหรับผลการแคชที่ไม่ถูกต้อง
ที่กล่าวว่าแต่ละโพสต์ที่เข้าชมแคชต้องการการตรวจสอบความถูกต้องโดยใช้ส่วนหัวที่มีเงื่อนไข สิ่งนี้จำเป็นในการรีเฟรชเนื้อหาแคชเพื่อหลีกเลี่ยงผลลัพธ์ของ POST ที่จะไม่ถูกสะท้อนในการตอบสนองต่อการร้องขอจนกระทั่งหลังจากอายุการใช้งานของวัตถุหมดอายุ
Mark Nottingham วิเคราะห์เมื่อเป็นไปได้ที่จะแคชการตอบสนองของ POST โปรดทราบว่าคำขอต่อมาที่ต้องการใช้ประโยชน์จากการแคชจะต้องเป็นคำขอ GET หรือ HEAD ดูเพิ่มเติมที่http semantics
โพสต์ไม่เกี่ยวข้องกับการเป็นตัวแทนของรัฐที่ระบุ 99 ครั้งจาก 100 อย่างไรก็ตามมีกรณีหนึ่งที่มัน; เมื่อเซิร์ฟเวอร์ไม่สามารถพูดได้ว่าการตอบสนอง POST นี้เป็นการแสดง URI ของเซิร์ฟเวอร์โดยการตั้งค่าส่วนหัวของเนื้อหา - สถานที่ซึ่งเป็นสิ่งเดียวกันกับคำขอของ URI เมื่อสิ่งนั้นเกิดขึ้นการตอบสนอง POST ก็เหมือนกับการตอบสนอง GET กับ URI เดียวกัน สามารถแคชและนำกลับมาใช้ใหม่ - แต่สำหรับคำขอ GET ในอนาคตเท่านั้น
หากคุณสงสัยว่าคุณสามารถแคชคำขอโพสต์และลองค้นคว้าคำตอบของคำถามนั้นได้หรือไม่คุณอาจประสบความสำเร็จไม่ได้ เมื่อค้นหา "คำขอโพสต์แคช" ผลลัพธ์แรกคือคำถาม StackOverflow
คำตอบคือส่วนผสมที่สับสนว่าการแคชควรทำงานอย่างไรการแคชทำงานตาม RFC อย่างไรการแคชควรทำงานตาม RFC อย่างไรและการแคชทำงานอย่างไรในทางปฏิบัติ เริ่มจาก RFC เดินผ่านการสาธิตว่าเบราว์เซอร์ทำงานอย่างไรจากนั้นพูดคุยเกี่ยวกับ CDNs, GraphQL และประเด็นอื่น ๆ ที่เกี่ยวข้อง
ตาม RFC คำขอ POST จะต้องทำให้แคชใช้ไม่ได้:
13.10 Invalidation After Updates or Deletions
..
Some HTTP methods MUST cause a cache to invalidate an entity. This is
either the entity referred to by the Request-URI, or by the Location
or Content-Location headers (if present). These methods are:
- PUT
- DELETE
- POST
ภาษานี้แสดงว่าคำขอ POST ไม่สามารถแคชได้ แต่นั่นไม่เป็นความจริง (ในกรณีนี้) แคชไม่ถูกต้องสำหรับข้อมูลที่เก็บไว้ก่อนหน้านี้เท่านั้น RFC (ดูเหมือนจะ) ชี้แจงอย่างชัดเจนว่าใช่คุณสามารถแคชPOST
คำขอ:
9.5 POST
..
Responses to this method are not cacheable, unless the response
includes appropriate Cache-Control or Expires header fields. However,
the 303 (See Other) response can be used to direct the user agent to
retrieve a cacheable resource.
แม้จะมีภาษานี้การตั้งค่าCache-Control
จะต้องไม่POST
ส่งคำขอต่อไปยังทรัพยากรเดียวกัน POST
ต้องส่งคำขอไปยังเซิร์ฟเวอร์:
13.11 Write-Through Mandatory
..
All methods that might be expected to cause modifications to the
origin server's resources MUST be written through to the origin
server. This currently includes all methods except for GET and HEAD.
A cache MUST NOT reply to such a request from a client before having
transmitted the request to the inbound server, and having received a
corresponding response from the inbound server. This does not prevent
a proxy cache from sending a 100 (Continue) response before the
inbound server has sent its final reply.
มันสมเหตุสมผลแค่ไหน? คุณไม่ได้แคPOST
ร้องขอคุณกำลังแคชทรัพยากร
เนื้อหาการตอบสนอง POST สามารถแคชสำหรับการร้องขอ GET ต่อมาไปยังทรัพยากรเดียวกัน ตั้งค่าLocation
หรือContent-Location
ส่วนหัวในการตอบสนอง POST เพื่อสื่อสารทรัพยากรที่ร่างกายเป็นตัวแทน ดังนั้นวิธีเดียวที่ถูกต้องทางเทคนิคในการแคชคำขอ POST สำหรับ GETs ต่อไปคือทรัพยากรเดียวกัน
คำตอบที่ถูกต้องคือ:
แม้ว่า RFC อนุญาตให้แคชคำขอไปยังทรัพยากรเดียวกัน แต่ในทางปฏิบัติเบราว์เซอร์และ CDNs ไม่ได้ใช้พฤติกรรมนี้และไม่อนุญาตให้คุณแคชคำขอ POST
แหล่งที่มา:
รับตัวอย่างแอ็พพลิเคชัน JavaScript ต่อไปนี้ (index.js):
const express = require('express')
const app = express()
let count = 0
app
.get('/asdf', (req, res) => {
count++
const msg = `count is ${count}`
console.log(msg)
res
.set('Access-Control-Allow-Origin', '*')
.set('Cache-Control', 'public, max-age=30')
.send(msg)
})
.post('/asdf', (req, res) => {
count++
const msg = `count is ${count}`
console.log(msg)
res
.set('Access-Control-Allow-Origin', '*')
.set('Cache-Control', 'public, max-age=30')
.set('Content-Location', 'http://localhost:3000/asdf')
.set('Location', 'http://localhost:3000/asdf')
.status(201)
.send(msg)
})
.set('etag', false)
.disable('x-powered-by')
.listen(3000, () => {
console.log('Example app listening on port 3000!')
})
และได้รับตัวอย่างหน้าเว็บต่อไปนี้ (index.html):
<!DOCTYPE html>
<html>
<head>
<script>
async function getRequest() {
const response = await fetch('http://localhost:3000/asdf')
const text = await response.text()
alert(text)
}
async function postRequest(message) {
const response = await fetch(
'http://localhost:3000/asdf',
{
method: 'post',
body: { message },
}
)
const text = await response.text()
alert(text)
}
</script>
</head>
<body>
<button onclick="getRequest()">Trigger GET request</button>
<br />
<button onclick="postRequest('trigger1')">Trigger POST request (body 1)</button>
<br />
<button onclick="postRequest('trigger2')">Trigger POST request (body 2)</button>
</body>
</html>
ติดตั้ง NodeJS, Express และเริ่มต้นแอปพลิเคชัน JavaScript เปิดหน้าเว็บในเบราว์เซอร์ของคุณ ลองใช้สถานการณ์ต่าง ๆ เพื่อทดสอบพฤติกรรมของเบราว์เซอร์:
สิ่งนี้แสดงให้เห็นว่าแม้ว่าคุณจะสามารถตั้งค่าCache-Control
และContent-Location
ตอบสนองส่วนหัว แต่ก็ไม่มีวิธีที่จะทำให้แคชของเบราว์เซอร์เป็นคำขอ HTTP POST
ลักษณะการทำงานของเบราว์เซอร์ไม่สามารถกำหนดค่าได้ แต่หากคุณไม่ใช่เบราว์เซอร์คุณไม่จำเป็นต้องผูกพันตามกฎของ RFC
หากคุณกำลังเขียนรหัสแอปพลิเคชันไม่มีอะไรที่ห้ามไม่ให้คุณทำการแคชคำขอ POST (pseudocode) อย่างชัดเจน:
if (cache.get('hello')) {
return cache.get('hello')
} else {
response = post(url = 'http://somewebsite/hello', request_body = 'world')
cache.put('hello', response.body)
return response.body
}
CDNs พร็อกซีและเกตเวย์ไม่จำเป็นต้องทำตาม RFC เช่นกัน ตัวอย่างเช่นถ้าคุณใช้ fastly เป็น CDN ของคุณ fastly ช่วยให้คุณสามารถเขียนVCL กำหนดเองตรรกะในการร้องขอ POST แคช
คำขอ POST ของคุณควรถูกแคชหรือไม่ขึ้นอยู่กับบริบท
ตัวอย่างเช่นคุณอาจสืบค้น Elasticsearch หรือ GraphQL โดยใช้ POST โดยที่การสืบค้นพื้นฐานของคุณคือ idempotent ในกรณีเหล่านั้นอาจหรือไม่เหมาะสมที่จะแคชการตอบสนองขึ้นอยู่กับกรณีการใช้งาน
ใน RESTful API คำขอ POST มักจะสร้างทรัพยากรและไม่ควรแคช นี่เป็นความเข้าใจของ RFC เกี่ยวกับ POST ว่าไม่ใช่การทำงานของ idempotent
หากคุณกำลังใช้ GraphQL และต้องแคช HTTP ทั่ว CDNs และเบราว์เซอร์ให้พิจารณาว่าการส่งคำสั่งโดยใช้วิธีการ GETตรงตามความต้องการของคุณแทนการโพสต์ เบราว์เซอร์และ CDN ต่างกันอาจมีข้อจำกัดความยาวของ URI ที่แตกต่างกัน แต่การดำเนินการให้ปลอดภัย (รายการที่อนุญาตพิเศษ) เป็นแนวทางปฏิบัติที่ดีที่สุดสำหรับแอป GraphQL ที่ใช้งานภายนอกอาจทำให้ URIs สั้นลง
หากเป็นสิ่งที่ไม่เปลี่ยนแปลงข้อมูลบนไซต์ของคุณจริง ๆ ควรเป็นคำขอ GET แม้ว่าจะเป็นฟอร์มคุณยังสามารถตั้งเป็นคำขอได้ ในขณะที่คนอื่น ๆ ชี้ให้เห็นว่าคุณสามารถแคชผลลัพธ์ของ POST ได้ แต่มันก็ไม่ได้หมายถึงความหมายเพราะ POST by definition กำลังเปลี่ยนแปลงข้อมูล
ด้วย firefox 27.0 และด้วย httpfox เมื่อวันที่ 19 พฤษภาคม 2014 ฉันเห็นบรรทัดนี้: 00: 03: 58.777 0.488 657 (393) POST (แคช) ข้อความ / html https://users.jackiszhp.info/S4UP
เห็นได้ชัดว่าการตอบสนองของวิธีการโพสต์ถูกแคชและมันก็อยู่ใน https เหลือเชื่อ!
POST ใช้ในสถานะอาแจ็กซ์ การส่งคืนการตอบกลับที่แคชไว้สำหรับ POST จะเอาชนะช่องทางการสื่อสารและผลข้างเคียงของการรับข้อความ นี่แย่มาก ๆ นอกจากนี้ยังเป็นความเจ็บปวดที่แท้จริงในการติดตาม ขอแนะนำอย่างยิ่งกับ
ตัวอย่างเล็ก ๆ น้อย ๆ จะเป็นข้อความที่ในฐานะที่เป็นผลข้างเคียงจ่ายเงินเดือนของคุณ $ 10,000 ต่อสัปดาห์ปัจจุบัน คุณไม่ต้องการได้รับ "ตกลงมันผ่าน!" หน้าเว็บที่ถูกแคชเมื่อสัปดาห์ที่แล้ว กรณีอื่น ๆ ในโลกแห่งความเป็นจริงที่ซับซ้อนมากขึ้นส่งผลให้เกิดความฮือฮาที่คล้ายกัน