I need to send multiple requests to a server. But my headers are dynamic and depend on the result of the previous request.
I use fetch to send my request, which is asynchronous. for exemple:
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
function server_time() {fetch("myserver/time", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));}
console.log(server_time)
So In this example result is displayed to the console whenever I call FetchTime(). Ok, this is fine. But, this result in my specific application is the server time. I need then to insert it in another Header.
I also need to check the time before each request.
Right now I can't get the result out of my function FetchTime because it is asynchronous and the rest of my code will be executed before. I tried to use async/await. But still, end up with the same result.
Is there a way to execute the rest of my code only after the previous example or should I try with XMLHttpRequest which is synchronous?
Related
I am trying to send a POST xmlhttprequest for Basic Authentication request. The response is an auth token which i need to use. I am defining the username and password and also sending a body. But whenever i execute the below code through Javascript, it gives me a 401 error. But when i send a request through postman, it gives me the expected output. I even tried taking the code directly from postman but it still gives me a 401 error. Below is the code i am executing -
var jsonToSend = {
'grant_type':'client_credentials'
};
var client_id= 'usernameTest';
var secret_key= 'PasswordTest';
var token_url = 'urlTest';
let xhr2 = new XMLHttpRequest();
xhr2.open("POST",token_url);
//xhr2.setRequestHeader("Authorization","Basic "+btoa(client_id+":"+secret_key));
xhr2.setRequestHeader("Authorization","Basic "+(client_id+":"+secret_key));
xhr2.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//xhr2.send(jsonToSend);
/* xhr2.send(JSON.stringify({
'grant_type':'client_credentials'
}));*/
xhr2.send("grant_type=client_credentials");
I have tried sending the body in different formats (which i have commented out in the above code) but it gives me a 401 error everytime.
Below is the postman generated code -
var myHeaders = new Headers();
myHeaders.append("Authorization", "Basic btoa");
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("grant_type", "client_credentials");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("urlTest", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
The postman code also gives 401 error when i try to execute it in my Javascript file. But in postman, POST call works properly.
I am sorry i cannot give out the credentials and url. I feel this is an issue in the way i am sending the body (which is grant_type:client_credentials).
Below is the screenshot from postman.
Any help would be appreciated.
I'm trying to build a HTML, CSS, JS website and want to incorporate an API and use the response further in my website.
I've managed to make this API part work but I'm stuck with the final part.
What I've Achieved
Executing a JS function using FETCH that makes a POST Call with Auth Headers
Getting the response to show up inside my Chrome Developer Console.
What I'm trying to achieve
Use the Response (Web URL) that is being received by the POST API Call inside my
website as a variable. So when the user hits a button this response (URL) opens up in
a new tab.
In simple terms, I want the make use of the web url that shows up in the Chrome Console.
Here is the code I'm using
function initiateIDV(){
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "Basic xxxxxxxxxxxxx");
var raw = JSON.stringify({
"customerInternalReference": "Will's App",
},
"userReference": "test-app",
"tokenLifetime": "10m"
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://[hidden]/api/v1/accounts", requestOptions)
.then(response => response.json())
.then(result => console.log(result.web.href))
.catch(error => console.log('error', error));
}
View From the Chrome Console of a Successful Response
I think there are 2 things to check first before make sure the value show in the Console.
Network request. Check in the Network panel to see if the network request call successful? If it's not fix the url or the API. Learn inspect network request
Log the result. Log the result object first to see if it contains .web.href. If it's not, fix the API.
I create a working example from your code. Run it and you will see result. I changed the API url to a demo url
function initiateIDV(){
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "Basic xxxxxxxxxxxxx");
// changed body content
var raw = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
})
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
// changed url
fetch("https://jsonplaceholder.typicode.com/posts", requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
initiateIDV();
Let me paraphrase your question. You want to:
make a POST request to an API
handle the API response in your JavaScript code
open a new tab in the user's browser, at the URL contained in the API response
And you are stuck at step 3.
What you are trying to achieve at step 3 is an effect (aka a side effect) on the user's browser.
Also, a minor remark about the terminology you used:
So when the user hits a button this response (URL) opens up in a new tab.
In your example the response is not a URL. You are calling response.json(), so the API response is JSON.
You are already performing a side effect at step 3: console.log(). A lot of stuff is a side effect. Basically everything that changes some kind of state. Printing something in the browser's console, showing an alert dialog, adding/removing CSS classes, adding/removing/altering DOM elements, are all side effects.
The side effect you want to achieve here is to open a new tab in the user's browser. In JS you can do it using this code:
window.open("https://stackoverflow.com/", '_blank').focus()
The state in your scenario is the fact that the browser currently has N tabs open, and after window.open() will have N+1 tabs open. And not only that. Opening a tab in Chrome might spawn a new operating system process (before the relationship was 1 tab => 1 process, but nowadays I don't think so, see here).
Stuck in unable to pass headers parameter in fetch call, I tried many different codes snippets by using Stackoverflow as well as Postman code too.
Currently here's the code Snippet for calling GET request by using Fetch method in reactjs
var myHeaders = new Headers();
myHeaders.append("mode", "no-cors");
myHeaders.append("Authorization", "Bearer oauth 2 token");
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch("api url", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Hi everyone,
I'm calling simple calling GET api by using Fetch function, but request Header is unable to pass in the request. But the same request I'm calling from PostMan it's working.
Any idea where I'm doing wrong.
I am posting request to my backend server using fetch api in React js
const formData = new FormData();
formData.append("image", file);
formData.append("userId", currentUser.id);
formData.append("sliderNumber", sliderNumber);
const myHeaders = new Headers();
myHeaders.append("Content-Type", file.type);
myHeaders.append("Aceess-Control-Allow-Origin", "*");
fetch("http://localhost:4000/upload/slide-image", {
method: "POST",
headers: myHeaders,
mode: "no-cors",
body: formData
})
.then(response => response)
.then(data => console.log("Printing data: ", data));
};
In elixir backend
def upload(conn, params) do
# uploading code
#send response to the client with amazon s3 image url
send_resp(conn, 200, image_url)
end
but Response object from fetch api is empty
Response {
body: null
bodyUsed: false
headers: Headers {}
ok: false
redirected: false
status: 0
statusText: ""
type: "opaque"
url: ""
}
And it doesn't change when I respond with status code 400.
It seems like fetch api is not building Reponse object correctly in some point. Because I can find correct status code and response body in browser network tab. But Response object doesn't hold response from backend server.
Any idea?
If you are expecting a text response from your server, then on your first .then(.. you should do like:
fetch("http://localhost:4000/upload/slide-image", {
method: "POST",
headers: myHeaders,
mode: "no-cors",
body: formData
})
.then(response => response.text()) // <---
.then(data => console.log("Printing data: ", data));
fetch returns a Promise that resolves to a Response. When you use .text() at this stage, what you actually do is to take the Response stream, read it to completion and return a promise that will resolve with a text.
Aside from that, you also use mode: "no-cors" (as other users mentioned on their answers) that limits you in many ways. For example, even if you follow my instructions above, you will get an empty string, even if you are trying to return something from your server. And that will be because of this mode.
You can find more details about it here, under bullet no-cors.
Your Content-Type is wrong. When sending files along with other data, the Content-Type should still be multipart/form-data.
mode: "no-cors",
You set the mode to no-cors, so the response is Opaque, which means you can't see inside it.
Don't do that if you need to read the response.
Asides:
myHeaders.append("Content-Type", file.type);
That's the wrong content-type for a form data object. Don't set the content-type. The fetch API will set the correct one automatically.
myHeaders.append("Aceess-Control-Allow-Origin", "*");
Access-Control-Allow-Origin, which you misspelt, is a response header, not a request header.
.then(response => response)
Returning the response unchanged is rather pointless. You probably want response.text() if you are getting a plain URL back.
The accepted answer solved my pinpoint.
if you are expecting a JSON object from the backend, use
.then((response) => response.json())
I'm making a POST request to a node.js server and I'm having trouble getting it to work. Here's my request:
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
};
export const postVote = (id, vote) =>
fetch(`${uri}/posts/${id}`, {
method: 'POST',
headers,
body: JSON.stringify({options: vote}),
}).then(response => response.json())
.then(data => data)
.catch(err => console.log(err));
The function accepts an 'id' and a 'vote', both strings. The id is being used as part of the URI in the request, and the vote is being supplied as options so the API knows what to do with it. Both of the arguments are being passed correctly:
id = '8xf0y6ziyjabvozdd253nd'
vote = 'upVote'
Here's a link to the GitHub repository for the server/API:
Udacity Readable API
and a screenshot of the network when firing the request:
UPDATE: Added the second screenshot which shows status 200. Though it shows this and appears to have been successful, it still doesn't post to the server and the information stays the same.
What you are looking at is the OPTIONS request in the network tab. For cross origin requests, every request if preceeded by an OPTIONS request which tells the calling client (browser, for example) if those HTTP methods are supported by the remote server for use in crosss origin context.
Check the other requests out. If the OPTIONS request was responded to correctly by the server, the browser must automatically follow up with your POST request
EDIT:
Also, the docs specify the param name to be option whereas in your screenshot it is coming up as options.
Further reading: CORS
Try declaring the headers as such:
var headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
})