Apollo-Client在响应中没有头信息。

3
我有一个GraphQL API和一个Vue.js前端,使用 Apollo客户端从后端请求数据。目前它运作良好。
服务器在每个响应头中回答一个新的JWT-Token,我需要它。因此,解决方案应该很简单...一个 afterware,它从每个响应中获取新的密钥并更新相应的存储条目。但是...头部是空的。
这是afterware:
apolloClient.networkInterface.useAfter([{
    applyAfterware({ response }, next) {
        if (process.env.NODE_ENV === 'development') {
            console.log('got new response', response);
        }
        if (response.status === 401) {
            store.commit('logout');
            store.commit('routeLogin');
        }
        next();
    }
}]);

这是响应的样子:

screenshot from devtools console.log

这实际上是发送的内容:

enter image description here

我有所遗漏吗?

更新

我在问题跟踪器中找到了一个类似的案例,通过添加Access-Control-Expose-Headers来解决。因此,我将它们添加到我的服务器配置中。现在响应看起来像这样,而apollo的headers对象仍然为空:

enter image description here

2个回答

0

你必须移除 {}。

来自:

applyAfterware({res}, next) {

到:

applyAfterware(res, next) {

现在您可以获取完整的头部信息。

apolloClient.networkInterface.useAfter([{
applyAfterware(res, next) {
        console.log("response:", res.options.headers);
        if (res.response.status === 401) {
            store.commit('logout');
            store.commit('routeLogin');
            // logout();
        }
        next();
    }
}]);

1
我在请求中发送的自定义头部可以在res.options.headers中看到。我认为@gordon-freeman正在寻找响应头... 我遇到了同样的问题... - James Moore
没错,我正在寻找响应头。 - Gordon Freeman

0

对于所有寻找获取响应头的方法的人,这里是我的最终解决方案:

import _ from 'lodash';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { ApolloLink, from } from 'apollo-link';
import { onError } from 'apollo-link-error';
import { InMemoryCache } from 'apollo-cache-inmemory';
// import { parse } from 'graphql'

import Auth from '@/store/api/system/auth';
import store from '@/store';

const ENDPOINT = `${process.env.VUE_APP_API_ENDPOINT}${process.env.VUE_APP_API_GRAPHQL_ROUTE}`;
const defaultHttpLink = new HttpLink({ uri: `${ENDPOINT}default` });
const adminHttpLink = new HttpLink({ uri: `${ENDPOINT}admin` });

const authMiddleware = new ApolloLink((operation, forward) => {
    // add the authorization to the headers

    let authorization = null;
    if (Auth.getToken('mimic')) {
        authorization = `Bearer ${Auth.getToken('mimic')}`;
    } else if (Auth.getToken()) {
        authorization = `Bearer ${Auth.getToken()}`;
    }

    operation.setContext({
        headers: { authorization }
    });

    return forward(operation).map(response => {
        const context = operation.getContext();
        const {
            response: { headers }
        } = context;

        if (headers) {
            const token = headers.get('Authorization');

            if (token) {
                const jwt = token.split('Bearer');
                if (jwt.length) {
                    const token = _.compact(jwt)[0].trim();
                    // console.log('fresh token: ', token);
                    // refresh correct token
                    let name = 'token';
                    if (Auth.getToken('mimic')) name = 'mimic';
                    store.commit('auth/addTokenToState', { token, name });
                }
            }
        }
        return response;
    });
});

const networkErrorLink = onError(({ response, networkError, operation, forward }) => {
    if (networkError) {
        switch (networkError.statusCode) {
            case 503: {
                const message = _.get(networkError, 'result.message');
                store.commit('updateMaintenanceState', message || true);
                response.errors = null;
                break;
            }
            case 404:
                // TODO
                // wenn ein menü angefragt wird, das nicht da ist ...
                break;
            case 401:
            case 403:
            case 422:
                store.dispatch('auth/signout');
                break;
        }
    }

    return forward(operation);
});

export const defaultClient = new ApolloClient({
    link: from([networkErrorLink, defaultHttpLink]),
    cache: new InMemoryCache(),
    connectToDevTools: process.env.NODE_ENV === 'development'
});

export const adminClient = new ApolloClient({
    link: from([authMiddleware, networkErrorLink, adminHttpLink]),
    cache: new InMemoryCache(),
    connectToDevTools: process.env.NODE_ENV === 'development'
});

const apolloProvider = new VueApollo({
    clients: {
        default: defaultClient,
        admin: adminClient
    },
    defaultClient
});

Vue.use(VueApollo);

export default apolloProvider;

注意!您需要在服务器端公开要获取的标头。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接