Просмотр исходного кода

Not sending headers with upload request

Fixes #2728
JC Brand 3 лет назад
Родитель
Сommit
2af758e66d
3 измененных файлов с 26 добавлено и 4 удалено
  1. 1 0
      CHANGES.md
  2. 17 3
      src/headless/plugins/chat/message.js
  3. 8 1
      src/plugins/chatview/tests/http-file-upload.js

+ 1 - 0
CHANGES.md

@@ -14,6 +14,7 @@
 - #2647: Singleton mode doesn't work
 - #2704: Send button doesn't work in a multi-user chat
 - #2725: Send new presence status to all connected MUCs
+- #2728: Not sending headers with upload request
 
 - Emit a `change` event when a configuration setting changes
 - 3 New configuration settings:

+ 17 - 3
src/headless/plugins/chat/message.js

@@ -4,8 +4,7 @@ import log from '../../log.js';
 import { _converse, api, converse } from '../../core.js';
 import { getOpenPromise } from '@converse/openpromise';
 
-const u = converse.env.utils;
-const { Strophe } = converse.env;
+const { Strophe, sizzle, u } = converse.env;
 
 /**
  * Mixin which turns a `ModelWithContact` model into a non-MUC message. These can be either `chat` messages or `headline` messages.
@@ -192,6 +191,18 @@ const MessageMixin = {
         return api.sendIQ(iq);
     },
 
+    getUploadRequestMetadata (stanza) {
+        const headers = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"] put header`, stanza);
+        // https://xmpp.org/extensions/xep-0363.html#request
+        // TODO: Can't set the Cookie header in JavaScipt, instead cookies need
+        // to be manually set via document.cookie, so we're leaving it out here.
+        return {
+            'headers': headers
+                .map(h => ({ 'name': h.getAttribute('name'), 'value': h.textContent }))
+                .filter(h => ['Authorization', 'Expires'].includes(h.name))
+        }
+    },
+
     async getRequestSlotURL () {
         const { __ } = _converse;
         let stanza;
@@ -205,8 +216,9 @@ const MessageMixin = {
                 'is_ephemeral': true
             });
         }
-        const slot = stanza.querySelector('slot');
+        const slot = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"]`, stanza).pop();
         if (slot) {
+            this.upload_metadata = this.getUploadRequestMetadata(stanza);
             this.save({
                 'get': slot.querySelector('get').getAttribute('url'),
                 'put': slot.querySelector('put').getAttribute('url')
@@ -222,6 +234,7 @@ const MessageMixin = {
 
     uploadFile () {
         const xhr = new XMLHttpRequest();
+
         xhr.onreadystatechange = async () => {
             if (xhr.readyState === XMLHttpRequest.DONE) {
                 log.info('Status: ' + xhr.status);
@@ -275,6 +288,7 @@ const MessageMixin = {
         };
         xhr.open('PUT', this.get('put'), true);
         xhr.setRequestHeader('Content-type', this.file.type);
+        this.upload_metadata.headers?.forEach(h => xhr.setRequestHeader(h.name, h.value));
         xhr.send(this.file);
     }
 };

+ 8 - 1
src/plugins/chatview/tests/http-file-upload.js

@@ -449,6 +449,8 @@ describe("XEP-0363: HTTP File Upload", function () {
                     </iq>`);
 
                 const promise = u.getOpenPromise();
+
+                spyOn(XMLHttpRequest.prototype, 'setRequestHeader');
                 spyOn(XMLHttpRequest.prototype, 'send').and.callFake(async () => {
                     const message = view.model.messages.at(0);
                     const el = await u.waitUntil(() => view.querySelector('.chat-content progress'));
@@ -461,7 +463,12 @@ describe("XEP-0363: HTTP File Upload", function () {
                     promise.resolve();
                 });
                 _converse.connection._dataRecv(mock.createRequest(stanza));
-                return promise;
+                await promise;
+                expect(XMLHttpRequest.prototype.setRequestHeader.calls.count()).toBe(2);
+                expect(XMLHttpRequest.prototype.setRequestHeader.calls.all()[0].args[0]).toBe('Content-type');
+                expect(XMLHttpRequest.prototype.setRequestHeader.calls.all()[0].args[1]).toBe('image/jpeg');
+                expect(XMLHttpRequest.prototype.setRequestHeader.calls.all()[1].args[0]).toBe('Authorization');
+                expect(XMLHttpRequest.prototype.setRequestHeader.calls.all()[1].args[1]).toBe('Basic Base64String==');
             }));
         });
     });