Trouble Recovering Data From API with Async in React - javascript

I am trying to run an api in react and have the response returned as a variable. The api returns the title of a given webpage.
DETAILS
The api uses the following URL {with a website url appended to the end}
http://textance.herokuapp.com/title/
A manual submission of this URL http://textance.herokuapp.com/title/www.antstand.com/ will result in "Antstand the bamboo laptop stand" being displayed in the browser. I am trying to use this api to set variable in my app.
MY CURRENT CODE
async function titleAPI(props) {
const baseUrl = 'http://textance.herokuapp.com/title/'
const response = await fetch(baseUrl + props)
const data = await response
console.log('FUNCTION OUTPUT: ',data)
return data
}
titleAPI(myUrl).then(console.log)
On running the code my unexpected ouptut is below (I was expecting : "Antstand the bamboo laptop stand")
FUNCTION OUTPUT:
Response {type: "cors", url: "http://textance.herokuapp.com/title/www.antstand.com/", redirected: false, status: 200, ok: true, …}
type: "cors"
url: "http://textance.herokuapp.com/title/www.antstand.com/"
redirected: false
status: 200
ok: true
statusText: "OK"
headers: Headers {}
body: (...)
bodyUsed: false
__proto__: Response
I think Cors refers to a cross origin error.

body: (...) and type:'cors' means you are getting opaque response because of CORS. Either send 'Access-Control-Allow-Origin' to your origin ( or * for all origins ), or configure proxy on frontend to change origin header of all requests so that server could not receive it as CORS. axios has options to configure proxy. create-react-app also provides mechanism to configure proxy in development environment.

try this way it's display your expecting result
"Antstand the bamboo laptop stand" show
const titleAPI=async props =>{
const baseUrl = 'http://textance.herokuapp.com/title/'
const url = baseUrl + props
const response = await fetch(url,{
method:'GET',
mode:"cors",
credentials:"same-origin",
cache:"no-cache",
headers:{
"Content-Type":"application/json",
"Access-Control-Allow-Origin":"*",
},
redirect:"follow",
referrer:"no-referrer"
})
let data = await response.text()
return data
}
titleAPI('www.antstand.com/').then(data=>console.log(data))

Related

Fetch API call not fetching cookies in expo react native?

I'm trying to send a post request to the server but the response does not contain 'set-cookie' header but the cookie is visible in postman.
This is the code:
axios.defaults.withCredentials = true;
let config = {
method: 'post',
url: 'https://app.bhive.fund/v1/api/account/signin',
headers: {
'Content-Type': 'application/json',
},
data: form
}
const res = await axios(config)
console.log(res.status)
console.log('set-cookie: ');
console.log(res.headers['set-cookie']);
console.log(res.headers);
return res;
This is the screenshot of the log
This is the screenshot of postman
That's because of the res.headers can't be accessed like an object.
You have to use the get()-method specified in order to get the cookie.
Try this instead of accessing the value right away by specifying the index with the brackets:
console.log(res.headers.get("Set-Cookie"));

cross origin for amazon lambda function from localhost in gatsby site

