[英]Multiple request url mapping handler in one controller does not work in Node Express JS
[英]Node js: How to handler multiple request in one API
假設這是我的 API:
app.post('/refund', function (req, res) {
Transaction.findOneAndUpdate({_id: req.body.transaction_id}, {$set: {refund_status: true}}).
exec(function (err, transaction_status) {
res.end("Refund successfully")
}
}
如果兩個管理員同時點擊退款按鈕。 我的客戶將收到雙倍退款。
那么,如何預防這些問題呢?
只需先獲取交易並檢查退款狀態並更新即可。 如果是虛假退款。 如果它是真的告訴它已經退款了。
app.post('/refund', function (req, res) {
// get the transaction first
Transaction.find({_id: req.body.transaction_id}, function(err, doc) {
if (doc.refund_status == false) {
Transaction.findOneAndUpdate({_id: req.body.transaction_id}, {$set: {refund_status: true}}).exec(function(err, transaction_status) {
res.end("Refund successfully")
})
} else { // already refunded
res.end("Already refunded")
}
})
}
首先,您應該在第一次完成之前禁用兩次單擊退款按鈕的可用性(以獲得更好的用戶體驗)。
為了防止這種情況在后端發生,您可以使用 rate limit the specific route 。
如果您使用的是 express,您應該查看express-slow-down或express-rate-limit
一個可能的解決方案是:
const slowDown = require("express-slow-down");
/* app.enable("trust proxy"); only if you're behind a reverse proxy (Heroku,
Bluemix, AWS if you use an ELB, custom Nginx setup, etc) */
const refundSpeedLimiter = slowDown({
windowMs: 10 * 1000, // 10 seconds
delayAfter: 1, // allow the first request to go at full-speed, then...
delayMs: 1.5 * 1000 // 2nd request has a **1.5s** delay, 3rd has a **3s** delay, 4th gets 4.5s, etc.
});
app.post('/refund', refundSpeedLimiter, function (req, res) {
// Fetch The Transaction
Transaction.find({_id: req.body.transaction_id}, function(err, doc) {
// Check if its not already refunded.
if (doc.refund_status == false) {
Transaction.findOneAndUpdate({_id: req.body.transaction_id}, {$set: {refund_status: true}}).exec(function(err, transaction_status) {
res.end("Refund successfully")
})
} else { // already refunded
res.end("Already refunded")
}
})
}
如express-rate-limit
中所述:
默認情況下,此模塊不與其他進程/服務器共享狀態。 如果您需要更強大的解決方案,我建議使用外部存儲。 有關外部商店的列表,請參閱下面的商店部分。
請注意,默認存儲是Memory store ,因此默認情況下它允許多個實例。 如果您打算使用不同的存儲(它允許跨多個節點實例使用速率限制 - 就像在集群模式中),您將需要為每個ratelimit
實例設置一個自定義鍵。
在session.withTransaction()的回調中實現您的退款邏輯。 這將防止並發更新。 不要擔心異步的東西; .withTransaction() 正確處理它。
或者,使您的退款邏輯具有冪等性。 也就是說,以多次調用它與調用一次完全相同的方式實現它。 您的設置幾乎是冪等的:您從交易 id 開始並將其退款狀態設置為 true。 但是,如果您必須在交易已經退款時進行報告,則冪等性可能對您不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.