Parcourir la source

simplify http status codes, update website info

jomo il y a 5 ans
Parent
commit
7f95a34e29
5 fichiers modifiés avec 67 ajouts et 37 suppressions
  1. 5 3
      config.js
  2. 2 2
      lib/helpers.js
  3. 23 11
      lib/response.js
  4. 34 18
      lib/views/index.html.ejs
  5. 3 3
      test/test.js

+ 5 - 3
config.js

@@ -35,7 +35,9 @@ var config = {
     browser: parseInt(process.env.CACHE_BROWSER) || 3600,
     // If true, redis is flushed on start.
     // Use this to avoid issues when you have a persistent redis database but an ephemeral storage
-    ephemeral: process.env.EPHEMERAL_STORAGE === "true" || false,
+    ephemeral: process.env.EPHEMERAL_STORAGE === "true",
+    // Used for information on the front page
+    cloudflare: process.env.CLOUDFLARE === "true"
   },
   // URL of your redis server
   redis: process.env.REDIS_URL || 'redis://localhost:6379',
@@ -47,9 +49,9 @@ var config = {
     // ms until connection to Mojang is dropped
     http_timeout: parseInt(process.env.EXTERNAL_HTTP_TIMEOUT) || 2000,
     // enables logging.debug & editing index page
-    debug_enabled: process.env.DEBUG === "true" || false,
+    debug_enabled: process.env.DEBUG === "true",
     // set to false if you use an external logger that provides timestamps,
-    log_time: process.env.LOG_TIME === "true" || true,
+    log_time: process.env.LOG_TIME === "true",
     // rate limit per second for outgoing requests to the Mojang session server
     // requests exceeding this limit are skipped and considered failed
     sessions_rate_limit: parseInt(process.env.SESSIONS_RATE_LIMIT) || Infinity

+ 2 - 2
lib/helpers.js

@@ -240,13 +240,13 @@ exp.get_image_hash = function(rid, userId, type, callback) {
         }
         store_images(rid, userId, cache_details, type, function(store_err, new_hash, slim) {
           if (store_err) {
-            // we might have a cached hash although an error occured
+            // an error occured, but we have a cached hash
             // (e.g. Mojang servers not reachable, using outdated hash)
 
             // when hitting the rate limit, let's pretend the request succeeded and bump the TTL
             var ratelimited = store_err.code === "RATELIMIT";
             cache.update_timestamp(rid, userId, !ratelimited, function(err2) {
-              callback(err2 || store_err, -1, cache_details && cached_hash, slim);
+              callback(err2 || store_err, 4, cache_details && cached_hash, slim);
             });
           } else {
             var status = cache_details && (cached_hash === new_hash) ? 3 : 2;

+ 23 - 11
lib/response.js

@@ -3,12 +3,13 @@ var config = require("../config");
 var crc = require("crc").crc32;
 
 var human_status = {
-  "-2": "user error",   // e.g. invalid size
-  "-1": "server error", // e.g. mojang/network issues
-  0: "none",            // cached as null (user has no skin)
-  1: "cached",          // found on disk
-  2: "downloaded",      // profile downloaded, skin downloaded from mojang servers
-  3: "checked",         // profile re-downloaded (was too old), has no skin or skin cached
+  "-2": "user error",        // e.g. invalid size
+  "-1": "server error",      // e.g. mojang/network issues
+  0: "none",                 // cached as null (user has no skin)
+  1: "cached",               // found on disk
+  2: "downloaded",           // profile downloaded, skin downloaded from mojang servers
+  3: "checked",              // profile re-downloaded (was too old), has no skin or skin cached
+  4: "server error;cached" // tried to check but ran into server error, using cached version
 };
 
 
@@ -83,13 +84,24 @@ module.exports = function(request, response, result) {
   if (result.status === -2) {
     response.writeHead(result.code || 422, headers);
   } else if (result.status === -1) {
-    // 500 responses shouldn't be cached
-    headers["Cache-Control"] = "private, max-age=0, no-cache";
-    response.writeHead(result.code || 500, headers);
+    // server errors shouldn't be cached
+    headers["Cache-Control"] = "no-cache, max-age=0";
+    if (result.body && result.hash && !result.hash.startsWith("mhf_")) {
+      headers["Warning"] = '110 Crafatar "Response is Stale"'
+      headers["Etag"] = etag;
+      result.code = result.code || 200;
+    }
+    if (result.err && result.err.code === "ENOENT") {
+      result.code = result.code || 500;
+    }
+    response.writeHead(result.code || 502, headers);
   } else {
     if (result.body) {
-      headers.Etag = etag;
-      response.writeHead(result.status === 2 ? 201 : 200, headers);
+      if (result.status === 4) {
+        headers["Warning"] = '111 Crafatar "Revalidation Failed"'
+      }
+      headers["Etag"] = etag;
+      response.writeHead(200, headers);
     } else {
       response.writeHead(404, headers);
     }

+ 34 - 18
lib/views/index.html.ejs

@@ -76,6 +76,7 @@
               </div>
             </div>
           </form>
+          <p>You can use <a rel="nofollow" target="_blank" href="https://mcuuid.net">mcuuid.net</a> to find the UUID of a username.</p>
         </section>
 
         <section id="avatars">
@@ -210,10 +211,12 @@
             <h3><a href="#meta-caching">About Caching</a></h3>
             <p>
               Crafatar checks for skin updates every <%= config.caching.local / 60 %> minutes.<br>
-              Images are cached in your browser for <%= config.caching.browser / 60 %> minutes until a new request to Crafatar is made.<br>
-              In addition, <span title="A CDN and caching proxy">CloudFlare</span> caches up to 2 hours on a per-url basis.
+              Images are also cached in your browser for <%= config.caching.browser / 60 %> minutes unless you clear your browser cache.
+              <% if (config.caching.cloudflare) { %>
+                <br>In addition, <span title="A CDN and caching proxy">Cloudflare</span> may cache images as long as your browser would.
+              <% } %>
             </p>
-            <p>When you changed your skin you can try clearing your browser cache to see the change faster.</p>
+            <p>After changing your Minecraft skin, you can try clearing your browser cache to see the change faster.</p>
           </section>
 
           <section id="meta-cors">
@@ -224,11 +227,25 @@
           <section id="meta-http-headers">
             <h3><a href="#meta-http-headers">HTTP Headers</a></h3>
             <p>
-              Responses come with some custom HTTP headers, useful for debugging.<br>
-              Please note that these headers may be cached by <span title="A CDN and caching proxy">CloudFlare</span>.
+              Crafatar always replies with a <code>200 OK</code> status code when the requested user's skin/cape was found. This is also used in some rare cases when Mojang servers are having issues and the image couldn't be checked for changes, but Crafatar still had a cached version. <code>502 Bad Gateway</code> and <code>500 Server Error</code> are used when no skin/cape was found because of Mojang or Crafatar server issues.
+            </p>
+            <p>
+              Note that requests are usually answered with an image (with Steve/Alex skin), even if an error occured!
+            </p>
+            <p>
+              Responses come with some HTTP headers that are useful for debugging.
+              <% if (config.caching.cloudflare) { %>
+                <br>Please note that these headers may be cached by <span title="A CDN and caching proxy">Cloudflare</span>.
+              <% } %>
             </p>
 
             <ul>
+              <li>
+                <b>Warning</b>: When using a cached image after an error occured. One of:
+                <ul>
+                  <li><code>110 Crafatar "Response is Stale"</code></li>
+                  <li><code>111 Crafatar "Revalidation Failed"</code></li>
+                </ul>
               <li>
                 <b>X-Storage-Type</b>: Details about how the requested image was stored on the server
                 <ul>
@@ -237,27 +254,19 @@
                   <li><b>checked</b>: Requested skin details, skin cached. (1 external request)<br>
                     This happens either when the user removed their skin or when it didn't change.</li>
                   <li><b>downloaded</b>: Requested skin details, skin downloaded. (2 external requests)</li>
-                  <li><b>server error</b>: This can happen, for example, when Mojang's servers are down.<br>
-                    If possible, a cached image is served instead.</li>
+                  <li><b>server error</b>: This can happen, for example, when Mojang's servers are down.</li>
+                  <li><b>server error;cached</b>: Same as server error, but a cached skin was available.</li>
                   <li><b>user error</b>: You have done something wrong, such as requesting a malformed uuid.<br>
                     Check the response body for details.</li>
                 </ul>
               <li>
                 <b>X-Request-ID</b>: The internal ID assigned to this request.<br>
-                If you think something is wrong with your request, please <a href="#contact">contact us</a> and provide this ID.
+                If you think something is wrong with your request, please contact us and provide this ID.
+              <li>
+                <b>Response-Time</b>: How long it took Crafatar to answer the request, in ms.
             </ul>
           </section>
         </section>
-
-        <section id="contact">
-          <h2><a href="#contact">Contact</a></h2>
-          <ul>
-            <li>Follow us on twitter <a href="https://twitter.com/crafatar" target="_blank">@crafatar</a></li>
-            <li>Open an issue <a href="https://github.com/crafatar/crafatar/issues" target="_blank">on GitHub</a></li>
-            <li><a href="https://webchat.esper.net/?channels=crafatar" target="_blank">Join us</a> in <a href="irc://irc.esper.net/crafatar">#crafatar</a> on irc.esper.net</li>
-          </ul>
-        </section>
-      </section>
     </div>
 
     <div class="col-md-3">
@@ -282,7 +291,14 @@
         <a rel="nofollow" href="https://github.com/sk89q/Plumeria" target="_blank" class="list-group-item">Plumeria <i>(Discord)</i></a>
         <a href="https://github.com/crafatar/crafatar/wiki/Who-uses-crafatar%3F#other-services-using-crafatar" target="_blank" class="list-group-item">and many more…</a>
       </div>
+      <hr>
+      <h4>Contact</h4>
+      <div class="list-group">
+        <a class="list-group-item" href="https://twitter.com/crafatar" target="_blank">@crafatar on Twitter</a>
+        <a class="list-group-item" href="https://github.com/crafatar/crafatar/issues" target="_blank">Issue tracker</a>
+      </div>
       <% if (config.sponsor.sidebar) { %>
+        <hr>
         <%- config.sponsor.sidebar %>
       <% } %>
     </div>

+ 3 - 3
test/test.js

@@ -258,7 +258,7 @@ describe("Crafatar", function() {
       var url = "http://localhost:3000/%61%76%61%74%61%72%73/%61%65%37%39%35%61%61%38%36%33%32%37%34%30%38%65%39%32%61%62%32%35%63%38%61%35%39%66%33%62%61%31"; // avatars/ae795aa86327408e92ab25c8a59f3ba1
       request.get(url, function(error, res, body) {
         assert.ifError(error);
-        assert.strictEqual(res.statusCode, 201);
+        assert.strictEqual(res.statusCode, 200);
         assert_headers(res);
         assert(res.headers.etag);
         assert.strictEqual(res.headers["content-type"], "image/png");
@@ -281,7 +281,7 @@ describe("Crafatar", function() {
       function req() {
         request.get(url, function(error, res, body) {
           assert.ifError(error);
-          assert.strictEqual(res.statusCode === 201 || res.statusCode === 200, true);
+          assert.strictEqual(res.statusCode, 200);
           assert_headers(res);
           assert(res.headers.etag);
           assert.strictEqual(res.headers["content-type"], "image/png");
@@ -489,7 +489,7 @@ describe("Crafatar", function() {
               done();
             } else {
               assert.strictEqual(res.headers["content-type"], "image/png");
-              assert.strictEqual(res.statusCode, res.headers["x-storage-type"] === "downloaded" ? 201 : 200);
+              assert.strictEqual(res.statusCode, 200);
               assert(res.headers.etag);
               assert.strictEqual(res.headers.etag, '"' + hash + '"');
               assert_cache(location.url, res.headers.etag, function() {