I want to set token in authorization header but the token is set null. I tried to get the token from chrome storage but token is not set though i get the token from the storage when i console the result['user_token'] inside the callback.
here is the code
var token = null; // i need this token in fetchTopics as well
function fetchCurrentUser() {
const apiUrl = `api2.navihq.com/get_current_user`;
chrome.storage.sync.get(['user_token'], function(result) {
token = result['user_token'];
});
console.log('token', token); // getting null
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', `Token: ${token}`)
fetch(apiUrl, {
method: 'GET',
headers
})
.then(function(response) {
console.log('response', response);
return response.json()
})
.then(function(data) {
console.log('data', data);
return JSON.parse(atob(data.user))
})
}
$(window).bind('load', function() {
document.addEventListener('click', init);
fetchCurrentUser();
fetchTopics();
});
How do i now set the token in authorization header?
The sync in chrome.storage.sync.get doesn't mean it's synchronous
the fact it takes a callback shows it is Asynchronous - not that taking a callback guarantees something is asynchronous of course, but in this case it's clear that it is
So put the fetch inside the callback
function fetchCurrentUser() {
const apiUrl = `api2.navihq.com/get_current_user`;
chrome.storage.sync.get(['user_token'], function(result) {
var token = result['user_token'];
console.log('token', token); // getting null
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', `Token: ${token}`)
fetch(apiUrl, {
method: 'GET',
headers
}).then(function(response) {
console.log('response', response);
return response.json()
}).then(function(data) {
console.log('data', data);
return JSON.parse(atob(data.user))
})
});
}
Alternatively you can "promisify" the chrome.storage.sync.get function
function fetchCurrentUser() {
const chromeStorageGetPromise = key =>
new Promise(resolve => chrome.storage.sync.get(key, resolve));
const apiUrl = `api2.navihq.com/get_current_user`;
chromeStorageGetPromise(['user_token'])
.then(({user_token: token}) => {
console.log('token', token);
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', `Token: ${token}`);
return fetch(apiUrl, {
method: 'GET',
headers
});
}).then(response => {
console.log('response', response);
return response.json();
}).then(data => {
console.log('data', data);
return JSON.parse(atob(data.user));
})
}
Related
I'm trying to fetch data from the server, and I want to try to resolve the response body as json, if failed return it as plain text
fetch(`/devapi/${url}`, {
method: 'GET',
headers: new Headers({
Authorization: `Bearer ${localStorage.getItem("token")}`,
}),
})
.then((res) =>
res
.json()
.then((res) => res?.body?.data || res?.body || res)
.catch((err) => res.text())
)
.then((val) => console.log(val));
when the response is NOT a valid json, ten res.text() is called, but it seems that calling .text() after .json causes an error
Failed to execute 'text' on 'Response': body stream already read
You could clone the response, and then use it in error handler:
Try this:
fetch(`/devapi/${url}`, {
method: 'GET',
headers: new Headers({
Authorization: `Bearer ${localStorage.getItem("token")}`,
}),
})
.then((res) => {
const clone = res.clone();
return res
.json()
.then((res) => res?.body?.data || res?.body || res)
.catch((err) => clone.text())
})
.then((val) => console.log(val));
or use XHR and process response in a try/catch:
const xhr = new XMLHttpRequest();
xhr.open('POST', `/devapi/${url}`, true);
xhr.setRequestHeader('Authorization', `Bearer ${localStorage.getItem("token")}`);
xhr.onload = function() {
let res;
try {
res = JSON.parse(xhr.response);
} catch (err) {
res = xhr.responseText;
}
console.log(res);
};
xhr.send();
I am trying to send html table inside append of FormData object using fetch request.
Code is Correct for these
let formData = new FormData();
formData.append('sponsor', "My sponsor");
formData.append('rider', "xRider");
But When trying to send an html in it Fetch request fails
formData.append('delegation', "<b>Bold Text</b>");
My complete request
fetch(request_url, {
method: 'POST',
processData: false,
contentType: false,
body: formData
})
.then(response => {
if (response.ok) return response.json();
})
.then(response => {
let response_status = response['status'] == 'success' ? 'success' : 'failed';
// In case of OK, this sendResponse will be called
Console.log("Working correctly")
})
.catch(error => {
// In case of error, this sendResponse will be called
call_back_function({
status: "failed",
data: error
});
console.log('%c View Visa Details Catch Error: ', 'background: #000; color: #bada55', error)
});
So this is an example from an actual project I am making. I don't see all of your code, so I can't see you request, or headers. But try something like this! or post all of your code so we can properly see everything.
export const NewPost = async(endpoint, body) =>
{
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const options = {
method:'POST',
body: JSON.stringify(body),
headers:headers,
};
const request = new Request(endpoint, options);
const response = await fetch(request).then((response) =>
{
if(response.ok)
return response.json();
throw new Error(`Response not received. Status: ${response.status}`);
})
.then((json) =>
{
console.log(`POST Request successful.`);
return json;
})
.catch(error => console.log(error));
return response;
};
I want to use axios in api test. To initialize client I need first to set auth token, which I expect to get with axios as well.How to get it form async code?
const a = require('axios');
getToken = () => {
var axios =a.create({
baseURL: 'http://local.v2.app.com/api/auth/v1.0',
headers: {'Content-Type': 'application/json'},
});
return axios.post('/credentials/login', {
username: '1#test.com',
password: 'Test#1234'
})
.then(function (response) {
return response.data.data.token;
})
.catch(function (error) {
console.log(error);
});
}
const client=a.create({
baseURL: 'http://local.v2.app.com/api/auth/v1.0',
headers: {
'Content-Type': 'application/json',
'Authorization': getToken()
},
});
module.exports = client;
First, getToken should be async (or just return promise):
async getToken() {
var axios = a.create({
baseURL: 'http://local.v2.app.com/api/auth/v1.0',
headers: {'Content-Type': 'application/json'},
});
try {
const response = await axios.post('/credentials/login', {
username: '1#test.com',
password: 'Test#1234'
})
return response.data.data.token;
} catch (error) {
console.error(error);
}
}
Then you can mock request:
const client = a.create({
baseURL: 'http://local.v2.app.com/api/auth/v1.0',
headers: {
'Content-Type': 'application/json'
}
})
const request = client.request
const addToken = (token) => (data, headers) => {
headers.Authorization = token
return data
}
client.request = (config = {}) => new Promise(async (resolve, reject) => {
token = await getToken()
if (!config.transformRequest) config.transformRequest = []
config.transformRequest.push(addToken(token))
request(config).then(resolve, reject)
})
module.exports = client
Yes, bit messy, feel free to refactor!
axios has request function which makes requests, others like get, post are aliases. This code patches request to get token first and then continue request.
transformRequest is took from axious readme on github, there is a comment "You may modify the headers object" so it is legal.
P.S good question, don't know why -1
I'm learning nodejs and trying to make an API call. The API uses JWT to authenticate.
I created these functions to sign a token:
function token() {
const payload = {
iat: Math.floor(new Date() / 1000),
exp: Math.floor(new Date() / 1000) + 30,
sub: "api_key_jwt",
iss: "external",
jti: crypto.randomBytes(6).toString("hex")
};
return new Promise((resolve, reject) => {
jwt.sign(payload, privatekey, { algorithm: "RS256" }, function(
err,
token2
) {
if (err) reject(err);
else resolve(token2);
});
});
}
exports.genToken = async function() {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: await token()
};
async function authorization(req, res) {
try {
const auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
res.send(auth.body);
} catch (error) {
res.send(404).send();
}
}
return {
"x-api-key": api,
Authorization: "Bearer " + authorization()
};
};
This works fine. Then I created a function to make the API call:
const token = require("./index").genToken;
const rp = require("request-promise");
exports.getOrderBook = function(res, error) {
const full_url = url + "order_book";
const auth = token();
rp({
url: full_url,
method: "GET",
headers: auth,
body: {
market: "btceur"
},
json: true
})
.then(function(response) {
res(response);
})
.catch(function(err) {
error(err);
});
};
And I call it using Express:
routes.get("/orderbook", async (req, res, next) => {
try {
const book = await orders.getOrderBook();
res.send(book);
} catch (error) {
next(error);
}
});
However, when I call my API, it shows an error in console:
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of
type string or Buffer. Received type object.
I guess the error is something with the token generation, because if I console.log(auth) in the getOrderBook function, it shows Promise { <pending> }, so probably an object is being passed as the jwt token.
Is it really the problem? I tried a lot of different solutions that I found on internet, however the concept of Async/Await is new to me, and I'm having some troubles to figure it out.
Thanks a lot in advance guys!
Since getToken is an anync function, the return is wrapped in a Promise as well so you would need another anync/await:
exports.getOrderBook = async function() {
let response;
try {
const full_url = url + "order_book";
const auth = await token();
response = await rp({
url: full_url,
method: "GET",
headers: auth,
body: {
market: "btceur"
},
json: true
});
} catch (e) {
// handle error
throw e
// or console.error(e)
}
return response;
};
In this line as well Authorization: "Bearer " + authorization(), authorization is returning a promise
const bearer = await authorization()
return {
"x-api-key": api,
Authorization: "Bearer " + bearer
};
For error handling wrap entire thing in try..catch block
exports.genToken = async function() {
try {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: await token()
};
async function authorization(req, res) {
let auth;
try {
auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
// res object not available
// res.send(auth.body);
} catch (error) {
// res object not available, better throw error and handle in your middleware
// res.send(404).send();
}
return auth
}
const bearer = await authorization()
} catch (e) {
// handle error
}
return {
"x-api-key": api,
Authorization: "Bearer " + bearer
};
}
I've encountered problems trying to resolve an http.post request before doing some other code.
Here's the place:
getRefresh(token){
debugger;
console.log("sono dentro get refresh");
console.log(token);
let params = new URLSearchParams();
params.append('grant_type','refresh_token');
params.append('refresh_token',token);
params.append('client_id','web_app');
let headers = new Headers({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8','Authorization': 'Basic '+btoa("web_app:")});
let options = new RequestOptions({headers: headers});
this._http.post('http://localhost:9997/oauth/token',params.toString(),options)
.map(res => res.json())
.subscribe(
data => this.saveToken(data),
err => alert('Invalid Credentials')
);
}
Following the control flow via Browser Console, I've noticed that saveToken method is not executed asap.
The fact is that I need that method for registering some cookies, reused here:
if (!Cookie.get("access_token")) {
this.getRefresh(Cookie.get("refresh_token"));
cookie = Cookie.get("access_token");
} else {
cookie = Cookie.get("access_token");
}
var headers = new Headers({
'Content-type': 'application/x-www-form-urlencoded; charset=utf-8',
'Authorization': 'Bearer ' + cookie
});
var options = new RequestOptions({headers: headers});
return this._http.get(resourceUrl, options)
.map((res: Response) => res.text())
.catch((error: any) => Observable.throw(error().json().error || 'Server error'));
How can I resolve the async problem of observable?
Change your getRefresh(token) method to return the observable and use that in your calling code:
function getRefresh(token) {
debugger;
console.log("sono dentro get refresh");
console.log(token);
let params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('refresh_token', token);
params.append('client_id', 'web_app');
let headers = new Headers({ 'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Basic ' + btoa("web_app:") });
let options = new RequestOptions({ headers: headers });
return this._http.post('http://localhost:9997/oauth/token', params.toString(), options)
.map(res => res.json())
.flatMap(
data => this.saveToken(data),
err => alert('Invalid Credentials')
);
}
function getResource() {
var cookie = Cookie.get("access_token");
var headers = new Headers({
'Content-type': 'application/x-www-form-urlencoded; charset=utf-8',
'Authorization': 'Bearer ' + cookie
});
var options = new RequestOptions({ headers: headers });
return this._http.get(resourceUrl, options)
.map((res: Response) => res.text())
.catch((error: any) => Observable.throw(error().json().error || 'Server error'));
}
function callingCodeFunction() {
if (!Cookie.get("access_token")) {
this.getRefresh(Cookie.get("refresh_token"))
.flatMap((result) => {
getResource();
});
} else {
getResource()
}
}
*I've not run this code - so there may be errors, but it should serve to demonstrate the principle.