how to us external api in react - javascript

I have created react app using the npm module 'create-react-app'
I wanted to use external API for say api.example.com but was unable to call the external API because axios is requesting localhost rather than external API.
I tried the following Code:
class Example extends Component{
static defaultProps={
'url':"api.example.com"
}
handleChange(event){
axios.get(this.props.url+event.target.value)
.then(result=> console.log(result.data)
}
}
}
How to allow react app to access external API?

For example, POST request for added some Product in database:
In example I use JWT authentification for access at API.
JSON.stringify not necessary use, because Axios already implement this feature, here it is used for greater understanding. Don't use this on production!
const jwtToken = 'd70414362252a41ceger5re435gdgd45hjk';
const data = JSON.stringify({
id: '5',
title: 'product'
price: '15000',
description: 'string',
});
const configAxios = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer + ${jwtToken}`,
},
};
axios.post('https://api.somesite.com/products', data, configAxios)
.then((res) => {
this.date.description = res.data;
console.log(res);
})
.catch((err) => {
console.warn('error during http call', err);
});
It's also important to note that we strictly write the JWT token in the code, although it must be received periodically, this is not realized in this example.

Related

Firebase cloud functions return api token to consume in axios

I have an axios instance that I use to fetch data:
const getQualtrics = axios.create({
baseURL: 'https://xx1.qualtrics.com/API/v3/',
headers: {
'Content-Type': 'application/json',
'X-API-TOKEN': import.meta.env.VITE_API_TOKEN,
},
});
Currently I'm getting the api token from vite's .env file.
I want to deploy the app so instead, I want a secure cloud function to return the api token. I created one:
exports.getAPI = functions.https.onCall((data, context) => {
return {
apiToken: process.env.API_TOKEN,
};
});
In this, I'm using .env inside the functions folder (not vite's .env).
The question is, how do I add this to the axios instance above?
I tried:
const getAPI = httpsCallable(functions, 'getAPI');
let getQualtrics;
getAPI().then(result => {
getQualtrics = axios.create({
baseURL: 'https://xx1.qualtrics.com/API/v3/',
headers: {
'Content-Type': 'application/json',
'X-API-TOKEN': result.apiToken,
},
});
});
It didn't work. I feel I'm doing something obviously wrong here. Any advice?
Is there a better way of storing 3rd party API tokens in firebase to consume in front-end?

Why post call made using fetch in my react app fails when the same is successfully executed in postman?

I am making a post API call using fetch in my react app (redux-thunk) and getting a '401-Unauthorized' error. but, I made the same post request in postman with the same Authorization token and it returned a successful response.
While trying multiple fixes, I found that I am able to post requests successfully using the npm request library in a standalone node application. Hence, I assume that I am missing something while making the call using fetch in react application. Unfortunately, I cannot use the request library in my react application as it is deprecated and throwing unwanted errors.
Can someone please help me fix this issue? I added my code below:
export const addTodoAsync = createAsyncThunk(
"todos/addTodoAsync",
let token = '22e745f508990f40c97feccf5cf3397f7fbe0ae96f6b7baf051fccbcbb8267df';
async (payload) => {
const response = await fetch('https://gorest.co.in/public/v1/todos', {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
body: {user_id: '6000', title: 'wakeup', status: 'pending', due_on: '2022-07-22T10:40:36.630Z+10:40'}
});
if (response.ok) {
let todo = await (response.json()).data;
return { todo };
}
}
);
change :
body: {user_id: '6000', title: 'wakeup', status: 'pending', due_on: '2022-07-22T10:40:36.630Z+10:40'}
to :
body: JSON.stringify({user_id: '6000', title: 'wakeup', status: 'pending', due_on: '2022-07-22T10:40:36.630Z+10:40'})

Auth0 React Native patch user by Management API

I want to patch the user_metadata of a user in my Auth0 Authentication in react native but I get the following error:
{"error": "Unauthorized", "message": "Missing authentication", "statusCode": 401}
So I am importing Auth0 in my react native:
import Auth0 from "react-native-auth0";
const auth0 = new Auth0({
domain: Config.AUTH0_DOMAIN,
clientId: Config.AUTH0_CLIENT_ID
});
I use the constants Config.AUTH0_DOMAIN and Config.AUTH0_CLIENT_ID from my dashboard from my application.
As a next step I execute the following code:
login = () => {
auth0.webAuth
.authorize({
scope: Config.AUTHO_SCOPE,
audience: Config.AUTH0_AUDIENCE,
device: DeviceInfo.getUniqueID(),
prompt: "login"
})
.then(res => {
auth0.auth
.userInfo({token: res.accessToken})
.then(data => {
fetch(`https://<MY_AUTH_DOMAIN>/api/v2/users/${encodeURIComponent(data.sub)}`, {
method: "PATCH",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"metadata": {first_name: 'John', last_name: 'Doe', skillLevel: 'PRO!'}
})
}).then(res => res.json())
.then(async (data) => {
try {
console.log('user stored', data);
} catch (e) {
console.log("error while user storing", e)
}
})
})
})
}
Whereby Config.AUTHO_SCOPE and Config.AUTH0_AUDIENCE is also from my auth0's app dashboard.
Am I missing some authentication in my headers or is the Management API the wrong choice? Do I need to to this query probably from my Back-End?
Resources:
Official API Doc from the Management API: https://auth0.com/docs/api/management/v2?_ga=2.147997749.368915485.1617866251-2089752765.1617460658#!/Users/patch_users_by_id
Official react-native-auth0 doc: https://auth0.github.io/react-native-auth0/src_management_users.js.html
Thanks for the help!
I was having this issue and I got it working after a little work.
First, I had to configure my project to give metadata write permission in Auth0's dashboard at Applications/Apis.
The two I added were read:current_user and update:current_user_metadata.
Then, in my authorize request, I modified both scope and audience.
audience: 'https://<MY APP DOMAIN>/api/v2/'
scope: 'read:current_user update:current_user_metadata openid profile offline_access'
Next, I got the userId by passing my authentication token to auth.userInfo like so.
auth0.auth.userInfo({token: authToken}).then((response)=>{
return response.sub;
})
Finally, I used the value returned from response.sub along with the authToken that I had setup with special audience and scope to patch the user, and it worked successfully. UserId is what response.sub returned.
auth0.users(authToken).patchUser({id: userId, metadata: newUserMetadata});
EDIT:
One other issue I see with your code snippet, if you want to use fetch, is you didn't put a bearer authorization token in the header. Your fetch response will probably return with a 401 error if that's the case. The code should look something like this:
const serverResponse = await fetch('https://<MYAPP>.auth0.com/api/v2/users/' + user.sub,{
headers:{
Authorization: 'Bearer ' + accessToken
}
})

