Merge branch 'v1.3-dev' as v1.3.11
[websub-hub] / src / communication.js
index dc4d464c70111b4ea2a8971575940c099d14b379..feda5887146c6b70ae242e1daf52ab3fbbe10a44 100644 (file)
@@ -196,6 +196,8 @@ class Communication {
     const acceptPreferred = [topic.contentType, acceptWildcard].filter((x) => x).join(', ');
     return Communication._axiosConfig('GET', topic.url, undefined, {}, {
       [Enum.Header.Accept]: acceptPreferred,
+      ...(topic.httpEtag && { [Enum.Header.IfNoneMatch]: topic.httpEtag }),
+      ...(topic.httpLastModified && { [Enum.Header.IfModifiedSince]: topic.httpLastModified }),
     });
   }
 
@@ -218,8 +220,8 @@ class Communication {
 
     const topic = await this.db.topicGetById(dbCtx, verification.topicId);
     if (!topic) {
-      this.logger.error(_scope, 'no such topic id', { verification, requestId });
-      throw new Errors.InternalInconsistencyError('no such topic id');
+      this.logger.error(_scope, Enum.Message.NoSuchTopicId, { verification, requestId });
+      throw new Errors.InternalInconsistencyError(Enum.Message.NoSuchTopicId);
     }
 
     if (!topic.isActive) {
@@ -436,8 +438,8 @@ class Communication {
 
     const topic = await this.db.topicGetById(dbCtx, topicId);
     if (topic === undefined) {
-      this.logger.error(_scope, 'no such topic id', logInfoData);
-      throw new Errors.InternalInconsistencyError('no such topic id');
+      this.logger.error(_scope, Enum.Message.NoSuchTopicId, logInfoData);
+      throw new Errors.InternalInconsistencyError(Enum.Message.NoSuchTopicId);
     }
 
     // Cull any expired subscriptions
@@ -467,6 +469,7 @@ class Communication {
 
     switch (common.httpStatusCodeClass(response.status)) {
       case 2:
+      case 3:
         // Fall out of switch on success
         break;
 
@@ -481,6 +484,12 @@ class Communication {
         return;
     }
 
+    if (response.status === 304) {
+      this.logger.info(_scope, 'content has not changed, per server', logInfoData);
+      await this.db.topicFetchComplete(dbCtx, topicId);
+      return;
+    }
+
     const contentHash = Communication.contentHash(response.data, topic.contentHashAlgorithm);
     logInfoData.contentHash = contentHash;
     if (topic.contentHash === contentHash) {
@@ -505,6 +514,8 @@ class Communication {
     }
 
     const contentType = response.headers[Enum.Header.ContentType.toLowerCase()];
+    const httpETag = response.headers[Enum.Header.ETag.toLowerCase()];
+    const httpLastModified = response.headers[Enum.Header.LastModified.toLowerCase()];
 
     await this.db.transaction(dbCtx, async (txCtx) => {
       await this.db.topicSetContent(txCtx, {
@@ -512,6 +523,8 @@ class Communication {
         content: Buffer.from(response.data),
         contentHash,
         ...(contentType && { contentType }),
+        ...(httpETag && { httpETag }),
+        ...(httpLastModified && { httpLastModified }),
       });
 
       await this.db.topicFetchComplete(txCtx, topicId);