XMLHttpRequest 无法加载资源

Posted

技术标签:

【中文标题】XMLHttpRequest 无法加载资源【英文标题】:XMLHttpRequest cannot load resource 【发布时间】:2017-05-02 21:29:05 【问题描述】:

我正在尝试制作一个简单的 php 后端来处理另一台服务器中的联系表单,但是尽管添加了正确的标头,它仍然给我同样的错误消息:

XMLHttpRequest cannot load https://php-contact-form-lual.herokuapp.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4000' is therefore not allowed access. The response had HTTP status code 404.

这是ajax请求:

$.ajax(
    type: 'POST',
    url: 'https://php-contact-form-lual.herokuapp.com/',
    data: 
            subject: 'subject',
            to: 'receiver',
            name: $('#name').val(),
            email: $('#email').val(),
            msg: $('#msg').val()
            
    ) // then the callbacks

这是php:

<?php

    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
  // return only the headers and not the content
  // only allow CORS if we're doing a POST - i.e. no saving for now.
  if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') 
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: X-Requested-With');
  
  exit;


// handling the data    
$subject = $_POST['subject'];
$to      = $_POST['to'];
$name    = $_POST['name'];
$email   = $_POST['email'];
$msg     = $_POST['msg'];
$msg     = "DE: " . $name . " (" . $email .")" . "\n\n" . $msg;

mail($to, $subject, $msg);

?>

请注意,“处理数据”块之前的代码行取自 this answer,我还尝试使用相同答案的第一部分中提供的更简单的解决方案 - 在其他地方也找到 - 甚至替换带有特定 URL 的星号,但结果是相同的 :(

任何帮助将不胜感激:)

更新:我在服务器端尝试过的事情的日志(从最旧到当前):

// Allow from any origin
if (isset($_SERVER['HTTP_ORIGIN'])) 
    header("Access-Control-Allow-Origin: $_SERVER['HTTP_ORIGIN']");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day


// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']");

    exit(0);


------------------------------------------

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, OPTIONS");

-----------------------------------------

header("Access-Control-Allow-Origin: http://localhost:4000");
header("Access-Control-Allow-Methods: POST, OPTIONS");

-----------------------------------------

header("Access-Control-Allow-Origin: http://localhost:4000");
header("Access-Control-Allow-Methods: POST, OPTIONS, GET");

-----------------------------------------

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') 
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers');
    
    exit;


------------------------------------------

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') 
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers');
    
    exit;


// + sending headers though ajax

------------------------------------------

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers');

-------------------------------------------

# created .htaccess file with this line:
Header set Access-Control-Allow-Origin "*" 

------------------------------------------

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS, GET');
header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers');

---------------------------------------------

header('Access-Control-Allow-Origin: http://localhost:4000');
header('Access-Control-Allow-Methods: POST, OPTIONS, GET');
header('Access-Control-Allow-Headers: X-Requested-With, content-type, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers');

-----------------------------------------------

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
  // return only the headers and not the content
  // only allow CORS if we're doing a POST - i.e. no saving for now.
  if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') 
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: X-Requested-With');
  
  exit;


--------------------------------------------------

header('Origin: http://localhost:4000');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');

附加信息

请求标头

