Skip to content

Commit 21dc121

Browse files
handle removing request lock on errors (#3284)
* handle removing request lock on errors * Fixed non function verifyUrl tests and added tests for the double requests this PR fixes
1 parent 24a0106 commit 21dc121

4 files changed

Lines changed: 50 additions & 6 deletions

File tree

src/htmx.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4446,6 +4446,7 @@ var htmx = (function() {
44464446
if (!verifyPath(elt, finalPath, requestConfig)) {
44474447
triggerErrorEvent(elt, 'htmx:invalidPath', requestConfig)
44484448
maybeCall(reject)
4449+
endRequestLock()
44494450
return promise
44504451
}
44514452

@@ -4508,10 +4509,11 @@ var htmx = (function() {
45084509
}
45094510
}
45104511
maybeCall(resolve)
4511-
endRequestLock()
45124512
} catch (e) {
45134513
triggerErrorEvent(elt, 'htmx:onLoadError', mergeObjects({ error: e }, responseInfo))
45144514
throw e
4515+
} finally {
4516+
endRequestLock()
45154517
}
45164518
}
45174519
xhr.onerror = function() {

test/core/api.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ describe('Core htmx API test', function() {
602602
htmx.off('htmx:beforeSwap', handler)
603603
})
604604

605-
it('ajax api with can pass in custom handler', function() {
605+
it('ajax api with can pass in custom handler and handle if it throws error', function() {
606606
var onLoadError = false
607607
var handler = htmx.on('htmx:onLoadError', function(event) {
608608
onLoadError = true
@@ -617,6 +617,15 @@ describe('Core htmx API test', function() {
617617
} catch (e) {}
618618
div.innerHTML.should.equal('')
619619
onLoadError.should.equal(true)
620+
621+
// repeat the error resonse a 2nd time to make sure request lock removed after error
622+
onLoadError = false
623+
try {
624+
htmx.ajax('GET', '/test', { handler: function() { throw new Error('throw') } })
625+
this.server.respond()
626+
} catch (e) {}
627+
div.innerHTML.should.equal('')
628+
onLoadError.should.equal(true)
620629
htmx.off('htmx:onLoadError', handler)
621630
})
622631
})

test/core/headers.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,7 @@ describe('Core htmx AJAX headers', function() {
367367
htmx.off('bar', handlerBar)
368368
})
369369

370-
it.skip('should change body content on HX-Location', function(done) {
371-
// this test is disabled because a bug is triggered by an earlier request where it does not remove endRequestLock() on errors blocking all future requests
370+
it('should change body content on HX-Location', function(done) {
372371
this.server.respondWith('GET', '/test', [200, { 'HX-Location': '{"path":"/test2", "target":"#work-area"}' }, ''])
373372
this.server.respondWith('GET', '/test2', [200, {}, '<div>Yay! Welcome</div>'])
374373
var div = make('<div id="testdiv" hx-trigger="click" hx-get="/test"></div>')

test/core/security.js

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,17 @@ describe('security options', function() {
144144

145145
it('can make a real local data uri request when selfRequestOnly false', function(done) {
146146
htmx.config.selfRequestsOnly = false
147+
var pathVerifier = htmx.on('htmx:validateUrl', function(evt) {
148+
if (evt.detail.sameHost === false && evt.detail.url.protocol !== 'data:') {
149+
evt.preventDefault()
150+
}
151+
})
147152
this.server.restore() // use real xhrs
148153
var btn = make('<button hx-get="data:,foo">Initial</button>')
149154
btn.click()
150155
htmx.config.selfRequestsOnly = true
151156
setTimeout(function() {
157+
htmx.off('htmx:validateUrl', pathVerifier)
152158
btn.innerHTML.should.equal('foo')
153159
done()
154160
}, 30)
@@ -211,38 +217,66 @@ describe('security options', function() {
211217

212218
it('can cancel egress request based on htmx:validateUrl event', function(done) {
213219
this.timeout(4000)
220+
htmx.config.selfRequestsOnly = false
214221
// should trigger send error, rather than reject
215222
var pathVerifier = htmx.on('htmx:validateUrl', function(evt) {
216223
evt.preventDefault()
217-
htmx.off('htmx:validateUrl', pathVerifier)
218224
})
219225
var listener = htmx.on('htmx:invalidPath', function() {
220226
htmx.off('htmx:invalidPath', listener)
227+
htmx.off('htmx:validateUrl', pathVerifier)
221228
done()
222229
})
223230
this.server.restore() // use real xhrs
224231
// will 404, but should respond
225232
var btn = make('<button hx-get="https://hypermedia.systems/www/test">Initial</button>')
226233
btn.click()
234+
htmx.config.selfRequestsOnly = true
227235
})
228236

229237
it('can cancel egress request based on htmx:validateUrl event, sameHost is false', function(done) {
230238
this.timeout(4000)
239+
htmx.config.selfRequestsOnly = false
231240
// should trigger send error, rather than reject
232241
var pathVerifier = htmx.on('htmx:validateUrl', function(evt) {
233242
if (evt.detail.sameHost === false) {
234243
evt.preventDefault()
235244
}
236-
htmx.off('htmx:validateUrl', pathVerifier)
237245
})
238246
var listener = htmx.on('htmx:invalidPath', function() {
247+
htmx.off('htmx:validateUrl', pathVerifier)
239248
htmx.off('htmx:invalidPath', listener)
240249
done()
241250
})
242251
this.server.restore() // use real xhrs
243252
// will 404, but should respond
244253
var btn = make('<button hx-get="https://hypermedia.systems/www/test">Initial</button>')
245254
btn.click()
255+
htmx.config.selfRequestsOnly = true
256+
})
257+
258+
it('can cancel egress request based on htmx:validateUrl event and then allow a request', function(done) {
259+
htmx.config.selfRequestsOnly = false
260+
var requestCount = 0
261+
var pathVerifier = htmx.on('htmx:validateUrl', function(evt) {
262+
requestCount = requestCount + 1
263+
if (requestCount === 1) {
264+
evt.preventDefault()
265+
}
266+
})
267+
this.server.restore() // use real xhrs
268+
var btn = make('<button hx-get="data:,foo">Initial</button>')
269+
btn.click()
270+
setTimeout(function() {
271+
btn.innerHTML.should.not.equal('foo')
272+
btn.click()
273+
setTimeout(function() {
274+
htmx.off('htmx:validateUrl', pathVerifier)
275+
htmx.config.selfRequestsOnly = true
276+
btn.innerHTML.should.equal('foo')
277+
done()
278+
}, 30)
279+
}, 30)
246280
})
247281

248282
it('can disable script tag support with htmx.config.allowScriptTags', function() {

0 commit comments

Comments
 (0)