I have the following code which works when I run it as a local serverless function with netlify dev, but I need it to run cross origin from a dev server to the hosted server function. I put the function in a aws lambda function but I am getting a cross origin blocked error on my https:dev.website.com, I thought I have the correct headers in the return object so not sure why I am getting a cross origin error.
Any help would be great
const sanityClient = require("#sanity/client");
const client = sanityClient({
projectId: "random-id",
dataset: "production",
useCdn: true,
});
exports.lambdaHandler = async (event, context) => {
var body = JSON.parse(event.body);
//console.log(body.price_id)
try {
const checkPriceId = async (test) => {
const query = `*[_type == "products" && price_id == "${body.price_id}"]`;
const documents = await client.fetch(query, {}); // this could throw
return documents.map((document) => document.sold);
};
var ok = checkPriceId().then((test) => {
return new Promise(function (resolve, reject) {
//console.log(test) // this will log the return value from line 7
console.log(test);
resolve(test);
});
});
var bools = await ok;
// prettier-ignore
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods':'GET, POST, OPTION',
},
body: JSON.stringify({
sold: bools,
}),
};
} catch (err) {
return { statusCode: 500, body: err.toString() };
}
};
This is my request to the function if that helps
var fetchUrl = https://random.executue-api.aws.com/prod/sold //not exact
var fetchData = async function () {
const response = await fetch(fetchUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
price_id: final,
}),
})
.then(res => {
return res.json()
})
.catch(error => console.log(error))
return response
}
Update:
I tried adding cors the way suggested in the answer below, but it failed seen below so I tried manually adding the method response seen after.
I still get a cross domain error. And I have changed the domain so it is now https as well. Really stuck here.
I was looking into this more, and it seems like before it does the actual post it does a cors check at the options method, so I added in the same access control headers, and deployed but did not work. Don't quite get this.
Your headers look ok to me. (note: If you mix HTTP and HTTPS you are most likely to get a mixed content error in the client). If it is ONLY a CORS issue that you are seeing in the console in the web browser, then you might not have configured the API Gateway correctly in AWS.
In AWS, go to API Gateway and you should see something like the below:
Make sure that you enable CORS and then redeploy.
UPDATE:
Just looking at a previous implementation of a lambda function I setup with AWS. The headers I declared were as follows:
headers: {
"Content-Type" : "application/json",
"Access-Control-Allow-Origin" : "*",
"Allow" : "GET, OPTIONS, POST",
"Access-Control-Allow-Methods" : "GET, OPTIONS, POST",
"Access-Control-Allow-Headers" : "*",
"Access-Control-Allow-Credentials" : true
}
Your headers look OK to me though. However, when you created the method in the API Gateway, did you select Use Proxy Lambda Integration? (see screenshot).
Your client side fetch request looks ok. For reference mine was:
const url = 'your url';
const options = {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
};
fetch(url, options).then(res => res.json());
Unrelated to this issue, but its not advisable to mix Async/Await with .then promise chaining. But this isn't the issue you are having. Just something to note.
Check the values from your Integration Response / try setting them manually for both OPTIONS and POST (and if that works, make sure you are passing through the response correctly from the lambda).
Your POST action should only require the Access-Control-Allow-Origin header. The other two (Access-Control-Allow-Methods, Access-Control-Allow-Headers) belong in the OPTION action. See this writeup, and note the full example exchange for a preflighted request (in grey): https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests

Sending JSON response in Flask "POST" Route

For reference, I've looked at these three questions:
Return JSON response from Flask view
Sending JSON and status code with a Flask response
Return a requests.Response object from Flask
As the title states, I am trying to return a JSON response from a flask post method.
The flask route is as follows:
#app.route('/login', methods=['POST'])
def login_route():
content = request.json
jwt = get_authorization(content['username'], content['password'])
return {'session-token': jwt} , 200
Where in my web application I would like to store the session-token in cookies (for now).
Currently on the web side I have the following code:
static postWithJSONResponse(url, body, onFetchComplete, onFetchFailure) {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
})
.then((data) => onFetchComplete(data))
.catch(error => onFetchFailure(error));
}
componentDidMount() {
NetworkUtils.postWithJSONResponse('/login', this.state.userObject,
(data) => {
console.log(data);
},
(error) => {
});
}
Where userObject consists of username and password attributes.
I've tried a few variations of my flask route given the previous searches listed above:
Variations based on this question
from flask import jsonify
#app.route('/login', post)
def login_route():
content = request.json
d = {}
d['session-token'] = get_authorization(content['username'], content['password'])
return jsonify(d)
This variation from the same post:
#app.route('/login', post)
def login_route():
content = request.json
jwt = get_authorization(content['username'], content['password'])
app.response_class(
response=json.dumps({'session-token': jwt}),
status=200,
mimetype='application/json'
)
And lastly this attempt in which it was recommended to try creating a new response object:
from flask import Flask, request, make_response
#app.route('/login', methods=['POST'])
def login_route():
content = request.json
jwt = get_authorization(content['username'], content['password'])
resp = make_response(json.dumps({'session-token': jwt}), 200)
resp.headers['Content-Type'] = 'application/json'
return resp
All 3 of these attempts return the following json response objects to my chrome console:
Response {type: "basic", url: "http://localhost:3000/login", redirected: false, status: 200, ok: true, …}
body: ReadableStream
locked: false
__proto__: ReadableStream
bodyUsed: false
headers: Headers
__proto__: Headers
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:3000/login"
__proto__: Response
As you can see, the response object doesn't contain a single entry for session-token. I'm really not sure what could be going wrong here and I'm not certain if the issue is with the flask route or the javascript anymore. Needless to say I could use some help and any recommendations would be appreciated. I am using Flask version 1.1.2.
The fetch API in Javascript is nice in the sense that it gives you options you're seeing when you log it like potentially accessing the body as stream (any day now TC 39...), but it's totally over-engineered for the 90% case. The magic incantation to remember is as follows:
New-fangled fancy-pantsed Javascript
// can only do this inside an async function
const resp = await fetch(someURL);
const jsonData = await resp.json();
// step 3, profit
(Very slightly) Old(er) school Javascript
fetch(someURL)
.then(resp => resp.json())
.then(jsonData => /* profit! */);
They are functionally equivalent. Use the newer one if you always wanted to sit at the cool kid's table at lunchtime in school. Use the other if you're a stodgy old curmudgeon like myself who complains about the kids these days with their cool tables and lunchtimes.

