title: jQuery AJAX POST skips Django CSRF token header on first call
body: <h2>Using jQuery AJAX POST to call Django for an updated JSON set.</h2>
  
  <p>Have included both 'django.middleware.csrf.CsrfViewMiddleware' and 'django.middleware.csrf.CsrfResponseMiddleware' for the Django app and the code from <a href="https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax" rel="nofollow">https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax</a> in my JS file.</p>
  
  <pre><code>$(document).ajaxSend(function(event, xhr, settings) {
      function getCookie(name) {
      var cookieValue = null;
      if (document.cookie &amp;&amp; document.cookie != '') {
          var cookies = document.cookie.split(';');
          for (var i = 0; i &lt; cookies.length; i++) {
              var cookie = jQuery.trim(cookies[i]);
              // Does this cookie string begin with the name we want?
              if (cookie.substring(0, name.length + 1) == (name + '=')) {
                  cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                  break;
              }
          }
      }
      return cookieValue;
      }
      function sameOrigin(url) {
      // url could be relative or scheme relative or absolute
      var host = document.location.host; // host + port
      var protocol = document.location.protocol;
      var sr_origin = '//' + host;
      var origin = protocol + sr_origin;
      // Allow absolute or scheme relative URLs to same origin
      return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
          (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
          // or any other URL that isn't scheme relative or absolute i.e relative.
          !(/^(\/\/|http:|https:).*/.test(url));
      }
      function safeMethod(method) {
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
      }
  
      if (!safeMethod(settings.type) &amp;&amp; sameOrigin(settings.url)) {
      xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
      }
  });
  </code></pre>
  
  <p><strong>What happens</strong></p>
  
  <ol>
  <li>Clear browser cookies and load the page.</li>
  <li>Django responds to the AJAX POST request with 403 forbidden, <em>and then</em> sets a cookie with the CSRF.  But there is no JSON data.</li>
  <li>Trigger the AJAX POST request again</li>
  <li>Django receives the CSRF token from the X-CSRFToken header and responds appropriately with the JSON set.  </li>
  </ol>
  
  <p>The html and js files that are producing the ajax requests are NOT django produced.  The js is interacting with django through jquery $.post() .  So the only way to get a csrf token is to make a call to django before sending the post data.  </p>
  
  <p>It seems to me that the jQuery function solution given in the Django docs doesn't have a local cookie yet and is not waiting to get the cookie back from the server before it submits the POST request.  But when it gets one along with the 403, it uses the (now locally stored) cookie for subsequent tries and works fine. </p>
  
  <p>How can this be fixed so the cookie is set ahead of time and used by the AJAX POST request the first time around?  Am I wrong to believe that django csrf can be made to work strictly from ajax calls originating on the same site?</p>
  
  <hr>
  
  <p>*Other questions here relating to CSRF not working at all have suggested using ajax.Setup instead of ajaxSend, but according to this <a href="https://code.djangoproject.com/ticket/15284?cversion=0&amp;cnum_hist=6" rel="nofollow">https://code.djangoproject.com/ticket/15284?cversion=0&amp;cnum_hist=6</a> , that could cause problems with other JS, so ajaxSend was chosen.*  </p>