When using aws amplify on react to make an call to api gateway, how do i go about getting the statuscode as well?

My API gateway (using serverless) is setup to respond correctly:
function buildResponse(statusCode, body) {
// console.log(body);
return {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true
},
body: JSON.stringify(body)
};
}
After deploying the backend to aws, I have client side using React.js with aws amplify, where I make the call:
return API.post("api", "/api");
The problem
I get the token from the api call correctly, but I don't get the status code. How can I build out the api so that I can get the status code as well from API gateway?
Take a look at this from aws amplify docs under "get" for example. If you include the "response" in myInit, you will be able to get the entire axios object including the statuscode.
let apiName = 'MyApiName';
let path = '/path';
let myInit = { // OPTIONAL
headers: {}, // OPTIONAL
response: true, // OPTIONAL (return the entire Axios response object instead of only response.data)
queryStringParameters: { // OPTIONAL
name: 'param'
}
}
API.get(apiName, path, myInit).then(response => {
// Add your code here
}).catch(error => {
console.log(error.response)
});

how do I make a post and get request with ReactJS, Axios and Mailchimp?

I am new to ReactJS and I am trying to build this app that need to use mailchimp so the user can subscribe for newsletter. I need to make a request using axios? can someone guide me through this? where do i put my api key? Did I do it correct in the bellow code? i put my mailchimps username in 'username' and my apikey in 'xxxxxxxxxxxxxxxxxxx-us16', however, i got the 401 error saying Unauthorized, BUT my console did say Fetch Complete: POST and caught no error.
import React, {Component} from 'react';
import './Subscribe.css';
class Subscribe extends Component {
sub = () => {
let authenticationString = btoa('username:xxxxxxxxxxxxxxxxxxx-us16');
authenticationString = "Basic " + authenticationString;
fetch('https://us16.api.mailchimp.com/3.0/lists/xxxxxxxxx/members', {
mode: 'no-cors',
method: 'POST',
headers: {
'Authorization': authenticationString,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email_address: "somedude#gmail.com",
status: "subscribed",
})
}).then(function(e){
console.log('complete')
}).catch(function(e){
console.log("fetch error");
})
};
render () {
return(
<div>
<button onClick={this.sub}> subscribe </button>
</div>
);
};
};
In the documentation, the curl example uses the --user flag. Using this to convert curl commands to an equivalent js code, you need the 'auth' property on the option object of the fetch to make it work.
fetch('https://us16.api.mailchimp.com/3.0/lists/xxxxxxxxx/members', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
email_address: "somedude#gmail.com",
status: "subscribed",
},
auth: {
'user': 'username',
'pass': 'xxxxxxxxxxxxxxxxxxx-us16'
})
})
It took me a while to get the syntax right for this. This is an example of a working request using nodejs in a server-side-rendered reactjs app using axios.
It appears "get" requests won't work for this method because of the 401 error: MailChimp does not support client-side implementation of our API using CORS requests due to the potential security risk of exposing account API keys.
However, patch, put, and post seem to work fine.
Example (using async / await)
// Mailchimp List ID
let mcListId = "xxxxxxxx";
// My Mailchimp API Key
let API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxx-us12";
// Mailchimp identifies users by the md5 has of the lowercase of their email address (for updates / put / patch)
let mailchimpEmailId = md5(values["unsubscribe-email-address"].toLowerCase());
var postData = {
email_address: "somedude#gmail.com",
status: "subscribed"
};
// Configure headers
let axiosConfig = {
headers: {
'authorization': "Basic " + Buffer.from('randomstring:' + API_KEY).toString('base64'),
'Accept': 'application/json',
'Content-Type': 'application/json'
}
};
try {
let mcResponse = await axios.post('https://us12.api.mailchimp.com/3.0/lists/' + mcListId + '/members', postData, axiosConfig)
console.log("Mailchimp List Response: ", mcResponse);
} catch(err) {
console.log("Mailchimp Error: ", err);
console.log("Mailchimp Error: ", err["response"]["data"]);
}
You can using the method described there: AJAX Mailchimp signup form integration
You will need to use JSONP otherwise you will get a CORS error.
If you use a modern environment (I mean not jQuery), you can achieve this method using a library like qs or queryString to transform your form data to an uri.
Your final url could look something like:
jsonp(`YOURMAILCHIMP.us10.list-manage.com/subscribe/post-json?u=YOURMAILCHIMPU&${queryString.stringify(formData)}`, { param: 'c' }, (err, data) => {
console.log(err);
console.log(data);
});
It's a bit hacky and I guess Mailchimp can remove this from one day to the other as it's not documented, so if you can avoid it, you'd better do.

Categories