Make synchronous post request from react to flask to get dict - javascript

Context:
I'm building a app that can plot graph structures in electron with react. My backend is some Matlab code that can perform analysis on the graph struct. I'm using flask as the middle man communicating between them.
In the GUI i have a button that should be able to load the data that is provided in a excel file to the GUI. This should be done by a post request that uses a matlab script to load the data from the excel file and then returns this to javascript.
I have tried using something like this:
fetch('http://localhost:5000/getGriddata', {
method : 'POST',
headers : {
'Content-Type' : 'application/json'
},
body : JSON.stringify(fileObj.path)
}).then(response => response.json())
.then(data => setGriddata(data))
.catch(error => console.log(error));
The problem is that this code won't wait for the flask function to be finished. The flask function takes about 10 seconds depending on the graph size. Therefor i want to make this call in sync with my javascript code so that after the request, i can assure that the new griddata is defined.
Question:
Is there some way to ensure this when using fetch?
Do i need to find a different way of connecting to flask, if so what would that be?

Solution:
Instead of using the fetch api, another post brought me to the XMLHttpRequest. This works synchronously if the parameter is set to false.
With this my code looks like this:
var request = new XMLHttpRequest();
request.open("POST",'http://localhost:5000/getGriddata',false);
request.setRequestHeader('content-type', 'application/json');
request.send(JSON.stringify(fileObj.path));
console.log(request.response)
console.log(request.responseText)
setGriddata(JSON.parse(request.responseText))

Instead of using callbacks, try using async/await
const fetchGridData = async () => {
try {
const response = await fetch('http://localhost:5000/getGriddata', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(fileObj.path)
});
const result = await response.json();
setGriddata(result)
} catch(error) {
console.error("fetchGridData =>", error)
}
}

Related

Method changes on fetch depending on where it is called from on Svelte

