From 9faba4273e448dac800f37b9a99e86344cc86a2b Mon Sep 17 00:00:00 2001
From: Lloyd Hilaiel <lloyd@hilaiel.com>
Date: Thu, 9 Feb 2012 09:53:49 -0700
Subject: [PATCH] use HTTP 429 for throttling responses.  issue #1083

---
 lib/httputils.js                   | 10 ++++++++++
 lib/wsapi/stage_email.js           |  2 +-
 lib/wsapi/stage_user.js            |  2 +-
 resources/static/shared/network.js |  8 ++++----
 tests/email-throttling-test.js     |  6 +++---
 5 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/lib/httputils.js b/lib/httputils.js
index 2491e5ee3..671fa5a16 100644
--- a/lib/httputils.js
+++ b/lib/httputils.js
@@ -42,6 +42,16 @@ exports.forbidden = function(resp, reason)
   resp.end();
 };
 
+exports.throttled = function(resp, reason)
+{
+  resp.writeHead(429, {"Content-Type": "text/plain"});
+  resp.write("Too Many Requests");
+  if (reason) {
+    resp.write(": " + reason);
+  }
+  resp.end();
+};
+
 exports.jsonResponse = function(resp, obj)
 {
   resp.writeHead(200, {"Content-Type": "application/json"});
diff --git a/lib/wsapi/stage_email.js b/lib/wsapi/stage_email.js
index c5b562304..9b4061bc8 100644
--- a/lib/wsapi/stage_email.js
+++ b/lib/wsapi/stage_email.js
@@ -26,7 +26,7 @@ exports.process = function(req, res) {
     if (last && (new Date() - last) < config.get('min_time_between_emails_ms')) {
       logger.warn('throttling request to stage email address ' + req.body.email + ', only ' +
                   ((new Date() - last) / 1000.0) + "s elapsed");
-      return httputils.forbidden(res, "throttling.  try again later.");
+      return httputils.throttled(res, "Too many emails sent to that address, try again later.");
     }
 
     try {
diff --git a/lib/wsapi/stage_user.js b/lib/wsapi/stage_user.js
index dc5f0aef0..580838037 100644
--- a/lib/wsapi/stage_user.js
+++ b/lib/wsapi/stage_user.js
@@ -31,7 +31,7 @@ exports.process = function(req, resp) {
     if (last && (new Date() - last) < config.get('min_time_between_emails_ms')) {
       logger.warn('throttling request to stage email address ' + req.body.email + ', only ' +
                   ((new Date() - last) / 1000.0) + "s elapsed");
-      return httputils.forbidden(resp, "throttling.  try again later.");
+      return httputils.throttled(resp, "Too many emails sent to that address, try again later.");
     }
 
     try {
diff --git a/resources/static/shared/network.js b/resources/static/shared/network.js
index a16b38df9..ce84f5616 100644
--- a/resources/static/shared/network.js
+++ b/resources/static/shared/network.js
@@ -186,8 +186,8 @@ BrowserID.Network = (function() {
           complete(onComplete, status.success);
         },
         error: function(info) {
-          // 403 is throttling.
-          if (info.network.status === 403) {
+          // 429 is throttling.
+          if (info.network.status === 429) {
             complete(onComplete, false);
           }
           else complete(onFailure, info);
@@ -392,8 +392,8 @@ BrowserID.Network = (function() {
           complete(onComplete, response.success);
         },
         error: function(info) {
-          // 403 is throttling.
-          if (info.network.status === 403) {
+          // 429 is throttling.
+          if (info.network.status === 429) {
             complete(onComplete, false);
           }
           else complete(onFailure, info);
diff --git a/tests/email-throttling-test.js b/tests/email-throttling-test.js
index db6a7d1a3..ba807a782 100755
--- a/tests/email-throttling-test.js
+++ b/tests/email-throttling-test.js
@@ -52,7 +52,7 @@ suite.addBatch({
       site:'fakesite.com'
     }),
     "is throttled": function(err, r) {
-      assert.strictEqual(r.code, 403);
+      assert.strictEqual(r.code, 429);
     }
   }
 });
@@ -101,8 +101,8 @@ suite.addBatch({
       email: 'second@fakeemail.com',
       site:'fakesite.com'
     }),
-    "is throttled with a 403": function(err, r) {
-      assert.strictEqual(r.code, 403);
+    "is throttled with a 429": function(err, r) {
+      assert.strictEqual(r.code, 429);
     }
   }
 });
-- 
GitLab