1

I'm building a Chrome extension that needs to post to a Rails app.

I can send the request with Fetch but the JSON object isn't right when Rails processes the request. My controller returns an error:

NoMethodError (undefined method permit' for #<String:0x00007ff83b5a36e8>)

The logs say the data object looks like this:

{"highlight"=>"{\"text\":\"hello world!\",\"url\":\"helloworld.com\"}"}

The data object should look something like this:

{"highlight"=>{"text"=>"hello world!", "url"=>"helloworld.com"}}

For some reason, Rails processes the request as a string with the quotes escaped, and not a hash. I don't know how to pass it from Fetch so that it doesn't do that.

Here is the JavaScript code:

function captureHighlight(selection, tab) {
  const highlight = {
      text: selection.selectionText, 
      url: selection.pageUrl
  }

  return highlight;
}

async function postHighlight(highlight) {
  let formData = new FormData();
  formData.append('highlight', JSON.stringify(highlight));

  const response = await fetch('http://localhost:3000/highlights', {
    method: 'POST',
    body: formData,
  });

  console.log(response);
}
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
greenie-beans
  • 440
  • 1
  • 5
  • 15
  • 2
    Your fetch is sending your data as `x-www-form-urlencoded` so Rails would process the posted fields as strings. I don't know Rails much but I don't think it knows how to automatically determine if request parameters are json and should be parsed. I think you are possibly confusing what you did with sending your request as JSON instead of `x-www-form-urlencoded`, if that is the case see: https://stackoverflow.com/questions/29775797/fetch-post-json-data – Patrick Evans Nov 16 '19 at 18:22
  • 3
    Rails definitely does not automatically detect and parse "JSON" fields in form data. I don't think any sensible framework does. How should they know that you even intended to parse the field as JSON and its not something like a code snippet? – max Nov 16 '19 at 18:37
  • I'm able to send the request in Postman as `x-www-form-urlencoded` and the Rails app successfully processes the request. I tried to match that Postman request with Fetch but having that string issue in Rails. Should I try sending it as `application/json` instead? – greenie-beans Nov 17 '19 at 01:57
  • i can't get it to work with application/json either. it leaves my browser in the proper form but then rails processes and malforms it into what i mentioned in my question – greenie-beans Nov 17 '19 at 03:53

3 Answers3

4

Rails .xhr? method checks if the X-Requested-With header contains the XMLHttpRequest value. Simply set it in headers, like so:

const response = await fetch('http://localhost:3000/highlights', {
  method: 'POST',
  body: formData,
  headers: {
    'X-Requested-With': 'XMLHttpRequest'
  },
});

and Rails will detect the request as xhr and return the response in the appropriate format.

2

You should include into headers 'Content-Type': 'application/json' and all will be ok. The problem jumps into existance because rails doesn't know what type your content have.

I_Shayderov
  • 148
  • 3
  • 9
  • i tried that but it didn't work. i never figured out why. i abandoned fetch and opted for the more reliable XMLHttpRequest. thanks! – greenie-beans Sep 30 '20 at 20:45
0

There are two things I did wrong. I abandoned fetch and found it easier to use XMLHttpRequest(). I don't have an JSON string problems with that, for whatever reason... FYI, my browser tool showed that my json was formatted correctly when the request left the client, whether using fetch or xml.

But, more importantly. I had CORS issues too. I should've gone back to the Chrome Extension documentation. All I had to do was grant permissions to whatever cross origin resource I want. https://developer.chrome.com/extensions/xhr

Thank y'all for reading/taking the time!

greenie-beans
  • 440
  • 1
  • 5
  • 15