For context, I am using go-gonic for my Backend and Svelte for my Frontend.
The Backend I don't believe is the issue here, it works correctly with tests and an alternate cli Frontend in python, along with working in a rest client. I have narrowed down the issue to the Svelte component, and the async function inside of it.
Summary: When I try to call a fetch with method POST from the on:click handler in Svelte it switches the method to OPTIONS, but when I call the fetch with method POST in the main body of the component when it first loads, the method stays as POST. (The method changes only when called from on:click)
I am writing a component that calls an endpoint from the Backend
as soon as it is loaded (GET)
when a button is click (POST)
For the first (GET), I call my API inside an OnMount like so (this works)
onMount(async () => {
await fetch(`http://127.0.0.1:1357/api/v1/col/`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Basic " + btoa("Admin:stackoverflow<3"),
},
})
.then((r) => r.json())
.then((data) => {
cols = JSON.parse(data["message"]);
});
});
But for the second one (POST), I want to call a fetch when a button is clicked.
Here is how I am doing that. This was the recommended way to call a function on click in svelte (the arrow syntax is there because I want to include parameters, but those are excluded for simplicity.)
<input
class="flat submit"
type="submit"
value="+"
on:click={async () => newStep()}
/>
Here is the definition of newStep.
async function newStep() {
let formData = new FormData();
formData.append("name", "NAME");
formData.append("desc", "DESC");
formData.append("collection", selected);
await fetch(`http://127.0.0.1:1357/api/v1/step/`, {
method: "POST",
headers: {
Authorization: "Basic " + btoa("Admin:stackoverflow<3"),
},
body: formData,
})
.then((r) => r.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
}
When the submit button is clicked, is attempts to make a fetch that is registered in the Backend, except the method is OPTIONS and not POST.
Here might be a hint. This code works as expect (POST is made) when the body of function is run at the start of the code like so. To clarify, the body of the function runs as expected when it is not in a function, but when run as the component is loaded. The code only breaks (Makes request of method OPTIONS) when it is run inside a async function. I also tested with a non async function. The problem for some reason happens whenever I wrap this code in a function and then try to call it on click. When the fetch changes method to OPTIONS, it will put this in the console. TypeError: NetworkError when attempting to fetch resource.
<script>
let formData = new FormData();
formData.append("name", "NAME");
formData.append("desc", "DESC");
formData.append("collection", selected);
await fetch(`http://127.0.0.1:1357/api/v1/step/`, {
method: "POST",
headers: {
Authorization: "Basic " + btoa("Admin:stackoverflow<3"),
},
body: formData,
})
.then((r) => r.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
</script>
I think I am following all of the recommended ways to do this, but I may have missed something, if there is a good library, similar to react-query to help alleviate issues like this involving async and fetch, that would help as well. My main goal is to call a fetch with method POST when a button is clicked and if there are betters ways to do this, that would help.
p.s. I use a better method for auth than in these examples.
Thanks in advance.
(edit): Add info from console.

How to make an axios post request that is structured like a form post request?

I am having some problems with trying to customize some code for Next-Auth, an authentication library for.Next.Js.
I want to be able to use Axios to manually make the post request rather than using a <form> element.
When I do the following, I have success.
<form method='POST' action='/api/auth/signout'>
<input name='csrfToken' value={csrfToken}/>
<button type='submit'>Submit</button>
</form>
But, when I try to do the same thing with axios, it doesn't work. I am attempting to call Next-auth's Signout endpoint, which I can do just fine using this html form element. I am expecting that the application with log the user out when calling this endpoint. When I do so with the form input, then it logs the user out. When calling the same endpoint with axios, it does not log the user out and instead nothing is happening
My axios request is
const submitForm = async () => {
if (csrfToken) {
const params = new URLSearchParams();
params.append("csrfToken", csrfToken);
try {
const response = await axios({
method: "POST",
url: "http://localhost:3000/api/auth/signout",
data: params,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}).then((res) => console.log(res));
} catch (err) {
console.log(err);
}
}
};
I have tried adding additional headers that I saw on the request that works properly, like:
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-User": "?1"
I have tried making it multipart form data, passing it simply a body of {csrfToken}, and anything else I could think of.
Any tips or things that I might be overlooking?
I can't figure out why I am unable to make this work. I am using ANTD, rather than using regular html <form> elements throughout the application and would love to be able to use that additional functionality.
Edited:
I found the solution after a lot of headache. It turns out that everything was functioning as it should have previously, but Next-Auth has an issue with updating the client-side 'session' object when you make a manual change on the server side.
I fixed this by doing the following:
const res = await axios.post("/api/auth/signout", { csrfToken }).then(
async ({ request: { responseURL } }) =>
await router
.push(responseURL)
//this is from https://github.com/nextauthjs/next-auth/issues/596#issuecomment-943453568
//force the client side to refresh and revalidate since it doesn't want to do so on its own.
.then(() => document.dispatchEvent(new Event("visibilitychange")))
.catch((err) =>
console.log("err refreshing client side session ", err)
)
);
The trick that i was missing was the document.dispatchEvent(new Event('visibilitychange'). This is the magical piece that allows you to force the client side next-auth session to sync with cookies/db.
see here for more info https://github.com/nextauthjs/next-auth/issues/596#issuecomment-943453568

Javascript Fetch API equivalent in Java for Http requests?

I am currently learning about Threads in Java. I wanted to know what the standard protocol would be when making Http Requests in Java that would be similar to the code I have below, which uses Javascript Fetch API and asynchronous programming. For example, if I was using the Fetch API in Javascript to first make a GET request to grab some data from a REST endpoint that I would later use to make a POST request (as seen in the code below), I would need to use a Callback function or Promise (like below) to wait until that first request has retrieved its data for the second request to then proceed. Obviously, if I did not use Promises or nest the second Http POST in the first Fetch method (GET) below, and wrote two separate Fetch API calls (one for GET, one for POST, sequentially one after other aka top-to-bottom), both calls would "fire-off" simultaneously and the second POST request wouldn't have the data it needs to make a successful POST.
const myHttpGETandPOSTmethod = () => {
// First Http request goes here
fetch('http://example.com/movies.json', {
method: 'GET',
headers: // Some headers here,
})
.then(response => response.json())
.then(data => {
console.log(data))
// Nest the second Http request inside here. It only runs after 1st request completes
return fetch('http://example.com/movies.json', {
method: 'POST',
headers: // Some headers here,
body: JSON.stringify(body);
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
})
}
So then, if I were using something like the Apache HttpClient https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html library in Java, would the standard procedure be to "spin-up" another Thread (besides the main thread) to execute the GET request and then do a thread.join() such that after the first thread completes, then the second request can fire-off its own Thread?
Would I need to use a Callable instead of Runnable so that I can save the HttpEntity data response of the first GET request?
I guess I'm just trying to understand the best way to implement the scenario I posed above regarding an HTTP GET request that is needed to make a subsequent POST request, while both fires asynchronously such that they do not block the main thread.
You can make a basic GET request using the apache Http Library as such (POST is also very similar):
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://targethost/homepage");
CloseableHttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
// Save the response body to a string
String body = EntityUtils.toString(entity1, StandardCharsets.UTF_8);
System.out.println(body);
EntityUtils.consume(entity1);
} finally {
response1.close();
}
Or am I on the wrong approach here and looking at this incorrectly? I believe the Http library in Apache offers both synchronous and asynchronous Http calls? or should I be using a newer library for Http in Java?

When to set the headers explicitly when making HTTP request in NodeJS application

So I was having a look at a codebase of a NodeJS application and there were some specific functions making HTTP requests to the backend. To be exact, those functions were making a GET request to the backend and one thing that I found confusing was that in some of the functions, the headers were mentioned explicitly whereas, in some other functions who were making the GET request, there was no mention of headers (i.e. headers were not being set explicitly). Below is an example:
In the code below, the function is making a GET request and there's no mention of headers (i.e. the headers are not being set explicitly):
// Method for fetching a single post from the backend on the basis of the post ID
export const singlePost = (postID) => {
return fetch(http://localhost:8080/post/${postID}, {
method: "GET",
})
.then((response) => {
return response.json();
})
.catch((error) => {
console.log(error);
});
};
In the code below, the function is making a GET request and the headers are being set explicitly:
// Helper Method for making the call to the backend and fetching all their details of all the posts
export const list = (page) => {
return fetch(http://localhost:8080/posts/?page=${page}, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
})
.then((response) => {
return response.json();
})
.catch((error) => console.log(error));
};
Now coming to the main question, could someone please explain to me when are we supposed to set the headers explicitly not only in just GET request but in other general HTTP requests as well (i.e. POST, PUT, OPTION etc).
It would be really great if some could refer a source or explain this concept here. Thanks!
HTTP request header is the information, in the form of a text record, that a user's browser sends to a Web server containing the details of what the browser wants and will accept back from the server. The request header also contains the type, version and capabilities of the browser that is making the request so that server returns compatible data.
Check this https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039

Post request to JSON server through FETCH api refreshes the page

I am trying to send POST requests through fetch API to JSON-server. Function is called on a simple button click (type 'button', not 'submit'). When I replace POST request with GET request everything works like it supposed to, but with POST I have a problem. Request passes, on the JSON-server entity gets created but keeps refreshing the page after each request. Also, I don't have a response from JSON-server, google chrome says 'Failed to load response data'.
Where I'm making a mistake?
const comment = {
text: "test comment",
article_id: 3
};
console.log(JSON.stringify(comment));
const options = {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(comment)
}
fetch(`${URL_COMMENTS}`, options)
.then(response => { return response.json() })
.then(data => {
console.log(data)
});
If you use Live Server extension, try disabling that and try again.
Check out for Json sever port number running on your machine
attach the html form code
So we can try it on oru local machine to reproduce the issue.... Which help us to resolve the issue easy

Categories