0

my scenario is:

"axios": "^0.26.1",
"vue": "^3.2.25",
"vue-router": "^4.0.14"

I use axios interceptor for two main things:

  • Add a header, and
  • refresh token logic.

before add the code of the axios interceptor, the router.push("/") or router.push({name:"Home"}) worked fine but now they are ignored.

I have read the same issue in other threats, but I have not seen solutions/workaround for continue using router.push outside of the interceptor code.

I hope that you can help me with the next two things:

  • how can I debug in deeper for check the logs inside vue router?
  • if I use axios interceptor, can I continue using router.push command, how?

thanks & regards,

the code:

Axios interceptor

    const setup = (authStore = useAuthStore()) => {
        http.interceptors.request.use(
            (config: AxiosRequestConfig) => {
                const token: string = authStore.getAccessToken
                if (token) {
                    config.headers.Authorization = 'Bearer ' + token
                }
                return config
            },
            (error) => {
                Promise.reject(error)
            }
        ),
        http.interceptors.response.use(
            (res: AxiosResponse) => {
                return res
            },
           async (err:AxiosError) => {
                const originalConfig = err.config
                if (originalConfig.url !== 'auth/login' && err.response) {
                    // access-token expired
                    if (err.response.status === 401 && !originalConfig._retry) {
                        originalConfig._retry = true
                        try {
                           const rs = await http.post('auth/refreshtoken/', { token: authStore.getRefreshToken })
                           const { accessToken } = rs.data
                           authStore.setAccessToken(accessToken)
                           return http(originalConfig)
                        } catch (_error) {
                           return Promise.reject(_error)
                        }
                    }
                }
                return Promise.reject(err)
            }
        )
    }
        
    export default setup

Auth service

    import http from "../utils/http-common"
    
    class AuthService{
        login(data: FormData): Promise<any> {
            return http.post("auth/login/", data, {headers: { "Content-Type": "multipart/form-data" }, timeout: 3000})
        }
    
        me(): Promise<any> {
            return http.get("auth/me/")
        }
    }
    
    export default new AuthService

Vue component

    const login = async () => {
        const formData = new FormData()
        loading.value = true
    
        formData.append("username", credentials.username)
        formData.append("password", credentials.password)
    
        await auth.login(formData)
        .then((res:AxiosResponse) => {
            authStore.setAuthenticated
            authStore.setAccessToken(res.data.access_token)
            authStore.setRefreshToken(res.data.refresh_token)
            router.push({ name: "Home" })
        })
        .catch((e:AxiosError) => {
            alert(e.response?.status + ' ' + e.response?.statusText)
        })
        .finally(() => loading.value = false)
CoDeC__
  • 93
  • 2
  • 9
  • Do you await your HTTP calls before calling `router.push`? More code would be quite welcome. – kissu Apr 26 '22 at 16:11
  • Yes as @kissu mentioned it would be great to have more code (maybe the interceptor and the usage of `router.push()`) – h0p3zZ Apr 26 '22 at 17:01
  • Hi, I have added the code in the question. thanks. – CoDeC__ Apr 26 '22 at 17:09
  • You should probably not mix and match `async/await` with `.then`. Give a read [to this](https://javascript.info/async-await) and use only `async/await`. Will be more readable and remove any possible errors like here, where you have both at the same time. – kissu Apr 26 '22 at 17:11

1 Answers1

0

This may maybe work in your case, didn't checked the whole possible issues

try {
  const response = await auth.login(formData)
  await authStore.setAuthenticated() // may not be needed if not an async Vuex action
  await authStore.setAccessToken(response.data.access_token) // same
  await authStore.setRefreshToken(response.data.refresh_token) // same
  await router.push({ name: "Home" }) // this one is always nice because it's actually async
} catch (e) {
  alert(e.response?.status + ' ' + e.response?.statusText)
}

PS: not sure about TS, I don't know how to use it (sorry).

kissu
  • 40,416
  • 14
  • 65
  • 133
  • thanks but not work. I am going to continue with your link. – CoDeC__ Apr 26 '22 at 19:43
  • @Alberto could you be more explicit on what is not working? – kissu Apr 26 '22 at 20:05
  • hi, finally the error was typo error, a parenthesis.. authStore.SetAuthenticated() instead of authStore.SetAuthenticated. thanks for all, you code is more clear and more elegant. – CoDeC__ Apr 26 '22 at 20:26