Using the fetch API to query an endpoint to get a json response and getting back an empty response error

Please forgive the long debug info and code. I figure its all relevant.
Im trying to query an api endpoint to get a ticket back. I query using postman and get the ticket response back as text that is shown in the headers tab. However, I want to use java script to get that ticket back and do other stuff with it. When i run the script, it logs an error to the console:
SyntaxError: Unexpected end of input
at FetchDemo.html:48
(anonymous) # FetchDemo.html:54
Promise.catch (async)
getTicket # FetchDemo.html:53
the response i get is this:
type: "opaque"
url: ""
redirected: false
status: 0
ok: false
statusText: ""
headers: Headers {}
body: (...)
bodyUsed: false
__proto__: Response
My code is below:
<script>
let URL = 'https://jsonplaceholder.typicode.com/posts/';
let TabURL = 'http://15.222.0.10/trusted/?username=admin';
document.getElementById("getTicket").addEventListener('click',getTicket);
function getTicket() {
console.log("in side getTicket");
//setup an options array to pass into the fetch call
let options = {
method: 'POST',
mode: 'no-cors',
headers: {
'Accept' : 'application-json,*/*',
'Content-Type' : 'application:json'
}
};
console.log(TabURL);
console.log(options);
fetch (TabURL,options)
.then(response => {
console.log(response);
return response.json();
})
.then(response => {
console.log(response);
})
.catch(error => {
console.error(error);
});
}
</script>
From the specs:
An opaque filtered response is a filtered response whose type is "opaque", URL list is the empty list, status is 0, status message is the empty byte sequence, header list is empty, and body is null.
The reason you're getting an opaque response, is because you use the no-cors flag. If you want to do cross-domain requests such as these, you need CORS.
https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
https://developer.mozilla.org/en-US/docs/Web/API/Response/type

coinmarketcap api integration - 401 error - JavaScript

I am trying to integrate coinmarketcap api but cannot really get the data. I registered, got the API key, and wrote the following method to fetch the data:
let getPostsList = async () => {
const options = {
method: 'GET',
headers: {
'X-CMC_PRO_API_KEY': 'api-key-goes-here'
},
mode: 'no-cors'
};
try {
const response = await fetch(`https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest`, options);
const json = await response.body;
// console.log(json)
return json
} catch (err) {
console.log('Error: ', err)
}
};
All I get is 401 error, like this:
GET https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest
401
Any suggestions what I should fix? Docs says that 401 is likely connected to API key, but they say to provide it in the headers like the above...
From what I've tested after getting my own API key, the no-cors mode is problematic. You will need to use CORS, where https://cors-anywhere.herokuapp.com/ comes into handy.
Just send the request like this :
const options = {
method: 'GET',
headers: {
'X-CMC_PRO_API_KEY': 'api-key-goes-here'
},
};
try {
const response = await fetch(`https://cors-anywhere.herokuapp.com/https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest`, options);

Categories

Resources