Rails 5: How Can a Form Submit with Custom HTTP Headers?
Asked Answered
C

3

17

I cant seem to find any information on how to get a webform in Rails 5 to submit with custom headers. I would like the URL to which I am sending a PUT request to also receive some custom headers. I am surprised that there is no argument for form_for for this.

I could accomplish this by submitting the form to an action where I modify the headers there, e.g., request.headers['my-header'] = 'xyz'. I would then have to make the PUT request from within this "middle" controller action, and I feel this additional step is clunky and unconventional.

I could also use jQuery to bind to the submit click, and submit the form data after adding the headers via JavaScript. Id rather not involve another layer (i.e., JS) in this process.

I would rather not do either. Is there a way I can just use the Rails form helpers (or some controller helper) to add some custom headers to the request made by the form submission?

Curative answered 2/2, 2017 at 21:56 Comment(3)
Why do you want to send a custom http header with the form? What do you try to archive?Quadragesimal
@Quadragesimal really, the answer is "whatever I want" - why shouldnt I have needs to send custom headers? I could think of many reasons. For this particular case, I am trying to send bearer token headers to an API which requires them for authentication.Curative
We have two headers we need to set, "Xmlrpc-Token", and "Token". How could we set these from a form_for?Pulpiteer
C
9

Rails does not have any tags that allows us to do that and therefore cannot add custom headers to your request.

In fact, you cannot set custom headers in html forms without xhr plugins, You have to use it with ajax. Something like this:-

<%= form_tag("/your_url", method: :post, :remote => true, :html => { id: "form-id" }) do |f| %>
    ...your form here...
<% end %>

and then you ajax code:-

$('#form-id').submit(function() {
    var valuesToSubmit = $(this).serialize();
    $.ajax({
        type: "POST",
        url: $(this).attr('action'),
        data: valuesToSubmit,
        headers: { 'Xmlrpc-Token': 'value' , 'Token': 'another_value'}
    }).success(function(response){
        //success code
    });
    return false;
});

Using only remote: true in rails will make ajax call, but you want to be able to customize it using the code above.

Corniculate answered 25/5, 2017 at 23:47 Comment(2)
No, the form tag does not simply create the form tag. When {remote: true}, Rails creates the HTML form tag and also provides javascript to get the values from the form, and make an AJAX call. So I was looking for some parameter to the form tag method to tell Rails to include setting a custom header when it makes its AJAX call.Pulpiteer
Right, will correct the answer, its a little more than just converting to html tags. But to answer your question, there is no way of adding headers using a rails tag. The alternative is to use js. Using only remote: true will not allow you to customize your request headers. For that you need to disable that behaviour(using return false in code above), and send it using your own submit function.Corniculate
D
3

Browser will send only standard headers like cookies, contenttype, etc. You can not send Authorization header (or other custom) using HTML form submit. You should use AJAX to do that.

Dramaturge answered 23/5, 2017 at 19:34 Comment(5)
It does not work with remote: true which uses AJAX.Pulpiteer
so you can use: github.com/rails/jquery-ujs/wiki/ajax, $('#your_form').on('ajax:beforeSend', function(event, data, status, xhr) { // Add headers });Dramaturge
Well, with remote: false Rails just builds a &lt;form&gt; tag, which won't set headers. With remote: true you are saying Rails won't do that, but for no good reason.Pulpiteer
@MarlinPierce: apparently, no one needed that before. That's good enough reason. :)Dialectics
@AlexLyalka this question is asking if it can be accomplished with Rails' #form_for, specifically. Thanks for providing another option.Curative
E
0

$("#idForm").submit(function(e) {

    var url = "path/to/your/script.php"; // the script where you handle the form input.

    $.ajax({
           type: "POST",
           url: url,
           data: $("#idForm").serialize(), // serializes the form's elements.
           success: function(data)
           {
               alert(data); // show response from the php script.
           }
         });

    e.preventDefault(); // avoid to execute the actual submit of the form.
});
<%= form_tag("/your_url", method: :post, :remote => true, :html => { id: "form-id" }) do |f| %>
    ...your form here...
<% end %>

$("#idForm").submit(function(e) {

    var url = "path/to/your/script.php"; // the script where you handle the form input.

    $.ajax({
           type: "POST",
           url: url,
           data: $("#idForm").serialize(), // serializes the form's elements.
           success: function(data)
           {
               alert(data); // show response from the php script.
           }
         });

    e.preventDefault(); // avoid to execute the actual submit of the form.
});
Everest answered 30/5, 2017 at 12:41 Comment(1)
Thanks, but I think everyone is aware that this can be done with javascript. The question was whether or not this can be accomplished with a Rails form helper.Curative

© 2022 - 2024 — McMap. All rights reserved.