I tried fetch to call api and passing credentials "include" to header which set cookies from server initially but on page refresh cookies got lost.
public post = async (payload:any, endpoint: string):Promise<any> => {
return new Promise((resolve, reject) => {
console.log(${config.baseUrl}${endpoint})
const URL = ${config.baseUrl}${endpoint};
fetch(URL, {
credentials: 'include',
method: 'POST',
body: JSON.stringify(payload),
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(data => data.json())
.then((data:any) => {
console.log("data", data)
const responsePayload = {
statusCode: data.status,
data: data
};
resolve(responsePayload);
})
.catch((error:any) => {
if (error.response === undefined) {
const errorpayload = {
statusCode: 503,
title: 'network error occured',
parameter: 'Network Error',
};
reject(errorpayload);
} else {
const errors = error.response.data.errors;
const errorPayload = {
statusCode: error.response.status,
data: error.response.data.errors,
};
reject(errorPayload);
}
});
});
};
Better read cookies on login and store it to loaclstorage and from there you can use it the way you want.
Related
I can sign up a user via postman. But when I use my app I am getting that error. My signup method is ok. But my fetch address is not good. here is method.
export const signup = user => {
return fetch(`${API}/signup`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
.then(response => {
return response.json();
})
.catch(err => {
console.log(err);
});
};
const API = process.env.REACT_APP_API_URL;
status: 500, error: "Internal Server Error"
message: Could not extract response: no suitable HttpMessageConverter found for response type [class com.clone.instagram.authservice.fetchdata.model.Example] and content type [text/html;charset=utf-8]"
So strangely this error has started showing up while accessing insta API,
What's strange is this happens "only sometimes",
And never happened before.
It works some times, some times it pops this error
const request = (options) => {
const headers = new Headers();
headers.append("Content-Type", "application/json");
if (localStorage.getItem("accessToken")) {
headers.append(
"Authorization",
"Bearer " + localStorage.getItem("accessToken")
);
}
const defaults = { headers: headers };
options = Object.assign({}, defaults, options);
return fetch(options.url, options).then((response) =>
response.json().then((json) => {
if (!response.ok) {
return Promise.reject(json);
}
return json;
})
);
};
export function registerInstaUserInfo(instaUserINfoRequest){
if (!localStorage.getItem("accessToken")) {
return Promise.reject("No access token set.");
}
console.log("inside getInstaUserInfo request ");
return request({
url: properties.INSTA_USER_REGISTER ,
method: "POST",
body: JSON.stringify(instaUserINfoRequest),
});
}
const getInstaUserInfoFromService = (response) => {
//store respose.data
if (response.data.user_id) {
console.log("setting up insta user staate ", response.data);
localStorage.setItem("insta_user", response.data);
cookies.set("insta_user", response.data, { path: "/" });
console.log("cookies ", cookies.get("insta_user"));
const fb_access_token = localStorage.getItem("accessToken");
console.log("fb_access_token", fb_access_token);
const user_info = registerInstaUserInfo(response.data)
.then((res) => {
console.log(res);
setLinkedInstaAccounts([...linkedAccounts, res]);
})
.catch((err) => console.error("Hello stackoverlflowpeople this is where error happens", err));
console.log("user_info", user_info);
props.history.push("/home");
//redirecting to account.js
// props.history.push("/me");
}
};
const successResponse = (code) => {
console.log("inside success func");
console.log(code);
var bodyFormData = new FormData();
bodyFormData.append("redirect_uri", properties.INSTA_REDIRECT_URL);
bodyFormData.append("code", code);
bodyFormData.append("client_id", properties.INSTA_CLIENT_ID);
bodyFormData.append("client_secret", properties.INSTA_CLIENT_SECRECT);
bodyFormData.append("grant_type", "authorization_code");
axios({
method: "post",
url: properties.INSTA_ACCESS_TOKEN_URL,
data: bodyFormData,
headers: {
"Content-Type": "multipart/form-data",
Accept: "application/vnd.api+json",
},
})
.then(getInstaUserInfoFromService)
.catch(function (response) {
//handle error
console.log(response);
});
};
----
//component
<InstagramLogin
clientId={properties.INSTA_CLIENT_ID}
buttonText="Login"
redirectUri={properties.INSTA_REDIRECT_URL}
scope="user_profile,user_media"
onSuccess={successResponse}
onFailure={failedresponseInstagram}
/>
=====================THIS getInstaUserFromService is where error happens
const getInstaUserInfoFromService = (response) => {
//store respose.data
if (response.data.user_id) {
console.log("setting up insta user staate ", response.data);
localStorage.setItem("insta_user", response.data);
cookies.set("insta_user", response.data, { path: "/" });
console.log("cookies ", cookies.get("insta_user"));
const fb_access_token = localStorage.getItem("accessToken");
console.log("fb_access_token", fb_access_token);
const user_info = registerInstaUserInfo(response.data)
.then((res) => {
console.log(res);
setLinkedInstaAccounts([...linkedAccounts, res]);
})
.catch((err) => console.error("Hello stackoverlflowpeople this is where error happens", err));
console.log("user_info", user_info);
props.history.push("/home");
//redirecting to account.js
// props.history.push("/me");
}
};
I was using this but I have not touched headers or anything, is it something with Instagram server?
I am writing a mobile application with using React Native. At some part, I need to send a post request and get response including the error part. So, for some certain input, API(my own) returns 409 with a message. Example return:
{
"status": 409,
"message": "E-mail is already exists!"
}
Here, I want to take that message and show to the user. This is what I tried:
UserService.signup({ fullName, email, username, password })
.then(response => {
this.setState({ signUp: true });
if (response.result) {
Toast.show(messages.successfulSignUp, {
backgroundColor: "green",
duration: Toast.durations.LONG,
position: Toast.positions.TOP
});
this.props.navigation.navigate("SignIn");
} else {
}
})
.catch(error => {
Toast.show(error.message, {
backgroundColor: "red",
duration: Toast.durations.LONG,
position: Toast.positions.TOP
});
this.setState({ signUp: false });
});
I tried error.message, error.response, error, error.data keys, but it always says TypeError: undefined is not an object (evaluating 'error.message'). So, how can I get the message from error object?
Edit: This is how I send the request:
import { post } from "./api";
export default {
signup: ({ fullName, email, username, password }) => {
return post("/user/register", { fullName, email, username, password });
}
};
export const request = config => {
return new Promise((resolve, reject) => {
axiosInstance
.request({
url: config.url,
method: config.method || "get",
data: config.body,
headers: {
"Content-Type": "application/json",
"X-Auth-Token": store.getState().auth.token
}
})
.then(response => {
resolve(response.data);
})
.catch(error => {
reject(error.data);
});
});
};
export const post = (url, body = {}) => {
return request({
url,
body,
method: "post"
});
};
Finally I solved this issue. I had to change my request method and the way I reach out to the error:
export const request = (config) => {
return new Promise((resolve, reject) => {
axiosInstance.request({
url: config.url,
method: config.method || 'get',
data: config.body,
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': store.getState().auth.token,
}
}).then(response => {
resolve(response.data)
}).catch(error => {
reject(error.response)
})
})
}
// This is how reach out to the error message:
console.log(error.data.message);
Depending on what the backend returns, the error message in axios is in response.data of the error object.
.catch(error => {
const errResponse = (error && error.response && error.response.data)
|| (error && error.message);
reject(errResponse);
});
I am trying to fetch multiple requests in an order in React. There are 3 requests,
first one gathering encoded information from backend
get token from authentication server
use api with the token.
All of them must be in order. But I am having difficulties because of async fetch function. I can't reach fetch's response outside of .then() block.
To solve it, I used await / async. But it caused another problem. My 3 requests must be in a sequencial order. When I use async, order gets broken.
Here is the code.
class App extends Component {
constructor() {
super();
this.state = { code: '', encoded: '', access_token: '', refresh_token: '' };
}
getCarDetails() {
const carId = '2F3A228F6F66AEA580'
var query = 'https://api.mercedes-benz.com/experimental/connectedvehicle/v1/vehicles/'.concat(carId).concat('/doors')
fetch(query, {
method: 'GET',
headers: {
'Authorization': 'Bearer '.concat(this.state.access_token),
'accept': 'application/json'
}
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err));
}
getToken() {
var post_data = {
grant_type: 'authorization_code',
code: this.state.code,
redirect_uri: 'http://localhost'
}
fetch('https://api.secure.mercedes-benz.com/oidc10/auth/oauth/v2/token', {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic '.concat(this.state.encoded),
'Content-Type': 'application/x-www-form-urlencoded'
}),
body: queryString.stringify(post_data)
})
.then(res => res.json())
.then(data => this.setState({ access_token: data.access_token, refresh_token: data.refresh_token }))
.catch(err => console.log(err));
}
getEncodedClientIdAndClientSecret() {
if (this.state.code != null) {
fetch('http://localhost:8000/encodeClientIdAndSecret', {
method: 'POST'
})
.then(res => res.json())
.then(data => this.setState({ encoded: data.encoded }))
.catch(err => console.log(err));
}
}
componentDidMount() {
const values = queryString.parse(this.props.location.search)
this.setState({ code: values.code })
console.log(this.state)
this.getEncodedClientIdAndClientSecret();
console.log(this.state) //this state is empty
//this.getToken();
//this.getCarDetails();
}
AWAIT / ASYNC
async getEncodedClientIdAndClientSecret() {
if (this.state.code != null) {
const response = await fetch('http://localhost:8000/encodeClientIdAndSecret', {
method: 'POST'
})
const data = await response.json();
console.log(data)
}
}
If I put await / async, I am having sequence problem between 3 requests.
in order to use async await on methods like
await getEncodedClientIdAndClientSecret();
await getToken();
you need to first return a promise from those functions like:
getToken() {
var post_data = {
grant_type: 'authorization_code',
code: this.state.code,
redirect_uri: 'http://localhost'
}
return fetch('https://api.secure.mercedes-benz.com/oidc10/auth/oauth/v2/token', {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic '.concat(this.state.encoded),
'Content-Type': 'application/x-www-form-urlencoded'
}),
body: queryString.stringify(post_data)
})
.then(res => res.json())
.then(data => this.setState({ access_token: data.access_token, refresh_token: data.refresh_token }))
.catch(err => console.log(err));
}
so it can wait for the promise to finish, othewise they will run in parallel and finish in random order.
I have stripe async code in my React app, and trying to add error handling in my code but have no idea how to handle it. i know how to do it with .then() but async/await is new to me
EDITED
added .catch() i got errors in network tab in response tab.
but i can log it to console?
submit = async () => {
const { email, price, name, phone, city, street, country } = this.state;
let { token } = await this.props.stripe
.createToken({
name,
address_city: city,
address_line1: street,
address_country: country
})
.catch(err => {
console.log(err.response.data);
});
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(err => {
console.log(err.response.data);
});
console.log(response);
if (response.ok)
this.setState({
complete: true
});
};
thanks
Fetch detects only network errors. Other errors (401, 400, 500) should be manually caught and rejected.
await fetch("/charge/pay", headers).then((response) => {
if (response.status >= 400 && response.status < 600) {
throw new Error("Bad response from server");
}
return response;
}).then((returnedResponse) => {
// Your response to manipulate
this.setState({
complete: true
});
}).catch((error) => {
// Your error is here!
console.log(error)
});
If you are not comfortable with this limitation of fetch, try using axios.
var handleError = function (err) {
console.warn(err);
return new Response(JSON.stringify({
code: 400,
message: 'Stupid network Error'
}));
};
var getPost = async function () {
// Get the post data
var post = await (fetch('https://jsonplaceholder.typicode.com/posts/5').catch(handleError));
// Get the author
var response = await (fetch('https://jsonplaceholder.typicode.com/users/' + post.userId).catch(handleError));
if (response.ok) {
return response.json();
} else {
return Promise.reject(response);
}
};
You can either use try/catch just like normal, imperative programming:
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
} catch(error) {
// Error handling here!
}
Or you can mix-and-match .catch() just like you do with promises:
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(function(error) {
// Error handling here!
});
Wrap your await with try catch.
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
console.log(response);
} catch (error) {
console.log(error);
}
This works if server returns { message: "some error" } but I'm trying to get it to support res.statusText too:
const path = '/api/1/users/me';
const opts = {};
const headers = {};
const body = JSON.stringify({});
const token = localStorage.getItem('token');
if (token) {
headers.Authorization = `Bearer ${token}`;
}
try {
const res = await fetch(path, {
method: opts.method || 'GET',
body,
headers
});
if (res.ok) {
return await (opts.raw ? res.text() : res.json());
}
const err = await res.json();
throw new Error(err.message || err.statusText);
} catch (err) {
throw new Error(err);
}
async function loginWithRedirect(payload: {
username: string;
password: string;
}) {
const resp = await (await fetch(`${env.API_URL}/api/auth/login`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(payload),
credentials: "include",
})).json();
if (resp.error) {
dispatch({type: "ERROR", payload: resp.error.message});
} else {
dispatch({type: "LOGIN", payload: resp});
}
}
If response.ok is false you can throw an error then chain catch method after calling your function as follows
async function fetchData(){
const response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
if(!response.ok){
const message = `An error occured: ${response.status}`;
throw new Error(message);
}
const data = await response.json();
return data;
}
fetchData()
.catch(err => console.log(err.message));
I write promise function for using fetch in async await.
const promisyFetch = (url, options) =>
new Promise((resolve, reject) => {
fetch(url, options)
.then((response) => response.text())
.then((result) => resolve(result))
.catch((error) => reject(error));
});
By the way i can use it easly in async with try catch
const foo = async()=>{
try {
const result = await promisyFetch('url' requestOptions)
console.log(result)
} catch (error) {
console.log(error)
}
}
It was simple example, you could customize promisyFetch function and request options as you wish.
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
axios
.post("/charge/pay", data)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err.response.data);
});