<-- Cameron's Log

All I wanted

Was to be able to POST from a web form with a custom authorization header. Is that so much to ask? BTW I don’t know anything about Javascript, so this will be fun.

No, it's not possible. [To set a custom header on a request in HTML.] - StackOverflow

Apparently there was this cool <meta http-equiv> tag which was supposed to tell the server to add something to the headers on its end. But the cost of parsing for this tag is too great, and no web server actually supports it.

Servers were supposed to parse HTML, extract meta tag and send it in real HTTP headers. As you can guess, this isn't implemented in any major web server. - StackOverflow Again

So I guess we have to use Javascript after all.

If you want to add a custom header (or set of headers) to an individual request then just add the headers property - StackOverflow again :)
// "Just use this" says above StackOverflow post.
// Request with custom header
$.ajax({
  url: 'foo/bar',
  headers: { 'x-my-custom-header': 'some value' }
});
// Okay, great, what do I do with that though?

So I guess this was an exercise in reading StackOverflow posts. We hijack the submit method using javascript, and give it this ajax jscript thing which just mirrors a bunch of stuff to build the request.

<form id="message" action="/entry" method="POST">
    ...
</form>

<script type="text/javascript">
    var frm = $('#message');
    frm.submit(function (ev) {
        $.ajax({
            type: frm.attr('method'),
            url: frm.attr('action'),
            data: frm.serialize(),
            headers: { 'Authentication': <%= @hmac_message %>}
            success: function (data) {
                alert('frosty');
            }
        });

        ev.preventDefault();
    });
</script>

(source)

That was an okay start, except I had to wrap it in a $(document).ready(function() {}); in order to get it to do anything. I tried a similar code that chained success as a function call after ajax, but apparently that either has to be a done call (if chaining) or move the success back inside the ajax call. (source)

I wasn’t 100% sure if you could just drop an erb interpolation into a javascript. I guess there’s no reason why not but it turns out: You sure can.

I found yet another code that suggested doing a beforeSend instead of just a headers: in ajax:

beforeSend: function (request) {
  request.setRequestHeader("AUTHORIZATION", "<%= @auth_string %>");
}

Although I just realized that I’m dumb, and I was setting the header as authentication instead of authorization. Also the HTTP_ is implied when setting the header name. Also I’m dumb because my other variable is @auth_string and not @hmac_message. Just not paying attention…

Anyway after some testing, that beforeSend is entirely unnecessary and the original headers: format works just fine. The document ready call is necessary.

Lastly I figured I would note that the ev.preventDefault call is a best practice alternative to return false, for reasons I don’t really care to remember.

Oh BTW it’s working, and I have my calculated HMAC string on the other side, so thanks for all your help, me.

<script type="text/javascript">
$(document).ready(function(){
  $('#form').submit(function(ev) {
    var valuesToSubmit = $(this).serialize();
    $.ajax({
      type: "POST",
      url: $(this).attr('action'), //sumbits it to the given url of the form
      data: valuesToSubmit,
      headers: { 'AUTHORIZATION': "<%= @auth_string %>"},
      success: function(response) {
         console.log("succeeded!");
      }
    });
    ev.preventDefault(); // prevents normal behaviour
  });
});
</script>