0

I constantly get 401 unauthorized server error for my post request. It is trivial post request to write item in database. I do't know how AsyncStorage work in details, but i read it is like local storage. I know it is unencrypted, asynchronous, persistent, key-value storage system.

It is react-native app, with redux and saga and axios like http client, backend is laravel. In saga response, when user is logged in, i get

token = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9wb3Bpcy5taWxzLm1lXC9hcGlcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNTc1NjE1OTg5LCJleHAiOjE1NzU2MTk1ODksIm5iZiI6MTU3NTYxNTk4OSwianRpIjoiMlBRaWVMUjdQT0h4VnZyMCIsInN1YiI6MSwicHJ2IjoiODdlMGFmMWVmOWZkMTU4MTJmZGVjOTcxNTNhMTRlMGIwNDc1NDZhYSJ9.dBYL8H9TVaXxEZgIZB56sbYSHp530D--Lni4klv9SRg

But in api.js when I want to do post request to write item in datebase my token is:

 Promise {
  "_40": 0,
  "_55": null,
  "_65": 0,
  "_72": null,
}

My code is Api.js:

import axios from 'axios'
import deviceStorage from './services/deviceStorage';

var config = {
    headers: {'Authorization': "bearer " + deviceStorage.loadToken()}
};

export function addProduct_api(item) {
    return axios.post('http://popis.mils.me/api/popis',item, config)
}

my Saga is:

export function* addProduct(action) {
    const response = yield call(addProduct_api, action.payload)
    if(!response || !response.data) {
        return yield put(addProduct_failure('Internal server error'))
    }
    if(response.status === 200) {
        return yield put(addProduct_success(response.data))
    } else {
        return yield put(addProduct_failure('Error for login user'))
    }
}

export function* loginUser(action) {
    const response = yield call(login_api, action.payload)
    if(!response || !response.data) {
        return yield put(login_failure('Internal server error for login user'))
    }
    if(response.status === 200) {
        deviceStorage.saveItem('token', response.data.token)
        return yield put(login_success(response.data))
    } else {
        return yield put(login_failure('Error for login user'))
    }
}

and my service deviceStorage.js is:

import { AsyncStorage } from 'react-native';

const deviceStorage =  {
    async saveItem(key, value) {
        try {
            await AsyncStorage.setItem(key, value)
        } catch (error) {

        }
    },

    async loadToken() {
        try {
            const token = AsyncStorage.getItem('token')
            console.log('token in service--------------------------------', token);
            return token
        } catch (error) {
            console.log('Load token error: ', error);
        }
        return token
    }
}
export default deviceStorage
octobus
  • 1,246
  • 1
  • 14
  • 20
Qli
  • 179
  • 2
  • 4
  • 19

2 Answers2

1

AsyncStorage returns a Promise. That's why you are getting a promise object in your backend.

You should use await when you are getting item in AsyncStorage, just like you did when you are setting it.

async loadToken() {
        try {
            const token = await AsyncStorage.getItem('token')
            console.log('token in service--------------------------------', token);
            return token
        } catch (error) {
            console.log('Load token error: ', error);
        }
        return token
    }

Also since loadToken function is also async. You should use it in your addProduct_api like this:

export function addProduct_api(item) {
var token = await deviceStorage.loadToken();
var config = {
    headers: {'Authorization': "bearer " + token}
};
    return axios.post('http://popis.mils.me/api/popis',item, config)
}
octobus
  • 1,246
  • 1
  • 14
  • 20
  • ok, tnx a lot. I changed code like you write. Now, token in deviceStorage is ok, but in Api.js i had a same promise token??? – Qli Dec 06 '19 at 08:55
  • What is the result of the `console.log` in your `loadToken` function? – octobus Dec 06 '19 at 09:02
  • token in service-------------------------------- eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9wb3Bpcy5taWxzLm1lXC9hcGlcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNTc1NjIzMDMyLCJleHAiOjE1NzU2MjY2MzIsIm5iZiI6MTU3NTYyMzAzMiwianRpIjoibWlKSWJrcXZOUlU3bVlsMSIsInN1YiI6MSwicHJ2IjoiODdlMGFmMWVmOWZkMTU4MTJmZGVjOTcxNTNhMTRlMGIwNDc1NDZhYSJ9.il6Y05aMpLd6db9Cas9H6J6IRs9Rf0vizgDbWrcT5vg – Qli Dec 06 '19 at 09:05
  • in servise is ok, but in api isn't. I do't why. Api's tokenTOKEN in api++++++++++: Promise { "_40": 0, "_55": null, "_65": 0, "_72": null, } – Qli Dec 06 '19 at 09:07
  • Can you also `console log` your `config` in your `addProduct_api`. – octobus Dec 06 '19 at 09:16
  • Can you try setting your config in your `addProduct_api` function. like this: `export function addProduct_api(item) {var config = { headers: {'Authorization': "bearer " + deviceStorage.loadToken()} }; return axios.post('http://popis.mils.me/api/popis',item, config) }` – octobus Dec 06 '19 at 09:19
  • config in api+++++++++: Object { "headers": Object { "Authorization": "bearer [object Object]", }, } – Qli Dec 06 '19 at 09:33
  • Ok then, it seems that your `deviceStorage.loadToken()` returns an object. Make sure cast to a string, before you make a string adding operation. – octobus Dec 06 '19 at 09:36
  • I tried everything..with JSON.stringify(token) returns samo thing like promise, but in string type :( – Qli Dec 06 '19 at 09:50
  • Hmm, when you `console.log(deviceStorage.loadToken())` directly in your `addProduct_api`. Is the result an object, if so which property does that object has? – octobus Dec 06 '19 at 09:53
  • config in api: Object { "headers": Object { "Authorization": "bearer [object Object]", }, } – Qli Dec 06 '19 at 10:07
  • this is console.log for config in function addProduct_api – Qli Dec 06 '19 at 10:07
  • Ok. Whan i meant was, can you `console.log(deviceStorage.loadToken())` directly in the `addProduct_api` function. If the result is an `object` what properties does that `object` have? – octobus Dec 06 '19 at 10:09
  • loadToken() in api: Promise { "_40": 0, "_55": null, "_65": 0, "_72": null, } – Qli Dec 06 '19 at 10:14
  • Ok. This is my stupidy. Your loadToken() function is also async and async functions also returns promises. See https://stackoverflow.com/questions/35302431/async-await-implicitly-returns-promise . I will update my answer. @Qli – octobus Dec 06 '19 at 10:20
  • ok, i read it. What is your suggestion for solving my problem? – Qli Dec 06 '19 at 10:37
0

First, add the await in the loadToken function

async loadToken() {
    try {
        const token = await AsyncStorage.getItem('token')
        console.log('token in service--------------------------------', token);
        return token
    } catch (error) {
        console.log('Load token error: ', error);
    }
    return token
}

Then update the addProduct_api function like

export async function addProduct_api(item) {
var config = {
        headers: {'Authorization': "bearer " + await deviceStorage.loadToken()}
    };
    return axios.post('http://popis.mils.me/api/popis',item, config)
}
Zeeshan Ansari
  • 9,657
  • 3
  • 26
  • 27