HttpClient tries to parse payload to json - ruby-on-rails

I'm working on a project which has rails api as a back-end and angular as a front end. In one particular point I need to make a text/plain call. Even though I set the content-type to 'text/plain', HttpClient tries to parse payload to json. I can't figure out why it behaves like that.
Rails back-end:
def getTranslations
render plain: 'some plain text'
end
Angular Client:
headers = new HttpHeaders({
"Content-Type": "text/plain",
"Accept": "text/plain"
});
this.http.get<any>('http://localhost:3000/getTranslations', { headers: this.headers })
.map((res:Response) => {
console.log(res);
return res.text()
})
.subscribe(
res => {
console.log(res);
},
err => {
console.log(err);
}
)
Response:
"Http failure during parsing for http://localhost:3000/getTranslations"
Unexpected token s in JSON
Thanks.

After looking at angular.io documentation I have found the answer.
Instead of making request by http.get I have changed the method call to
this.http.get('http://localhost:3000/getTranslations', { responseType: 'text'} )
.map((res:string) => {
console.log(res);
return res
})
.subscribe(
res => {
console.log(res);
},
err => {
console.log(err);
}
)

Related

Missing parameters in Rails Controller when using multipart/form-data in React

I am using Rails and React with Axios to create a record. In my React app I collect all the data and put it inside of FormData like this:
const createVtc = () => {
let data = new FormData()
data.append('image', vtcImageToSend)
data.append('name', vtcName)
data.append('description', vtcDescription)
data.append('main_color', vtcColor)
data.append('minimum_age_to_join', vtcMinimumAge)
axios.post(`${ROOT_API}/v1/vtcs/create`, data, {
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'multipart/form-data'
}
}).then(res => {
console.log(res.data);
history.push('/dashboard')
}).catch(err => {
console.log(err);
})
};
This contains all the necessary data in order to create a record.
This is the Rails controller responsible for creating it:
def create
vtc = Vtc.new(vtc_params)
# other code is not important
end
And this is vtc_params private function:
def vtc_params
params.require(:vtc).permit(:id, :name, :description, :minimum_age_to_join, :main_color, :image)
end
Pretty standard stuff. It worked until I had to implement picture upload which made me switch to FormData upload and since then Rails throws this error:
ActionController::ParameterMissing in V1::VtcsController#create
param is missing or the value is empty: vtc
I can assume what's the problem but I don't know how to fix it. Before FormData I used to send it like this:
// other stuff
axios.post(`${ROOT_API}/v1/vtcs/create`, {
"vtc": {
"name": vtcName,
// etc.
}
}, {
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'multipart/form-data'
}
})
// other stuff
All of the data was inside of "vtc" object but now it's just data variable. I tried adding {"vtc": data} as Axios data which not surprisingly didn't work.
Just wrap your data variable in an object with the key vtc:
axios.post(`${ROOT_API}/v1/vtcs/create`, {vtc: data}, {
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'multipart/form-data'
}

Response Isn't Converting To JSON

I'm trying to take info from a React form and post it to my Rails database, but I get an error "unexpected token '<' at position 0" which means my response is still HTML and not JSON.
Here's my code:
export const createCar = car => {
return dispatch => {
return fetch(`${API_URL}/cars/create`, {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({ car: car })
})
.then(response => response.json())
.then(car => {
dispatch(addCar(car))
dispatch(resetCarForm())
})
.catch(error => console.log(error + 'createCar POST failed'))
}
}
Is there a reason why it's not converting to JSON?
Additionally, I don't seem to be able to drop debugger into my code, or at least in this function - do I need to import it or something?
I'm thinking that your server is sending you back HTML and then you are trying to parse it in response.json()
use a try/catch in this block:
export const createCar = car => {
return dispatch => {
return fetch(`${API_URL}/cars/create`, {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({ car: car })
})
.then(response => {
try {
return response.json()
} catch(error) {
console.error(error);
}
})
.then(car => {
dispatch(addCar(car))
dispatch(resetCarForm())
})
.catch(error => console.log(error + 'createCar POST failed'))
}

How to add a BearerToken to React API Requests?

newbie to React looking for some help... I'm using React to make API requests like so:
class CatsApi {
static createCat(cat) {
const request = new Request('http://localhost:4300/api/v1/cats', {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json'
}),
body: JSON.stringify(cat)
});
return fetch(request).then(response => {
return response.json();
}).catch(error => {
return error;
});
}
Meanwhile, I have authentication to my API via react-devise:
https://github.com/timscott/react-devise
Which has a method getBearerToken like so: https://github.com/timscott/react-devise/blob/master/src/actions/authTokenStore.js
How do I use getBearerToken to pass the API the token so API requests are authenticated with the token?
Thank you!
You can use the Authorization header like:
{ 'Authorization': `Bearer ${authToken}` }
Using fetch you could try with something like:
fetch('http://localhost:4300/api/v1/cats', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
'Accept' : 'application/json',
'Content-Type' : 'application/json',
},
body: JSON.stringify({
cat : cat_value,
})
})
.then((response) => response.json())
.then((responseData) => { console.log(responseData) })
.catch((error) => { console.log(error) })
.done()
Also, it'd be great to see what's the Rails output in the console when you make a request, or the browser console.

