apollo-client 没有响应的标头

Posted

技术标签:

【中文标题】apollo-client 没有响应的标头【英文标题】:apollo-client has no headers in response 【发布时间】: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 对象仍然是空的:

【问题讨论】:

【参考方案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: `$ENDPOINTdefault` );
const adminHttpLink = new HttpLink( uri: `$ENDPOINTadmin` );

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;

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

【讨论】:

以上是关于apollo-client 没有响应的标头的主要内容,如果未能解决你的问题,请参考以下文章

AWS API Gateway 429 响应 - 没有 CORS 标头

HAR 响应中没有标头

响应没有“内容长度”标头时的 AVURLAsset

没有将 Cors 标头添加到响应中

被 CORS 策略阻止:对预检的响应...没有 HTTP ok 状态。标头没有解决问题

为啥我的“Set-Cookie”响应标头没有被翻译成实际的 cookie?