获取补丁请求不被允许。

65

我有两个应用程序,一个是React前端,第二个是Rails-API应用程序。

我一直很愉快地使用isomorphic-fetch,但当我需要向服务器发送PATCH方法时,出现了问题。

我得到了以下错误信息:

Fetch API cannot load http://localhost:3000/api/v1/tasks. Method patch is not allowed by Access-Control-Allow-Methods in preflight response.

但服务器返回的OPTIONS响应中包含一个“PATCH”方法在Access-Control-Allow-Methods列表中:

输入图片描述

这是fetch如何实现的:

const API_URL = 'http://localhost:3000/'                                            
const API_PATH = 'api/v1/'

fetch(API_URL + API_PATH + 'tasks', {
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  method: 'patch',                                                              
  body: JSON.stringify( { task: task } )                                        
})

POST、GET和DELETE的设置基本相同,并且它们都可以正常工作。

这里有什么问题吗?

更新:

方法patch是大小写敏感的:

https://github.com/github/fetch/blob/master/fetch.js#L200

我不确定这是否是预期行为或错误。

更新2:

这是预期行为,方法类型PATCH需要区分大小写。 将fetch方法的代码行更新为:

method: 'PATCH'

修复了这个问题。

https://github.com/github/fetch/issues/254


1
看起来isomorphic-fetch可能存在一个bug,因为如果我将方法名更改为POST,则请求将正常工作,但对于post、get、delete等方法名不区分大小写。 - Kocur4d
1
顺便提一下,对于 OPTIONS 请求的响应中允许使用的方法的标头是 Allow:。您的响应正在使用不同的标头 (Access-Control-Allow-Methods:)。 - drhining
1
不过,我认为你应该将其添加为答案,因为它是解决你的问题的方法。 - silvenon
7
把“patch”改成大写的“PATCH”就解决了问题。需要内置枚举时它们在哪里呢?:) 感谢您发布更新。 - James Perih
2
和@JamesPerih一样...将'patch'替换为'PATCH'解决了这个"问题" :/ - errata
显示剩余5条评论
3个回答

6

我在使用Rack::Cors时,遇到了reactJS前端和rails API非常相似的问题,将patch添加到允许的方法列表中解决了我的问题。

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource '*', headers: :any, methods: [:get, :post, :patch, :options]
  end
end

这个解决方案帮助我在PHP页面中修复了我的Javascript fetch问题。我添加了我的解决方案。 - Noitidart
这将禁用GET、POST、PATCH、OPTIONS请求的CORS令牌检查,使您的应用程序容易受到攻击... 相反,您应该在请求头中传递cors_token。 - cyc115

2

当使用全大写的 PATCH 时,我遇到了这个错误。同时我也在使用 DELETEPUT 时遇到了同样的错误。我检查了我的 fetch 请求头,发现有一个 OPTIONS 方法。我在这里使用的是 isomorphic-fetch 库 - https://www.npmjs.com/package/isomorphic-fetch

对我来说,解决方法是在我的 PHP 页面中添加以下内容:

<?php
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH');

如果没有这个,Firefox 53中我将一直收到JavaScript错误:

尝试提取资源时出现NetworkError。

我所做的获取是这样的:

try {
    await fetch('https://my.site.com/', {
        method: 'PATCH',
        headers: { 'Content-Type':'application/x-www-form-urlencoded' },
        body: 'id=12&day=1'
    });
} catch(ex) {
    console.error('ex:', ex);
}

1
使用这段代码:_method: 'PATCH'
return (
        fetch(API_ROOT + route, {
            _method: 'PATCH',
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            },
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json',
                'Authorization': ''
            },
            data: JSON.stringify(data),
            credentials: 'include'
        })
        .then(res => res.json())
        .then(res => {
            return res
        })
        .catch(err => console.error(err))
    );

另一种方法是在标题中插入方法。
headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
            '_method': 'PATCH',
            'Authorization': ''
        }

它帮助你。
return (
        fetch(API_ROOT + route, {
            method: 'POST',
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            },
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json',
                '_method': 'PATCH',
                'Authorization': ''
            },
            data: JSON.stringify(data)
        })
        .then(res => res.json())
        .then(res => {
            console.log(res);
            return res
        })
        .catch(err => console.error(err))
    );

这对于NGINX(反向代理)也适用。它解决了我的“在PATCH请求期间出现API 400 Bad Request”的问题。完美! - YetAnotherDuck
fetch(API_ROOT + route, {_method: 'PATCH'} has error it should be fetch(API_ROOT + route, {method: 'PATCH'} - Raskul

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