如何正确设置 GET/POST 获取的标头以避免 CORS

Posted

技术标签:

【中文标题】如何正确设置 GET/POST 获取的标头以避免 CORS【英文标题】:How do I properly set headers for GET/POST fetch to avoid CORS 【发布时间】:2018-03-31 11:33:05 【问题描述】:

我的目标是在 React-app 中将突变发布到 graphQL API。这样做时我遇到了一个错误:POST http://urlhere/graphiql 405 (Method Not Allowed) 我发送数据的功能:

getRating = (e, id) => 
        e.preventDefault();
        let value = 2;
            const uri = '//hereIputAddress/graphiql';
    
            const query = `
            mutation
                rating(group_id: 3, product_id: $product_id, value: $value, name: $name, phone: $phone, email: $email, content:$content) 
                product_id,
                value,
                
            
            `;

            const variables = 
                product_id: id,
                value: value,
                name: "wq",
                phone: "601654654",
                email: "goto@gmail.com",
                content: "some content"
            ;

            const apolloFetch = createApolloFetch( uri );
            
            apolloFetch.use(( request, options , next) => 
                if (!options.headers) 
                options.headers = ;
                console.log(options.headers);
                
            
                next();
            );
            
            apolloFetch( query, variables ).then(res =>

            );
        
    

经过一番搜索,我意识到可能是缺少标题,所以我将代码更改为:

getRating = (e, id) => 
        e.preventDefault();
        let value = 2;
            const uri = '//hereIputAddress/graphiql';
    
            const query = `
            mutation
                rating(group_id: 3, product_id: $product_id, value: $value, name: $name, phone: $phone, email: $email, content:$content) 
                product_id,
                value,
                
            
            `;

            const variables = 
                product_id: id,
                value: value,
                name: "wq",
                phone: "601654654",
                email: "goto@gmail.com",
                content: "some content"
            ;

            const apolloFetch = createApolloFetch( uri );
            
            apolloFetch.use(( request, options , next) => 
                if (!options.headers) 
                options.headers = ;
                console.log(options.headers);
                

                options.headers['Access-Control-Allow-Credentials'] = 'true';
                options.headers['Access-Control-Allow-Origin'] = 'http://localhost:3000';
                options.headers['Access-Control-Max-Age:1728000`'] = '1728000'; 
                options.headers['authorization'] = 'created token';
            
                next();
            );
            
            apolloFetch( query, variables ).then(res =>

            );
        
    

现在我有错误:Failed to execute 'fetch' on 'Window': Invalid name

我对获取数据完全陌生,所以我完全不知道发生了什么。值得注意的是,当我尝试使用 GET 从该服务器获取数据时,我得到了响应:No 'Access-Control-Allow-Origin' header is present on the requested resource。我通过将 Allow-Cors-Allow-Origin 插件下载到 chrome 来“解决”这个问题,但这似乎不是最好的解决方案。我的功能是:

const url = 'http://188.116.11.87/graphql?query=%23%20Welcome%20to%20GraphiQL%0A%23%0A%23%20GraphiQL%20is%20an%20in-browser%20IDE%20for%20writing%2C%20validating%2C%20and%0A%23%20testing%20GraphQL%20queries.%0A%23%0A%23%20Type%20queries%20into%20this%20side%20of%20the%20screen%2C%20and%20you%20will%0A%23%20see%20intelligent%20typeaheads%20aware%20of%20the%20current%20GraphQL%20type%20schema%20and%0A%23%20live%20syntax%20and%20validation%20errors%20highlighted%20within%20the%20text.%0A%23%0A%23%20To%20bring%20up%20the%20auto-complete%20at%20any%20point%2C%20just%20press%20Ctrl-Space.%0A%23%0A%23%20Press%20the%20run%20button%20above%2C%20or%20Cmd-Enter%20to%20execute%20the%20query%2C%20and%20the%20result%0A%23%20will%20appear%20in%20the%20pane%20to%20the%20right.%0A%0A%0Aquery%7B%0A%20%20product%7B%0A%20%20%20%20id%0A%20%20%20%20name%0A%20%20%20%20description%0A%20%20%20%20keywords%0A%20%20%20%20is_published%0A%20%20%20%20author%0A%20%20%20%20attributes%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%20%20basket%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%20%20post%20%7B%0A%20%20%20%20id%0A%20%20%20%20publication_date%0A%20%20%7D%0A%20%23%20last_comments(data%3A%226%22)%0A%20%20%0A%7D%0A%0A'
    return fetch(url).then(function(response)
    console.log(response);
      return response.json();
    ).then((data) =>//doing stuff with data here

这是我在控制台中找到的: https://s1.postimg.org/2e35egfbbj/Zrzut_ekranu_2017-10-18_o_21.12.33.png

---编辑--- 我尝试以这种方式添加标题:

const headers = new Headers()
    headers.append('Access-Control-Allow-Origin', 'http://localhost:3000')
    headers.append('Access-Control-Allow-Credentials', 'true')
    headers.append('Content-Type','application/json');
    //headers.append('Content-Type','text/plain;charset=UTF-8');

    const url = 'http://myurl/graphql?
    const fetchInit = 
      method: 'GET',
      headers: headers,
      mode: 'cors',
      cache: 'default'
    


    return fetch(url, fetchInit)
    .then(function(response)
      return response.json();
    ).then((data) => ...stuff here

但是我有错误:Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

但是,如果我将 no-cors 模式添加到 fetchInit,我会在包含以下内容的行中得到错误 Unexpected end of inputreturn response.json();

【问题讨论】:

【参考方案1】:

尝试在服务器端设置 cors 选项和 Access-Control-Allow-Origin 标头。

const graphQLServer = express();
const corsOptions = 
  origin(origin, callback) 
    callback(null, true);
  ,
  credentials: true
;
graphQLServer.use(cors(corsOptions));
var allowCrossDomain = function(req, res, next) 
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();

graphQLServer.use(allowCrossDomain);

这可能对你有帮助

【讨论】:

【参考方案2】:

您在请求中设置标头,而您应该在服务器上这样做。使用 npm 中的 cors 包来设置 cors 响应选项。

【讨论】:

以上是关于如何正确设置 GET/POST 获取的标头以避免 CORS的主要内容,如果未能解决你的问题,请参考以下文章

如何在apigility中正确设置子路线?

如何从标头中正确获取 jwt 令牌并将其与 express 一起使用

我应该如何配置我的标头以对 APNs 进行 HTTP/2 POST 以避免“收到重复的伪标头字段”错误?

如何避免“超出 GET/POST 参数数量”错误?

设置 Rails 应用程序以避免使用 CORS

如何正确配置服务器和浏览器以避免cors错误?获取 API + Node.js