【问题标题】:apollo-client does not work with CORSapollo-client 不适用于 CORS
【发布时间】:2018-07-26 21:06:16
【问题描述】:

我正在 AWS Lambda 上编写一个 graphql 服务器组件(不使用 graphql-server)。在客户端,我使用的是 apollo-client。关于我正在设置的 lambda 函数的响应

const response = {
    statusCode: 200,
    headers: {
        "Access-Control-Allow-Origin": "*" // Required for CORS support to work
    },
    body: JSON.stringify({
        result: 'mock data',
        input: event,
    }),
};
callback(null, response);

在客户端使用 ApolloClient 我收到以下错误

对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'http://localhost:8080'。

但是,当我使用 axios 之类的东西执行相同的请求时,它可以正常工作。此外,当我通过邮递员之类的方式执行请求时,我看到响应中启用了“Access-Control-Allow-Origin”设置。这是 apollo-client 的已知问题吗?我该如何解决?

【问题讨论】:

  • 不,这很可能是您不知道 preflight 请求是什么的问题...对于什么 HTTP 方法确实指定了您显示的响应?

标签: lambda cors apollo-client


【解决方案1】:

首先,我们正在做的错误是 从“apollo-boost”导入 ApolloClient。实际上我们必须从 'apollo-client' 导入 ApolloClient

import ApolloClient from 'apollo-client';

因为,来自 apollo-boostApolloClient 仅支持较小的配置选项子集。 apollo-client 中的 ApolloClient 为您提供所有配置选项。

那么我们可以只为 Apollo-client 实例提供 linkcache

import { InMemoryCache } from "apollo-cache-inmemory";
import { createHttpLink } from 'apollo-link-http';

const client = new ApolloClient({ 
    link: new createHttpLink(
        {
            uri: "Your QraphQL Link"
        }
    ),
    cache: new InMemoryCache(),
});

【讨论】:

    【解决方案2】:

    这是一个工作示例。服务器必须启用 CORS。这意味着您的 http 请求的来源

    来源:https://example.com

    必须与您的请求的响应的 access-control-allow-origin 标头相匹配。

    访问控制允许来源:https://example.com

    然后在 Angular 客户端上你可以使用这个模块:

    import {NgModule} from '@angular/core';
    import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular';
    import {HttpLinkModule, HttpLink} from 'apollo-angular-link-http';
    import {InMemoryCache} from 'apollo-cache-inmemory';
    import {environment} from 'src/environments/environment';
    import {errorLink} from './dm-core/graphql/apollo-link-error';
    import {concat} from 'apollo-link';
    
    export function createApollo(httpLink: HttpLink) {
        return {
            link: concat(errorLink, httpLink.create({uri: environment.graphql, withCredentials: true})),
            cache: new InMemoryCache(),
            defaultOptions: {
                watchQuery: {
                    errorPolicy: 'all'
                }
            }
        };
    }
    
    @NgModule({
        exports: [ApolloModule, HttpLinkModule],
        providers: [
            {
                provide: APOLLO_OPTIONS,
                useFactory: createApollo,
                deps: [HttpLink]
            }
        ]
    })
    export class GraphQLModule {}
    

    注意“withCredentials: true”:

        link: concat(errorLink, httpLink.create({uri: environment.graphql, withCredentials: true})),
    

    【讨论】:

    • 如何将来源从 example.com 更改为其他任何内容?
    • 源由客户端发送到服务器。服务器只是在 origin 标头中接收它,并在 access-control-allow-origin 标头中将其回显给客户端。
    【解决方案3】:

    要解决 Apollo 的 CORS 问题,您必须将 no-cors 选项传递给底层 fetch

    import ApolloClient from "apollo-boost";
    
    const client = new ApolloClient({
      uri: "your client uri goes here",
      fetchOptions: {
        mode: 'no-cors',
      },
    });
    

    这不是特定的 Apollo 问题,而是要在 fetch 方面解决的配置,有关更多信息,请参阅:https://developers.google.com/web/ilt/pwa/working-with-the-fetch-api#cross-origin_requests

    我想知道为什么它确实适用于您的 Axios,我希望您在某处设置了 no-cors 模式。

    【讨论】:

    • 我使用了 mode: no-cors ,它默默地停止了我的 http 标头。值得一提的是,作为使用 no-cors 的副作用
    • 此选项在 apollo 3.0 中不可用
    • 如果我添加 mode:'no-cors' 我收到响应代码为 500 的服务器端错误,我不知道如何解决它
    【解决方案4】:

    我假设您使用的是 AWS API Gateway。

    您的一个问题是:您是否为网关启用了 CORS? See how

    我相信这应该可以解决您的问题,如果您还发送 cookie,您也可以设置 "Access-Control-Allow-Credentials" : true 标头。 `

    【讨论】:

    • 我也在 API 网关中启用了 CORS。另外,当我从同一个客户端应用程序到同一个端点执行一个简单的 Axios 命令时,它工作正常。就在我尝试通过 apollo-client 时它失败了。
    猜你喜欢
    • 2019-11-27
    • 1970-01-01
    • 2018-05-29
    • 2013-01-19
    • 2017-07-12
    • 2015-07-09
    • 2021-01-15
    • 2019-08-13
    相关资源
    最近更新 更多