From 9b2af1359614f4ad5afd05be7cf9853909334592 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston <174761+Jermolene@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:15:20 +0100 Subject: [PATCH] tm-http-request: Add support for binary responses With a demo courtesy of https://random.dog/ @rmunn you recently worked on the base64 utilities. I tried to use $tw.utils.base64Encode instead of window.btoa, but found that it didn't work. It's concerning because we expose that utility method as a filter operation, and it would be frustrating if we were not base64encoding things properly. --- core/modules/startup/rootwidget.js | 1 + core/modules/utils/dom/http.js | 16 ++++ ...ge_ tm-http-request Example Random Dog.tid | 88 +++++++++++++++++++ ...essage_ tm-http-request Example Zotero.tid | 4 +- .../WidgetMessage_ tm-http-request.tid | 4 +- 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request Example Random Dog.tid diff --git a/core/modules/startup/rootwidget.js b/core/modules/startup/rootwidget.js index f5d90afb5..716275cda 100644 --- a/core/modules/startup/rootwidget.js +++ b/core/modules/startup/rootwidget.js @@ -38,6 +38,7 @@ exports.startup = function() { url: params.url, method: params.method, body: params.body, + binary: params.binary, oncompletion: params.oncompletion, onprogress: params.onprogress, bindStatus: params["bind-status"], diff --git a/core/modules/utils/dom/http.js b/core/modules/utils/dom/http.js index 5b1f0abe6..083381d8d 100644 --- a/core/modules/utils/dom/http.js +++ b/core/modules/utils/dom/http.js @@ -90,6 +90,7 @@ wiki: wiki to be used for executing action strings url: URL for request method: method eg GET, POST body: text of request body +binary: set to "yes" to force binary processing of response payload oncompletion: action string to be invoked on completion onprogress: action string to be invoked on progress updates bindStatus: optional title of tiddler to which status ("pending", "complete", "error") should be written @@ -110,6 +111,7 @@ function HttpClientRequest(options) { this.bindProgress = options["bindProgress"]; this.method = options.method || "GET"; this.body = options.body || ""; + this.binary = options.binary || ""; this.variables = options.variables; var url = options.url; $tw.utils.each(options.queryStrings,function(value,name) { @@ -156,6 +158,8 @@ HttpClientRequest.prototype.send = function(callback) { type: this.method, headers: this.requestHeaders, data: this.body, + returnProp: this.binary === "" ? "responseText" : "response", + responseType: this.binary === "" ? "text" : "arraybuffer", callback: function(err,data,xhr) { var hasSucceeded = xhr.status >= 200 && xhr.status < 300, completionCode = hasSucceeded ? "complete" : "error", @@ -175,6 +179,16 @@ HttpClientRequest.prototype.send = function(callback) { data: (data || "").toString(), headers: JSON.stringify(headers) }; + /* Convert data from binary to base64 */ + if (xhr.responseType === "arraybuffer") { + var binary = "", + bytes = new Uint8Array(data), + len = bytes.byteLength; + for (var i=0; i + <$action-log/> + + <$list filter="[compare:number:gteq[200]compare:number:lteq[299]]" variable="ignore"> + + <$action-createtiddler + $basetitle=`$:/RandomDog/$(title)$` + text=<> + tags="$:/tags/RandomDog" + type={{{ [jsonget[content-type]] }}} + credits="https://random.dog/" + > + <$action-log msg="Created tiddler" title=<>/> + + +\end completion-download-dog + +<$action-sendmessage + $message="tm-http-request" + url=<> + method="GET" + binary="yes" + oncompletion=<> + var-title=<> +/> +\end download-dog + +\procedure get-random-dog() + +\procedure completion-get-json() +\import [subfilter{$:/core/config/GlobalImportFilter}] + <$action-log msg="In completion-get-json"/> + <$action-log/> + + <$list filter="[compare:number:gteq[200]compare:number:lteq[299]]" variable="ignore"> + + <$macrocall $name="download-dog" url={{{ [jsonget[url]] }}}/> + +\end completion-get-json + +<$action-sendmessage + $message="tm-http-request" + url="https://random.dog/woof.json" + method="GET" + oncompletion=<> +/> +\end get-random-dog + +!! Random Dogs + +This demo uses the API of the website https://random.dog/ to import a random dog image or video. + +<$button actions=<>> +Import a random dog image or video + + +<$list filter="[tag[$:/tags/RandomDog]limit[1]]" variable="ignore"> + +!! Imported Tiddlers + +<$button> +<$action-deletetiddler $filter="[tag[$:/tags/RandomDog]]"/> +Delete all imported random dogs + + +Export all imported random dogs: <$macrocall $name="exportButton" exportFilter="[tag[$:/tags/RandomDog]]" lingoBase="$:/language/Buttons/ExportTiddlers/"/> + + + +
    +<$list filter="[tag[$:/tags/RandomDog]!sort[modified]]"> +
  1. +<$link> +<$text text=<>/> + +
    +<$transclude $tiddler=<>/> +
    +
  2. + +
diff --git a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request Example Zotero.tid b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request Example Zotero.tid index 472f0abb0..c26eb9895 100644 --- a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request Example Zotero.tid +++ b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request Example Zotero.tid @@ -1,5 +1,5 @@ title: WidgetMessage: tm-http-request Example - Zotero -tags: $:/tags/Macro +tags: $:/tags/Global \procedure select-zotero-group() Specify the Zotero group ID to import @@ -34,7 +34,7 @@ Specify the Zotero group ID to import \procedure zotero-get-items(start:"0",limit:"25") \procedure completion() -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] <$action-log msg="In completion"/> <$action-log/> diff --git a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request.tid b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request.tid index f6c82e760..9c441c524 100644 --- a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request.tid +++ b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-http-request.tid @@ -1,6 +1,6 @@ caption: tm-http-request created: 20230429161453032 -modified: 20230429161453032 +modified: 20230717104212742 tags: Messages title: WidgetMessage: tm-http-request type: text/vnd.tiddlywiki @@ -18,6 +18,7 @@ The following parameters are used: |!Name |!Description | |method |HTTP method (eg "GET", "POST") | |body |String data to be sent with the request | +|binary |<<.from-version "5.3.1">> Set to "yes" to cause the response body to be treated as binary data and returned in base64 format | |query-* |Query string parameters with string values | |header-* |Headers with string values | |password-header-* |Headers with values taken from the password store | @@ -49,3 +50,4 @@ Note that the state tiddler $:/state/http-requests contains a number representin !! Examples * [[Zotero's|https://www.zotero.org/]] API for retrieving reference items: [[WidgetMessage: tm-http-request Example - Zotero]] +* [[Random Dog's|https://random.dog/]] API for retrieving random pictures of dogs showing how to retrieve binary data: [[WidgetMessage: tm-http-request Example - Random Dogs]]