POST / HTTP/1.1
Host: php-contact-form-lual.herokuapp.com
Connection: keep-alive
Content-Length: 88
Accept: */*
Origin: http://localhost:4000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:4000/contacto/
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en-GB;q=0.8,en;q=0.6,de;q=0.4

响应标头

HTTP/1.1 404 Not Found
Connection: keep-alive
Date: Sat, 17 Dec 2016 16:10:02 GMT
Server: Apache
Content-Length: 198
Content-Type: text/html; charset=iso-8859-1
Via: 1.1 vegur

【问题讨论】:

这是一个重复的查询。尝试从这里获得帮助***.com/questions/20035101/… 谢谢@Nadeem,但我已经遇到了这个问题,php 的答案不起作用,而且大多数其他答案都没有直接解决问题,而是提供第三方解决方案或解决方案不基于 php 的后端。我真的很想为 php 解决它作为智力兴趣,但是我强烈考虑用其他语言重写后端。 奇怪的是响应标头根本没有提及您的访问标头。 heroku 是否过滤您可以返回的标题? 我看到服务器返回一个404 错误;您确定在https://php-contact-form-lual.herokuapp.com/index.php 下的index.php 文件中有上面的PHP 代码吗?你真的需要https吗?服务器是否也接受单个 http 请求,如果是,为什么不尝试在没有 SSL 的情况下使用它?另外,您是否尝试使用 jQuery $.ajax dataType: "jsonp"JSON.stringify() 将数据作为 JSON 数据传递给 $.ajax data 的对象? @ChristosLytras 你是完全正确的,我在消息的第一部分得到了如此固定(没有 cors 标题......),我认为 404 是标题而不是其他方式的结果大约。读完这篇文章后,我去了目录,发现 index.php 名​​称中有一个错字。请正式回答,以便我接受您的回答(@Robbie 也答对了,但您比他早 3 小时发表评论),非常感谢 【参考方案1】:

我已经提出了一个非常简单的测试用例(假设一些本地服务器,或 mac 等)

文件 1:site1/index.php

<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script>
$
    .ajax(
        type: 'POST',
        url: 'http://127.0.0.1:7772',
        data: 
            subject: 'foo bar 123',
        
    )
    .done(function(data) 
        alert(data);
    );
</script>
Site 1 - sending data

文件 2:site2/index.php

<?php

header('Access-Control-Allow-Origin: *');

echo "You posted " . $_POST['subject'];

启动两个本地“服务器”,如果您使用的是 Mac,则可以执行以下操作:

cd ./site1/
php -S 127.0.0.1:7771

cd ../site2/
php -S 127.0.0.1:7772

现在转到127.0.0.1:7771,您应该会看到一个显示site2 内容的小警报。

现在注释掉站点 2 中的 header 行:

// header('Access-Control-Allow-Origin: *');

然后刷新127.0.0.1:7771,你应该回到第一格,错误为:No 'Access-Control-Allow-Origin' header is present on the requested resource

“工作”响应/请求标头:

“不工作”响应/请求标头:

我强调您不应该在生产站点中添加header('Access-Control-Allow-Origin: *');。但是你需要缩小问题的范围,这应该足以解决错误/错误配置发生的地方

【讨论】:

投反对票?我已经提供了 OP 能够回答他自己的问题所需的所有工具 - 鉴于他/她提供的信息,这是一个人能做的最多的事情。 您好@Chris,感谢您的回答,我同意您的观点,这可能澄清了我的错误,因为本地测试会让我想到与错误消息第一部分不同的其他选项由浏览器给出。【参考方案2】:

问题是 404 状态码。它甚至没有达到您输入的代码。

    你有没有

    $app->post('/', function() use($app) 
        // This is the route you need to edit.
    );
    

    您对路线有任何“时间”或其他条件吗?如果是这样,请暂时将其删除。

    您必须具有特定于 https 的配置?我还注意到您在 http (403) 和 https (404) 上有不同的设置,默认情况下 Heroku 为 http 和 https 提供相同的代码,除非您在配置中为 Silex 设置。

    1234563 . 之后有一个“退出”实际上会阻止返回的内容,这并不完全有帮助。(您需要在重定向/位置标头之后“退出”,但这里不需要)。

其他说明:

如果您想创建一个“简单”的 PHP 后端,为什么选择 Heroku?您实际上并不是在编写 PHP 代码,而是在编写 Symphony、Silex、Twig 和所有其他库,这意味着您在文档和库中过分了。 在您使用 Heroku 时,有一个 SwiftMailer 界面(将帮助您确保 mail() 安全!

【讨论】:

感谢您的评论,我选择 Heroku 是因为它的可靠性。您的第一句话实际上给了我正确的观点,我忽略了错误消息的 404 部分,因为我(错误地)假设浏览器因为标题而给了我 404 - 结果却相反:/ .我已经赞成你的回答,如果@ChristosLytras 没有发表他的评论作为答案,我会接受你的(他的评论也将我指向 404 并在你的回答之前发表)。再次,非常感谢 很高兴您对它进行了排序!并且不要担心滴答作响/不滴答作响 - 感谢 cmets 更加感激,因为我知道它有帮助。【参考方案3】:

我看到服务器返回 404 错误。这表明您在index.php 文件中的https://php-contact-form-lual.herokuapp.com/index.php 下没有上面的PHP 代码。

另外,考虑一下你是否真的需要https。服务器是否也接受单个http 请求,如果是,为什么不尝试在不使用 SSL 的情况下使用它?

最后,您是否尝试使用 jQuery $.ajax dataType: "jsonp"JSON.stringify() 将数据作为 JSON 数据传递给 $.ajax data 的对象?

【讨论】:

【参考方案4】:

有没有 htaccess 文件?

是吗?

那你可以试试这个测试吗?

<IfModule mod_headers.c>
SetEnvIfNoCase ORIGIN (.*) ORIGIN=$1
Header always set Access-Control-Allow-Methods "POST, GET, PUT, OPTIONS, PATCH, DELETE"
Header always set Access-Control-Allow-Origin "%ORIGINe"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Allow-Headers "X-Accept-Charset,X-Accept,Content-Type"
Header always set P3P "policyref='/w3c/p3p.xml', CP='NOI DSP COR NID CUR ADM DEV OUR BUS'" 
RewriteEngine On
RewriteCond %REQUEST_METHOD OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_ORIGIN:%HTTP:ORIGIN]    
</IfModule>

没有?

您可以将此 htaccess 转换为 php Header 标记。示例转换在这里 How to convert my htaccess code to php header

【讨论】:

以上是关于XMLHttpRequest 无法加载资源的主要内容,如果未能解决你的问题,请参考以下文章

XMLHttpRequest 无法以角度加载

XMLHttpRequest 无法加载。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许 Origin 访问

XMLHttpRequest 无法加载 http://127.0.0.1:1337/。请求的资源上不存在“Access-Control-Allow-Origin”标头[重复]

XMLHttpRequest 无法加载 <instagram OEMBED URL>。请求的资源上不存在“Access-Control-Allow-Origin”标头

XMLHttpRequest 无法加载请求的资源上不存在“Access-Control-Allow-Origin”标头。 AWS S3,视网膜.JS

无法通过 xmlhttprequest 加载本地 xml 文件