Câu trả lời:
RFC 2616 tương ứng trong phần 9.5 (POST) cho phép lưu vào bộ đệm của phản hồi tới tin nhắn POST, nếu bạn sử dụng các tiêu đề thích hợp.
Các phản hồi cho phương thức này không được lưu trong bộ nhớ cache, trừ khi phản hồi bao gồm các trường tiêu đề Kiểm soát bộ đệm hoặc hết hạn thích hợp. Tuy nhiên, phản hồi 303 (Xem Khác) có thể được sử dụng để chỉ đạo tác nhân người dùng truy xuất tài nguyên có thể lưu trong bộ nhớ cache.
Lưu ý rằng cùng một trạng thái RFC rõ ràng trong phần 13 (Bộ đệm trong HTTP) rằng bộ đệm phải làm mất hiệu lực thực thể tương ứng sau khi yêu cầu POST .
Một số phương thức HTTP PHẢI gây ra bộ đệm để vô hiệu hóa một thực thể. Đây là thực thể được gọi bởi URI yêu cầu hoặc bởi các tiêu đề Vị trí hoặc Nội dung (nếu có). Những phương pháp này là:
- PUT - DELETE - POST
Tôi không rõ làm thế nào những thông số kỹ thuật này có thể cho phép bộ nhớ đệm có ý nghĩa.
Điều này cũng được phản ánh và làm rõ thêm trong RFC 7231 (Mục 4.3.3.), Làm lỗi thời RFC 2616.
Phản hồi cho các yêu cầu POST chỉ được lưu trong bộ nhớ cache khi chúng bao gồm
thông tin độ mới rõ ràng (xem Mục 4.2.1 của [RFC7234]).
Tuy nhiên, bộ nhớ đệm POST không được triển khai rộng rãi. Đối với trường hợp máy chủ gốc muốn máy khách có thể lưu trữ kết quả của POST theo cách có thể được sử dụng lại bởi GET sau đó, máy chủ gốc CÓ THỂ gửi phản hồi 200 (OK) có chứa kết quả và Vị trí nội dung trường tiêu đề có cùng giá trị với URI yêu cầu hiệu quả của POST (Mục 3.1.4.2).
Theo đó, kết quả của POST được lưu trong bộ nhớ cache (nếu khả năng này được chỉ định bởi máy chủ) có thể được sử dụng sau đó là kết quả của yêu cầu GET cho cùng một URI.
Theo RFC 2616 Mục 9.5:
"Phản hồi cho phương thức POST không được lưu trong bộ nhớ cache, KHÔNG GIỚI HẠN phản hồi bao gồm các trường tiêu đề Kiểm soát bộ đệm hoặc hết hạn thích hợp."
Vì vậy, CÓ, bạn có thể lưu trữ phản hồi yêu cầu POST nhưng chỉ khi nó đến với các tiêu đề thích hợp. Trong hầu hết các trường hợp, bạn không muốn lưu trữ phản hồi. Nhưng trong một số trường hợp - chẳng hạn như nếu bạn không lưu bất kỳ dữ liệu nào trên máy chủ - điều đó hoàn toàn phù hợp.
Lưu ý, tuy nhiên, nhiều trình duyệt, bao gồm cả Firefox 3.0.10 hiện tại, sẽ không lưu bộ đệm phản hồi POST bất kể các tiêu đề. IE hành xử thông minh hơn trong khía cạnh này.
Bây giờ, tôi muốn làm sáng tỏ một số nhầm lẫn ở đây liên quan đến RFC 2616 S. 13.10. Phương thức POST trên URI không "làm mất hiệu lực tài nguyên cho bộ nhớ đệm" như một số đã nêu ở đây. Nó tạo ra một phiên bản được lưu trong bộ nhớ cache trước đó của URI đó, ngay cả khi các tiêu đề kiểm soát bộ đệm của nó chỉ ra độ mới của thời lượng dài hơn.
GET
và POST
yêu cầu. Nếu bạn là bộ đệm nằm giữa máy khách và máy chủ, bạn sẽ thấy GET /foo
và bạn lưu bộ đệm phản hồi. Tiếp theo bạn sẽ thấy POST /foo
sau đó bạn được yêu cầu vô hiệu hóa phản hồi được lưu trong bộ nhớ cache GET /foo
ngay cả khi POST
phản hồi không bao gồm bất kỳ tiêu đề kiểm soát bộ đệm nào vì chúng là cùng một URI , do đó tiếp theo GET /foo
sẽ phải xác nhận lại ngay cả khi các tiêu đề ban đầu chỉ ra bộ đệm vẫn còn trực tiếp (nếu bạn chưa thấy POST /foo
yêu cầu)
But in some cases - such as if you are not saving any data on the server - it's entirely appropriate.
. Điểm đầu tiên của API POST như vậy ở vị trí đầu tiên là gì?
Nhìn chung:
Về cơ bản POST không phải là một hoạt động bình thường . Vì vậy, bạn không thể sử dụng nó để lưu trữ. GET phải là một hoạt động bình thường, vì vậy nó thường được sử dụng để lưu trữ.
Vui lòng xem phần 9.1 của HTTP 1.1 RFC 2616 S. 9.1 .
Khác với ngữ nghĩa của phương thức GET:
Phương thức POST tự nó có nghĩa là để gửi một cái gì đó lên một tài nguyên. POST không thể được lưu trong bộ nhớ cache vì nếu bạn làm điều gì đó một lần so với hai lần so với ba lần, thì bạn đang thay đổi tài nguyên của máy chủ mỗi lần. Mỗi yêu cầu quan trọng và nên được gửi đến máy chủ.
Phương thức PUT tự nó có nghĩa là để đặt hoặc tạo một tài nguyên. Đây là một hoạt động bình thường, nhưng nó sẽ không được sử dụng để lưu vào bộ đệm vì có thể xảy ra XÓA trong thời gian này.
Phương thức DELETE tự nó có nghĩa là để xóa một tài nguyên. Đây là một hoạt động bình thường, nhưng nó sẽ không được sử dụng để lưu vào bộ đệm vì PUT có thể đã xảy ra trong thời gian đó.
Về bộ nhớ đệm phía máy khách:
Trình duyệt web sẽ luôn chuyển tiếp yêu cầu của bạn ngay cả khi nó có phản hồi từ thao tác POST trước đó. Ví dụ: bạn có thể gửi email với gmail cách nhau vài ngày. Chúng có thể là cùng một chủ đề và cơ thể, nhưng cả hai email nên được gửi.
Về bộ nhớ cache proxy:
Một máy chủ HTTP proxy chuyển tiếp tin nhắn của bạn đến máy chủ sẽ không bao giờ lưu trữ bất cứ thứ gì ngoại trừ một yêu cầu GET hoặc CHÍNH.
Về bộ nhớ đệm máy chủ:
Một máy chủ theo mặc định sẽ không tự động xử lý yêu cầu POST thông qua kiểm tra bộ đệm của nó. Nhưng tất nhiên, một yêu cầu POST có thể được gửi đến ứng dụng hoặc bổ trợ của bạn và bạn có thể có bộ đệm riêng mà bạn đọc từ khi các tham số giống nhau.
Vô hiệu hóa tài nguyên:
Kiểm tra HTTP 1.1 RFC 2616 S. 13.10 cho thấy phương thức POST sẽ làm mất hiệu lực tài nguyên để lưu vào bộ đệm.
Nếu bạn lưu bộ đệm một phản hồi POST, nó phải theo hướng của ứng dụng web. Đây là ý nghĩa của "Phản hồi cho phương thức này không thể lưu trong bộ nhớ cache, trừ khi phản hồi bao gồm các trường tiêu đề Cache-Control hoặc hết hạn thích hợp".
Người ta có thể giả định một cách an toàn rằng ứng dụng, biết kết quả của POST có bình thường hay không, quyết định có đính kèm các tiêu đề kiểm soát bộ đệm cần thiết và phù hợp hay không. Nếu các tiêu đề đề xuất bộ nhớ đệm được cho phép có mặt, ứng dụng sẽ cho bạn biết rằng POST thực tế là một siêu GET; rằng việc sử dụng POST chỉ được yêu cầu do số lượng dữ liệu không cần thiết và không liên quan (với việc sử dụng URI làm khóa bộ đệm) cần thiết để thực hiện thao tác tạm thời.
Theo dõi GET có thể được phục vụ từ bộ đệm theo giả định này.
Một ứng dụng không đính kèm các tiêu đề cần thiết và chính xác để phân biệt giữa các phản hồi POST có thể lưu trong bộ nhớ cache và không lưu trong bộ nhớ cache có lỗi đối với mọi kết quả bộ đệm không hợp lệ.
Điều đó nói rằng, mỗi POST chạm vào bộ đệm yêu cầu xác nhận bằng các tiêu đề có điều kiện. Điều này là bắt buộc để làm mới nội dung bộ đệm để tránh kết quả POST không được phản ánh trong các phản hồi cho các yêu cầu cho đến khi hết thời gian của đối tượng.
Mark Nottingham đã phân tích khi khả thi để lưu lại phản hồi của POST. Lưu ý rằng các yêu cầu tiếp theo muốn tận dụng bộ nhớ đệm phải là các yêu cầu GET hoặc HEAD. Xem thêm ngữ nghĩa http
BÀI VIẾT không giải quyết các đại diện của trạng thái được xác định, 99 lần trong số 100. Tuy nhiên, có một trường hợp thực hiện; khi máy chủ hết cách để nói rằng phản hồi POST này là đại diện cho URI của nó, bằng cách đặt tiêu đề Content-Location giống như URI yêu cầu. Khi điều đó xảy ra, phản hồi POST giống như phản hồi GET cho cùng một URI; nó có thể được lưu trữ và sử dụng lại - nhưng chỉ cho các yêu cầu GET trong tương lai.
Nếu bạn đang tự hỏi liệu bạn có thể lưu trữ một yêu cầu bài đăng hay không và thử nghiên cứu một câu trả lời cho câu hỏi đó, có khả năng bạn sẽ không thành công. Khi tìm kiếm "yêu cầu bài đăng bộ đệm", kết quả đầu tiên là câu hỏi StackOverflow này.
Các câu trả lời là một hỗn hợp lẫn lộn về cách hoạt động của bộ nhớ đệm, cách bộ đệm hoạt động theo RFC, cách bộ đệm nên hoạt động theo RFC và cách thức hoạt động của bộ đệm. Hãy bắt đầu với RFC, xem qua phần trình diễn về cách thức hoạt động của trình duyệt, sau đó nói về CDN, GraphQL và các lĩnh vực quan tâm khác.
Theo RFC, các yêu cầu POST phải làm mất hiệu lực bộ đệm:
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
Ngôn ngữ này cho thấy các yêu cầu POST không được lưu trong bộ nhớ cache, nhưng điều đó không đúng (trong trường hợp này). Bộ đệm chỉ bị vô hiệu đối với dữ liệu được lưu trữ trước đó. RFC (dường như) làm rõ một cách rõ ràng rằng có, bạn có thể lưu trữ POST
các yêu cầu:
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.
Mặc dù ngôn ngữ này, việc thiết lập Cache-Control
không được lưu trữ các POST
yêu cầu tiếp theo vào cùng một tài nguyên. POST
yêu cầu phải được gửi đến máy chủ:
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.
điều đó có nghĩa gì? Chà, bạn không lưu trữ POST
yêu cầu, bạn đang lưu trữ tài nguyên.
Phần thân phản hồi POST chỉ có thể được lưu trong bộ nhớ cache cho các yêu cầu GET tiếp theo cho cùng một tài nguyên. Đặt tiêu đề Location
hoặc Content-Location
trong phản hồi POST để truyền đạt tài nguyên mà cơ thể đại diện. Vì vậy, cách duy nhất hợp lệ về mặt kỹ thuật để lưu trữ một yêu cầu POST, là cho các GET tiếp theo vào cùng một tài nguyên.
Câu trả lời đúng là cả hai:
Mặc dù RFC cho phép lưu trữ các yêu cầu vào cùng một tài nguyên, nhưng trên thực tế, các trình duyệt và CDN không thực hiện hành vi này và không cho phép bạn lưu trữ các yêu cầu POST.
Nguồn:
Cho ví dụ sau về ứng dụng 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!')
})
Và đưa ra trang web ví dụ sau (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>
Cài đặt NodeJS, Express và khởi động ứng dụng JavaScript. Mở trang web trong trình duyệt của bạn. Hãy thử một vài kịch bản khác nhau để kiểm tra hành vi của trình duyệt:
Điều này cho thấy, mặc dù bạn có thể đặt tiêu đề Cache-Control
và Content-Location
phản hồi, nhưng không có cách nào để tạo bộ đệm cho trình duyệt một yêu cầu POST HTTP.
Hành vi của trình duyệt không thể định cấu hình được, nhưng nếu bạn không phải là trình duyệt, bạn không nhất thiết bị ràng buộc bởi các quy tắc của RFC.
Nếu bạn đang viết mã ứng dụng, sẽ không có gì ngăn bạn lưu các yêu cầu POST (mã giả) một cách rõ ràng:
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
}
CDN, proxy và cổng không nhất thiết phải tuân theo RFC. Ví dụ: nếu bạn sử dụng Nhanh như CDN của mình, Nhanh chóng cho phép bạn viết logic VCL tùy chỉnh vào bộ đệm yêu cầu POST .
Việc yêu cầu POST của bạn có nên được lưu trữ hay không phụ thuộc vào ngữ cảnh.
Ví dụ: bạn có thể truy vấn Elaticsearch hoặc GraphQL bằng cách sử dụng POST trong đó truy vấn cơ bản của bạn là idempotent. Trong những trường hợp đó, có thể có hoặc không có ý nghĩa để lưu trữ phản hồi tùy thuộc vào trường hợp sử dụng.
Trong API RESTful, các yêu cầu POST thường tạo tài nguyên và không nên lưu vào bộ đệm. Đây cũng là sự hiểu biết của RFC về POST rằng nó không phải là một hoạt động bình thường.
Nếu bạn đang sử dụng GraphQL và yêu cầu bộ đệm HTTP trên các CDN và trình duyệt, hãy xem xét việc gửi truy vấn bằng phương thức GET có đáp ứng yêu cầu của bạn thay vì POST không . Như một lời cảnh báo, các trình duyệt và CDN khác nhau có thể có giới hạn độ dài URI khác nhau, nhưng hoạt động an toàn (danh sách trắng truy vấn), như một cách thực hành tốt nhất cho các ứng dụng GraphQL sản xuất bên ngoài, có thể rút ngắn URI.
Nếu đó là thứ gì đó không thực sự thay đổi dữ liệu trên trang web của bạn, thì đó sẽ là một yêu cầu NHẬN. Ngay cả khi đó là một hình thức, bạn vẫn có thể đặt nó làm yêu cầu nhận. Trong khi, giống như những người khác chỉ ra, bạn có thể lưu trữ kết quả của POST, nó sẽ không có ý nghĩa ngữ nghĩa vì POST theo định nghĩa đang thay đổi dữ liệu.
Với firefox 27.0 và với httpfox, vào ngày 19 tháng 5 năm 2014, tôi đã thấy một dòng này: 00: 03: 58.777 0.488 657 (393) POST (Cache) văn bản / html https://users.jackiszhp.info/S4UP
Rõ ràng, phản hồi của một phương thức bài được lưu trữ và nó cũng có trong https. Không thể tin được!
POST được sử dụng trong Ajax trạng thái. Trả lại phản hồi được lưu trong bộ nhớ cache cho POST đánh bại kênh liên lạc và các tác dụng phụ của việc nhận tin nhắn. Điều này rất rất xấu. Đó cũng là một nỗi đau thực sự để theo dõi. Rất khuyến khích chống lại.
Một ví dụ tầm thường sẽ là một thông điệp rằng, như một tác dụng phụ, trả cho bạn mức lương 10.000 đô la trong tuần hiện tại. Bạn KHÔNG muốn nhận được "OK, nó đã đi qua!" trang trở lại đã được lưu trữ tuần trước. Các trường hợp thực tế khác, phức tạp hơn dẫn đến sự vui nhộn tương tự.