Это убивает меня.
Я создаю мобильное приложение, используя Apache Cordova, где jQuery AJAX и PHP используются для связи с сервером и базой данных. Я впервые обнаружил эту проблему, когда столкнулся с ошибками, которых не было у моих товарищей по команде, и мы использовали один и тот же код. В некоторых наших PHP-кодах мы использовали $_SESSION
переменные для хранения данных, но они не сохраняются должным образом при запуске приложения на моем компьютере. Вот пример кода, который не работает:
<?php
header('Access-Control-Allow-Origin : *');
include 'connection.php';
$userId = $_SESSION["userId"];
$query = "SELECT * ".
"FROM `db`.`users` ".
"WHERE `userId` = $userId;";
$result = $conn->query($query);
$result_array = array();
while($row = mysqli_fetch_assoc($result))
{
$result_array[] = $row;
}
echo json_encode($result_array);
На странице, которая запускается до этого, вызывается другой php-файл, содержащий следующую строку:
$_SESSION["userId"] = $userId;
include connection.php
содержит всю информацию о пользователе / логине, а также session_start();
прежде всего. Обходной путь был следующим: эта ошибка не возникает, когда я собираю приложение и тестирую его на устройстве. Это происходит только на моей машине при отладке приложения через эмулятор пульсации в окне браузера Chrome. Поскольку я не хотел создавать новую сборку так часто, я изменил наш код для хранения данных на внешнем интерфейсе, используя sessionStorage
и пришлось отключить настройку междоменного прокси на эмуляторе.
Вот где я считаю, что ошибка такова: ни один из моих вызовов AJAX не будет успешным, если я не установлю для междоменного прокси-сервера значение «Отключено», но если я это сделаю, PHP $_SESSION
больше не работает (я обнаружил, что идентификатор сеанса просто сбрасывает каждый новый вызов). Мой товарищ по команде может отлаживать на эмуляторе очень хорошо, и его кросс-домен прокси установлен на «Локальный». Когда я пытаюсь сделать это таким образом, все мои AJAX снова вызывают ошибку.
Также — последнее, на что следует обратить внимание: когда я запускаю приложение только в веб-браузере, не используя эмулятор пульсации или что-то еще, все работает просто отлично. Что сузило бы проблему до чего-то конкретно с помощью эмулятора пульсации.
Я относительно новичок в этом деле — запросы CORS и AJAX, но перед публикацией здесь я провел серьезное исследование — это мое последнее средство. Я буду часто следить за этим вопросом, если вам понадобится что-то еще от меня, чтобы помочь мне решить эту проблему. Спасибо!
РЕДАКТИРОВАТЬ: Ниже приведена ошибка, которую я получаю при запуске ripple emulate
из командной строки после внесения некоторых из предложенных изменений, это та же ошибка, которую я получал раньше:
C:\Users\Brian\Documents\HoH Docs\Source Code\gitDev\HoH\www>ripple emulate
INFO: Server instance running on: http://localhost:4400
INFO: CORS XHR proxy service on: http://localhost:4400/ripple/xhr_proxy
INFO: JSONP XHR proxy service on: http://localhost:4400/ripple/jsonp_xhr_proxy
INFO: Could not find cordova as a local module. Expecting to find it installed g
lobally.
INFO: Using Browser User Agent (String)
INFO: Proxying cross origin XMLHttpRequest - http://www.server.com/php/
[email protected]&password=test
_http_outgoing.js:347
throw new TypeError(
^
TypeError: Trailer name must be a valid HTTP Token ["access-control-allow-origin
"]
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:347:13)
at ServerResponse.res.setHeader (C:\Users\Brian\AppData\Roaming\npm\node_mod
ules\ripple-emulator\node_modules\express\node_modules\connect\lib\patch.js:59:2
2)
at Request.pipeDest (C:\Users\Brian\AppData\Roaming\npm\node_modules\ripple-
emulator\node_modules\request\main.js:723:12)
at C:\Users\Brian\AppData\Roaming\npm\node_modules\ripple-emulator\node_modu
les\request\main.js:614:14
at Array.forEach (native)
at ClientRequest.<anonymous> (C:\Users\Brian\AppData\Roaming\npm\node_module
s\ripple-emulator\node_modules\request\main.js:613:18)
at ClientRequest.g (events.js:260:16)
at emitOne (events.js:77:13)
at ClientRequest.emit (events.js:169:7)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:433:21
)
И получите это от Fiddler Web Debugger, когда запрос сделан:
The connection to 'localhost' failed. <br />Error: ConnectionRefused (0x274d). <br />System.Net.Sockets.SocketException No connection could be made because the target machine actively refused it 127.0.0.1:4400
Скорее всего это ваша проблема:
header('Access-Control-Allow-Origin : *');
include 'connection.php';
Вы отправляете заголовки в браузер, прежде чем включить файл подключения, с которого вы начинаете сеанс.
В некоторых средах тестирования может быть включена буферизация вывода, чтобы это работало. Тем не менее, в вашей среде кажется, что это не так, ваш session_start()
в connection.php
не удастся.
Вы не должны ничего выводить в браузер перед вызовом session_start()
так что в этом случае вы должны переместить header()
позвоните ниже, чтобы включить:
include 'connection.php';
header('Access-Control-Allow-Origin : *');
Вы можете убедиться, что это проблема в журнале ошибок сервера.
Возможно, вам придется установить header
в вашем запросе ajax
если вы используете jQuery ajax метод, то добавьте ниже опцию
xhrFields: {
withCredentials: true
}
Или, если вы отправляете ajax-запрос с использованием объекта XMLHttpRequest, то это должно быть что-то вроде belwo
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
Ответы XmlHttpRequest из другого домена не могут установить cookie
значения для их собственного домена, если для withCredentials не установлено значение true
перед выполнением запроса, независимо от Access-Control-заголовка
ценности.