With a `new Request` in Node/React, how to pass params with a GET request? - ruby-on-rails

I have the following API call in my Reactjs app:
static getAllSkills(title_id) {
const request = new Request(`http://localhost:4300/api/v1/job_title_skills`, {
method: 'GET',
headers: new Headers({
'Content-Type': 'application/json'
}),
body: JSON.stringify({title_id: title_id})
});
return fetch(request).then(response => {
return response.json();
}).catch(error => {
return error;
});
}
Which points to a Rails endpoint which expects the param title_id like so:
def index
#skills = Skill.where(id: params[:title_id])
....
end
The controller is expecting a GET request however with the above, I'm getting the following JS console error:
Uncaught TypeError: Failed to construct 'Request': Request with GET/HEAD method cannot have body.
What is the right way to construct the Request and pass the param to the API?

I think the url in your api is waiting for the title_id maybe like:
api/v1/job_title_skills/:title_id
So you can append it in your url when you make the request:
static getAllSkills(title_id) {
const request = new Request(`http://localhost:4300/api/v1/job_title_skills/${title_id}`, {
headers: new Headers({
'Content-Type': 'application/json'
})
});
return fetch(request).then(response => {
return response.json();
}).catch(error => {
return error;
});
}

Related

handle post request with redux and rails api

i'm trying to post some data with fetch medthod in my api
export const CREATE_MATCH = 'CREATE_MATCH'
export function createMatch(user) {
const request = fetch("/api/matches", {
// Adding method type
method: "POST",
// Adding headers to the request
headers: {
"Content-type": "application/json",
"X-User-Token": user.authentication_token,
"X-User-Email": user.email
}
})
return {
type: CREATE_MATCH,
payload: request
}
}
but the i only get the response and not the data created
Response {type: "basic", url: "http://localhost:3000/api/matches", redirected: false, status: 200, ok: true, …}
i dont know how to get the data created.
in rails this is what i have, i dont have any data in a Match, only id and timestamps
def create
#match = Match.new
authorize #match
if #match.save
render json: #match
else
render_error
end
end
i've just find an answer with async / await function
export async function createMatch(user) {
const request = await fetch("/api/matches", {
// Adding method type
method: "POST",
// Adding body or contents to send
// body: JSON.stringify(),
// Adding headers to the request
headers: {
"Content-type": "application/json",
"X-User-Token": user.authentication_token,
"X-User-Email": user.email
}
})
const match = await request.json();
console.log(match)
return {
type: CREATE_MATCH,
payload: match
}
}

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'
}

Rails API empty request headers

Sending request from javascript to rails and providing the Authorization header with a token always shows up as empty headers on my rails API.
I have the follow piece of base code for all my API controllers:
module Api
class BaseController < ActionController::API
before_action :require_login
private
def require_login
unless signed_in?
head :unauthorized
end
end
def signed_in?
current_user.present?
end
def current_user
if request.headers['Authorization'].present?
User.find_by(token: request.headers['Authorization'])
else
nil
end
end
end
end
Doing my fetch request on javascript side like this:
fetch(`/api/clients?page=${page}`, {
headers: {
Accept: "application/json",
"Content-Type": "application/json",
'Authorization': AUTH_TOKEN
},
credentials: 'same-origin',
})
Fetching the value Authorization from request.headers always comes up as nil.
Anyone knows what might be going wrong?
Since you're using the Fetch() library, you can use the new Request() object which helps you customize your configurations.
// https://developer.mozilla.org/en-US/docs/Web/API/Request/Request
var myHeaders = new Headers({
"Content-Type": "application/json",
'Authorization': AUTH_TOKEN
});
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request(`/api/clients?page=${page}, myInit);
fetch(myRequest).then(function(response) {
...
});
I had the same issue with Axios and it turns out I was using a get request with headers and params wrongly.
const params = { id: "ghjfsd7634" };
const headers = {
headers: {
"Content-Type": "application/json",
Authorization: token,
},
};
axios
.get(url, params, headers)
.then(function foo(response) {
handleResponse(response.data);
})
.catch(function foo(error) {
console.log("GET Resource Error");
console.log(error);
});
Correct way: Params and headers in get requests are passed differently compared to post, put etc. requests. Axios takes the entire config in the second argument, not a list of config objects. Put the params inside the config, and pass the entire object as the second argument:
const params = { id: "ghjfsd7634" };
const headers = {
"Content-Type": "application/json",
Authorization: token,
};
const config = { headers, params };
await axios
.get(url, config)
.then(function foo(response) {
handleResponse(response.data);
})
.catch(function foo(error) {
console.log("GET Resource Error");
console.log(error);
});

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.

Observable with POST call in Angular2

I am using Angular2 in my application, And I saw advantages of using Observable while calling http calls. But somehow I am not able to make call when I am using Observable for POST requests, But it's working while GET request. If I use subscribe method, then POST is working.
Below is my code,
using Observable,
AddBreakoutsManually(breakoutUploads: Uploads): Observable<boolean> {
console.log("Data = ", JSON.stringify(breakoutUploads));
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post("/breakout/InsertUploads", JSON.stringify(breakoutUploads), options)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
Using subscribe,
Adding(breakoutUploads: Uploads) {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this.http
.post('/breakout/InsertUploads', JSON.stringify(breakoutUploads), options)
.subscribe(data => {
alert('ok');
}, error => {
console.log(error.json());
});
}
My API,
[HttpPost]
public bool InsertUploads([FromBody]BreakoutUpload breakoutUploads)
{
return true;
}
What mistake I am making while using observable in POST call ?
Not sure what I changed, But it starts working with below code,
AddBreakoutsManually(breakoutUploads: Uploads): Observable<string> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(Configuration.Url_AddBreakoutsManually, JSON.stringify(breakoutUploads), options) // ...using post request
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}

Resources