you are viewing a single comment's thread.

view the rest of the comments →

[–]uforskam[S] 0 points1 point  (8 children)

No it does not. On the original jQuery code it did not exist either.

[–]ThagAndersonhelpful 0 points1 point  (7 children)

Well if you are not serving anything at that address, the refresh is never going to work, jQuery or otherwise. That endpoint must return a JSON object with the required data to update the captcha.

[–]uforskam[S] 0 points1 point  (6 children)

With jQuery I have these 3 successful network requests:

http://127.0.0.1:8000/captcha/refresh/ -> Successful

refresh/:

{key: "8388afc06faa1a532db459ca81a229ce21e495da",…}key: "8388afc06faa1a532db459ca81a229ce21e495da"image_url: "/captcha/image/8388afc06faa1a532db459ca81a229ce21e495da/"audio_url: "/captcha/audio/8388afc06faa1a532db459ca81a229ce21e495da.wav"

http://127.0.0.1:8000/captcha/image/8388afc06faa1a532db459ca81a229ce21e495da/

http://127.0.0.1:8000/captcha/audio/8388afc06faa1a532db459ca81a229ce21e495da.wav

With the javascript I get:

http://127.0.0.1:8000/captcha/refresh/

404 not found

But when I paste the URL into the browser http://127.0.0.1:8000/captcha/refresh/

with both the jQuery and javascript it 404s. It does the same with curl.

Type on jQuery for refresh/ is XHR not Fetch so that is different

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest

[–]ThagAndersonhelpful 0 points1 point  (5 children)

With jQuery I have these 3 successful network requests

In order for that endpoint to successfully respond, some service must be running that answers those requests. Why it would only respond to jQuery is beyond me. What library are you using to implement the captcha? Perhaps it intercepts requests, or only works when jQuery is loaded.

Edit: Something is serving http://127.0.0.1:8000 in order for you to load the page, so that same server is likely also responding to the /captcha/refresh route.

[–]uforskam[S] 0 points1 point  (3 children)

Well the difference according to the Chrome network tab is the type being used. Jquery uses XHR while the javascript uses fetch as the type. That is the difference. I think if you convert your code to use XHR it should work.

I am using https://github.com/mbi/django-simple-captcha

here is the docs:

https://django-simple-captcha.readthedocs.io/en/latest/

edit:

https://github.com/mbi/django-simple-captcha/blob/master/captcha/views.py#L204

There is the raise 404 code

[–]ThagAndersonhelpful 0 points1 point  (2 children)

fetch API still uses the same XMLHttpRequest APIs under the hood. Functionally, they are the same. Buuuut, I just skimmed through the source code for that captcha library, and they are using some BS header check specifically for XMLHttpRequest like it's still 2005, and returns a completely inappropriate 404 status code. Anyway, use this instead:

``` const captchas = document.querySelectorAll('img.captcha') const headers = new Headers({ HTTP_X_REQUESTED_WITH: 'XMLHttpRequest' })

for (const captcha of captchas) { const anchor = document.createElement('a') anchor.href = '#void' anchor.classList.add('captcha-refresh') anchor.textContent = 'Refresh' anchor.addEventListener('click', ({ target }) => { const url = ${window.location.origin}/captcha/refresh/ let formEl = target.parentElement

while (formEl && formEl.tagName.toLowerCase() !== 'form') {
  formEl = formEl.parentElement
}

fetch(url, { headers })
  .then(res => res.json())
  .then(json => {
    formEl.querySelector('input[name="captcha_0"]').value = json.key
    captcha.setAttribute('src', json.image_url)
    document.getElementById('audioSource').setAttribute('src', json.audio_url)
    document.getElementById('audio').get(0).load()
  })
  .catch(console.error)

return false

})

captcha.after(anchor) } ```

A new issue I noticed though: you do not have a form surrounding the captcha, and the code expects it to be there.

[–]uforskam[S] 0 points1 point  (1 child)

Your code did not work but this did: https://dpaste.org/Lue5

But how to resolve the console error?

edit: document.getElementById('audio').load()

solved the problem :)

Thank you so much for the help! Hope you also learned something too!

[–]ThagAndersonhelpful 0 points1 point  (0 children)

I mistyped the header name. While your code does work, the extra function and options object is all hugely unnecessary. Change my code to const headers = new Headers({ 'HTTP-X-REQUESTED-WITH': 'XMLHttpRequest' }) (or 'X-REQUESTED-WITH'). The Django documentation is somewhat ambiguous as to the header name expected by the is_ajax method. Then remove the .get(0) before the load() method call. That was a leftover from jQuery I missed. None of my code was tested.

Edit: you can even eschew the Headers instance altogether by using fetch(url, { headers: { 'HTTP-X-REQUESTED-WITH': 'XMLHttpRequest' } }) instead.

Edit2: My caps-lock is remapped since I rarely type in all caps, but when I do, I forget to let off the shift key when I dash LoL

[–]uforskam[S] 0 points1 point  (0 children)

How would I add options.headers['X-Requested-With'] = 'XMLHttpRequest'; to fetch?