support for hx-request attribute with the following config values:

* `timeout` - the request timeout
* `credentials` - send credentials w/ the request
* `noHeaders` - do not send any non-standard headers with the request

We also support the `htmx.config.timeout` configuration value for setting the default timeout
This commit is contained in:
carson 2021-07-07 06:37:40 -06:00
parent bbf2ae4412
commit a4a9d2d733
3 changed files with 65 additions and 5 deletions

View File

@ -50,6 +50,7 @@ return (function () {
allowEval:true,
attributesToSettle:["class", "style", "width", "height"],
withCredentials:false,
timeout:0,
wsReconnectDelay: 'full-jitter',
disableSelector: "[hx-disable], [data-hx-disable]",
useTemplateFragments: false,
@ -2018,6 +2019,9 @@ return (function () {
if (str.indexOf("javascript:") === 0) {
str = str.substr(11);
evaluateValue = true;
} else if (str.indexOf("js:") === 0) {
str = str.substr(3);
evaluateValue = true;
}
if (str.indexOf('{') !== 0) {
str = "{" + str + "}";
@ -2224,6 +2228,8 @@ return (function () {
path = getDocument().location.href;
}
var requestAttrValues = getValuesForElement(elt, 'hx-request');
var requestConfig = {
parameters: filteredParameters,
unfilteredParameters: allParameters,
@ -2231,6 +2237,8 @@ return (function () {
target:target,
verb:verb,
errors:errors,
withCredentials: requestAttrValues.credentials || htmx.config.withCredentials,
timeout: requestAttrValues.timeout || htmx.config.timeout,
path:path,
triggeringEvent:event
};
@ -2278,13 +2286,18 @@ return (function () {
}
xhr.overrideMimeType("text/html");
xhr.withCredentials = htmx.config.withCredentials;
xhr.withCredentials = requestConfig.withCredentials;
xhr.timeout = requestConfig.timeout;
// request headers
for (var header in headers) {
if (headers.hasOwnProperty(header)) {
var headerValue = headers[header];
safelySetHeaderValue(xhr, header, headerValue);
if (requestAttrValues.noHeaders) {
// ignore all headers
} else {
for (var header in headers) {
if (headers.hasOwnProperty(header)) {
var headerValue = headers[header];
safelySetHeaderValue(xhr, header, headerValue);
}
}
}
@ -2336,6 +2349,13 @@ return (function () {
maybeCall(reject);
endRequestLock();
}
xhr.ontimeout = function() {
removeRequestIndicatorClasses(indicators);
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
triggerErrorEvent(elt, 'htmx:timeout', responseInfo);
maybeCall(reject);
endRequestLock();
}
if(!triggerEvent(elt, 'htmx:beforeRequest', responseInfo)){
maybeCall(resolve);
endRequestLock()

View File

@ -0,0 +1,39 @@
describe("hx-request attribute", function() {
beforeEach(function () {
this.server = makeServer();
clearWorkArea();
});
afterEach(function () {
this.server.restore();
clearWorkArea();
});
it('basic hx-request timeout works', function (done) {
var timedOut = false;
this.server.respondWith("GET", "/test", "Clicked!");
var div = make("<div hx-post='/vars' hx-request='\"timeout\":1'></div>")
htmx.on(div, 'htmx:timeout', function(){
timedOut = true;
})
div.click();
setTimeout(function(){
div.innerHTML.should.equal("");
// unfortunately it looks like sinon.js doesn't implement the timeout functionality
// timedOut.should.equal(true);
done();
}, 400)
});
it('hx-request header works', function () {
this.server.respondWith("POST", "/vars", function (xhr) {
should.equal(xhr.requestHeaders['HX-Request'], undefined);
xhr.respond(200, {}, "Clicked!")
});
var div = make("<div hx-post='/vars' hx-request='{\"noHeaders\":true}'></div>")
div.click();
this.server.respond();
div.innerHTML.should.equal("Clicked!");
});
});

View File

@ -104,6 +104,7 @@
<script src="attributes/hx-preserve.js"></script>
<script src="attributes/hx-push-url.js"></script>
<script src="attributes/hx-put.js"></script>
<script src="attributes/hx-request.js"></script>
<script src="attributes/hx-select.js"></script>
<script src="attributes/hx-sse.js"></script>
<script src="attributes/hx-swap-oob.js"></script>