React Native fetch "unsupported BodyInit type"

I'm trying to send a POST request to the OneSignal REST API using fetch:
var obj = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
'app_id': '(API KEY)',
'contents': {"en": "English Message"},
'app_ids': ["APP IDS"],
'data': {'foo': 'bar'}
})
}
fetch('https://onesignal.com/api/v1/notifications', obj)
I know you're not really supposed to put your API key in client code, but this is just a test to see if it would work. Besides, the error I'm getting isn't a bad response from the server, it's:
Possible Unhandled Promise Rejection (id: 0):
unsupported BodyInit type
I've tried putting a catch method on the fetch, but it doesn't get called.
At a bit of a loss, not really sure how to proceed.
Thanks in advance!
Even I tried the same POST request for One-Signal REST API for creating notifications,the below worked for me fine.
const bodyObj = {
app_id: "**********",
included_segments: ["All"],
data: {"foo": "bar"},
contents: {"en": "Hi good morning"}
}
fetch('https://onesignal.com/api/v1/notifications',{
method:'POST',
headers:{
'Authorization':'Basic **********',
'Content-Type':'application/json'
},
body:JSON.stringify(bodyObj)
})
.then((response) => response.json())
.then((responseJson) => {
console.log("success api call");
})
.catch((error) => {
console.error(error);
});
Have you tried to change your json to the one below?
JSON.stringify({
app_id: '(API KEY)',
contents: {en: "English Message"},
app_ids: ["APP IDS"],
data: {foo: 'bar'}
})
Or even tried a simpler json?

isomorphic fetch post can't read body on server

I'm struggling with this strange problem, I can't seem to solve. I'm using isomorphic fetch to to post data to a server. I'm sending the body as a JSON-string. But on the server, I can't read the body, it's just an empty object.
The stack is: node, react.
Here is the client-code:
handleSubmit = (event) => {
const { dispatch } = this.props;
fetch('/api/me', {
method: 'POST',
header: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'xxx'
})
})
.then(response => response.json())
.then( json => dispatch( login( json ) ))
.catch( err => console.log(err) )
}
The server code:
var jsonParser = bodyParser.json()
app.post( '/api/me', jsonParser, ( req, res ) => {
console.log('req', req.body);
})
I've tried googling the problem. But the few solutions I found, didn't to the trick.
All help is much appreciated.
BR
Martin
// UPDATE //
figured it out, it was a silly 's', I had forgotten. 'header' should be 'headers'
Thank you for the update that one of the params should be plural:
headers: {
'Accept': ...,
'Content-Type': ...
},
You appended it to the question. Please feel free to accept this as the answer, or to create a new answer with that text, and accept it. Then the "unanswered" queue will contain one less dangling entry for folks to stumble upon.

Resources