• 9
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

XMLHttpRequest cannot load resource

I'm trying to make a simple php backend to handle a contact form in another server, but despite adding the proper headers, it keeps giving me the same error message:

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.


This is the ajax request:

$.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


and this is the 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);

?>

Notice that the lines of code before the "handling the data" block are taken from this answer, I also tried with the simpler solution presented in the first part of that same answer -found also elsewhere-, and even replacing the asterisk with the specific URL, but the result has been the same :(

Any help would be appreciated :)


Update: log of the things I've tried on the server side (from oldest to current):

// 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');


Aditional info

Request headers

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

Response headers

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
      • 2
    • @ChristosLytras You are totally right, I got so fixed in the first part of the message (no cors headers...) that I thought that the 404 was consequence of the headers instead of the other way around. After I read this I went to the directory and found out a typo in the index.php name. Please answer officially so I can accept your answer (@Robbie also got it right, but you commented 3 hours before him), thanks a lot
    • Thanks @Nadeem, but I already came accross that question and the php answer doesn't work and most of the other answers doesn't address the problem directly, but give third-party solutions or solutions with backends not based on php. I'd really like to solve it for php as for intellectual interest, however I'm strongly considering to rewrite the backend in other language.
      • 2
    • The strange thing is the response headers don't mention your access headers at all. Does heroku filter the headers you can return?
    • I see the server return a 404 error; are you sure you have the PHP code above inside the index.php file under https://php-contact-form-lual.herokuapp.com/index.php? Do you really need https? Does the server also accepts single http requests and if so, why don't you try to use it without SSL? Also, did you try to pass the data as JSON data using the jQuery $.ajax dataType: "jsonp" and JSON.stringify({}) an object for the $.ajax data?

I see that the server is returning a 404 error. This suggests that you do not have the PHP code above inside the index.php file under https://php-contact-form-lual.herokuapp.com/index.php.

Also, consider whether you really need https. Does the server also accept single http requests, and if so, why don't you try to use it without SSL?

Finally, did you try to pass the data as JSON data using the jQuery $.ajax dataType: "jsonp" and JSON.stringify({}) an object for the $.ajax data?

  • 9
Reply Report

The problem is the 404 status code. It's not even reaching the code you're typing.

  1. Do you have a

    $app->post('/', function() use($app) {
        // This is the route you need to edit.
    });
    
  2. Do you have any "when" or other condition for the route? If so, remove it for now.

  3. You must has configuration specific for https? I also note that you have different settings on http (403) vs. https (404), by default Heroku delivers the same code for both http and https unless you set in config for Silex.

  4. Once you get that working (i.e. not a 404), you'll need to return the Access-Control-Allow-Origin header at the same time as the response (as you have in one of the "what I tried" examples. Having an "exit" after that will actually prevent the content being returned which is not totally helpful. (You need "exit" after redirect/location headers, but not here).


Other notes:

  • If you're trying to create a "simple" PHP backend, why go for Heroku? You're not really coding PHP, but coding Symphony, Silex, Twig and all the other libraries that mean you're in documentation and library overkill.
  • As you are using Heroku, there's a SwiftMailer interface (will help you make the mail() secure!
  • 4
Reply Report
      • 1
    • Thanks for your remarks, I chose Heroku because of its reliability. Your first sentence actually gives me the correct perspective, I had ignored the 404 part of the error message because I assumed (wrongly) that the browser gave me that 404 because of the headers -and it turned out to be the other way around :/. I already upvoted your answer and if @ChristosLytras doesn't publish his comment as an answer, I'll accept yours (his comment also pointed me to the 404 and was published before your answer). Again, thanks a lot
    • Glad you sorted it! And don't be concerned about ticking/not ticking - the thank-you comments are much more appreciated as I know it helped.

I've put up an extremely simple test case (assuming some local server, or mac, etc)

File 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

File 2: site2/index.php

<?php

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

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

Boot up both local "servers", if you're on a mac, you can do something like:

cd ./site1/
php -S 127.0.0.1:7771

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

Now go to 127.0.0.1:7771 and you should see a little alert showing the contents of site2.

Now comment out the header line in site 2:

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

And refresh 127.0.0.1:7771 and you should be back at square one with the error of: No 'Access-Control-Allow-Origin' header is present on the requested resource

"Working" response/request headers:

enter image description here

"Not Working" response/request headers:

enter image description here

I stress that you shouldn't add header('Access-Control-Allow-Origin: *'); in a production site. But you need to narrow down the issue, and this should be enough to where the error/misconfiguration is occurring

  • 1
Reply Report
      • 2
    • Downvote? I have given all the tools the OP needs to be able to answer his own question - which given the information he/she has provided is the most one can do.
      • 1
    • Hello @Chris, thanks for your answer, I agree with you that this might have clarified my mistake, since the local test would have made me think of other options different from the first part of the error message given by the browser.

is there any htaccess file ?

Yes ?

Then can you try this one for test ?

<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 "%{ORIGIN}e"
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>

No ?

You can convert this htaccess to the php Header tag. Sample conversion here How to convert my htaccess code to php header

  • 0
Reply Report

Warm tip !!!

This article is reproduced from Stack Exchange / Stack Overflow, please click

Trending Tags

Related Questions