【问题标题】:apollo-client has no headers in responseapollo-client 没有响应的标头
【发布时间】:2018-02-25 16:59:09
【问题描述】:

我有一个带有 apollo client 的 graphql api 和一个 vue.js 前端,用于从后端请求数据。到目前为止它运行良好。

服务器在我需要的每个响应标头中都使用新的 JWT-Token 进行回答。所以解决方案应该很简单.. 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();
    }
}]);

下面是响应的样子:

以下是实际发送的内容:

我错过了什么吗?

更新

我找到了一个similar case in the issue tracker,已通​​过添加Access-Control-Expose-Headers 解决。所以我将它们添加到我的服务器配置中。现在响应看起来像这样,而 apollos headers 对象仍然是空的:

【问题讨论】:

    标签: javascript vue.js graphql apollo apollo-client


    【解决方案1】:

    您必须删除 {}。

    来自:

    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();
        }
    }]);
    

    【讨论】:

    • 我在res.options.headers 的请求中看到了我发送的自定义标头。我认为@gordon-freeman 正在寻找响应标头...我看到了同样的问题..
    • 没错。我正在寻找响应标头
    【解决方案2】:

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

    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;
    

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

    【讨论】:

      猜你喜欢
      • 2018-05-06
      • 2019-12-22
      • 2018-07-17
      • 2018-02-14
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 2023-04-10
      • 2021-09-28
      相关资源
      最近更新 更多