#php #session #curl
#php #сеанс #curl
Вопрос:
Я создаю приложение, используя локальный php-файл, который принимает post / get ввод и возвращает результаты JSON. Я делаю это, чтобы разделить работу интерфейса и серверной части, исходя из идеи, что в конечном итоге можно переместить серверную часть в другое место (и это здорово, потому что вы можете протестировать работу серверной части, используя только переменные браузера и URL.
Чтобы было ясно, у меня нет немедленных или даже долгосрочных планов по их фактическому разделению: прямо сейчас они находятся на одном сервере в одной папке даже — у меня просто есть один backend.php файл, притворяющийся удаленным сервером, чтобы я мог практиковать развязку. Победа в этой проблеме означает вызов CURL и получение бэкэндом сеанса, бэкэнд может изменять / обновлять / добавлять к сеансу, а интерфейс видит все изменения (в основном ОДИН сеанс для передней и задней части).
Проблема в том, что я постоянно борюсь за то, чтобы сеанс работал между ними. Когда я делаю AJAX-запросы с помощью Javascript, сеанс работает нормально, потому что страница загружается на тот же сервер, поэтому session_start() просто работает. Но когда я выполняю CURL, данные сеанса не передаются.
Я боролся с этим в течение нескольких месяцев, поэтому моя функция curl довольно запутанная, но я не могу понять волшебную комбинацию, которая заставляет это работать. Никакое количество вопросов SO или онлайн-руководств, которые я смог найти, не работают последовательно в этом случае:
// Call the backend using the provided URL and series of name/value vars (in an array)
function backhand($data,$method='POST') {
$url = BACKEND_URL;
// Make sure the backend knows which session in the db to connect to
//$data['session_id'] = session_id();
// Backend will send this back in session so we can see the the connection still works.
//$data['session_test'] = rand();
$ch = curl_init();
if ('POST' == $method) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$get_url = sprintf("%s?%s", $url, http_build_query($data));
$_SESSION['diag']['backend-stuff'][] = $get_url;
if ('GET' == $method) {
curl_setopt($ch, CURLOPT_PUT, 1);
$url = $get_url;
}
// Optional Authentication:
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
# curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
# curl_setopt($ch, CURLOPT_VERBOSE, 1);
# curl_setopt($ch, CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']);
// Retrieving session ID
// $strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';
$cookieFile = "cookies.txt";
if(!file_exists($cookieFile)) {
$fh = fopen($cookieFile, "w");
fwrite($fh, $_SESSION);
fclose($fh);
}
#curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
#curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
#curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Cookie aware
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // Cookie aware
// We pass the sessionid of the browser within the curl request
curl_setopt( $ch, CURLOPT_COOKIEFILE, $strCookie );
# session_write_close();
// Have to pause the session or the backend wipes the front
if (!$result = curl_exec($ch)) {
pre_r(curl_getinfo($ch));
echo 'Cerr: '.curl_error($ch);
}
curl_close($ch);
# session_start();
// "true" makes it return an array
return json_decode($result,true);
}
Я вызываю функцию таким образом из интерфейса, чтобы получить результаты из серверной части:
// Get user by email or ID
function get_user($emailorid) {
// If it's not an email, see if they've been cached. If so, return them
if (is_numeric($emailorid) amp;amp; $_SESSION['users'][$emailorid])
return $_SESSION['users'][$emailorid];
return backhand(['get_user'=>$emailorid]);
}
Поэтому, если я вызову «get_user» в любом месте спереди, он перейдет на задний план, запустит запросы к БД и сбросит все это в JSON, который возвращается мне в ассоциативных массивах значений. Это работает нормально, но данные сеанса не сохраняются должным образом, и это вызывает проблемы.
Я даже некоторое время пробовал сеансы DB, но это тоже не соответствовало. У меня заканчиваются идеи, и, возможно, придется создать какую-то альтернативную возможность сеанса с помощью db и пользовательских функций, но я ожидаю, что это МОЖЕТ сработать… Я просто еще не понял, как это сделать.
Комментарии:
1. Просто чтобы убедиться, ваша проблема заключается в совместном использовании сеанса PHP между двумя серверами?
2. Нет. Я хотел бы, возможно, рассмотреть это в конечном итоге, но прямо сейчас файлы внешнего интерфейса и серверной части находятся в одной папке на одном сервере. Я пытаюсь убедиться, что сеанс не теряется в CURL.
Ответ №1:
Вы можете сохранить хранилище файловой системы и совместно использовать каталог файлов, в котором хранится сеанс, с NFS, если ваши серверные веб-серверы находятся на разных серверах.
Вы также можете использовать http://www.php.net/manual/en/function.session-set-save-handler.php чтобы установить другой обработчик сохранения для вашего сеанса, но я не уверен, что сохранение их в базе данных было бы хорошей идеей для ввода-вывода.
Комментарии:
1. Я согласен, что хранилище БД для сеанса — это болото, и я хочу этого избежать. И интерфейс, и серверная часть находятся на одном сервере в одной папке в данный момент и в обозримом будущем. Если я смогу найти хороший ответ для решения насущной проблемы, этого будет достаточно на данный момент
Ответ №2:
После проб и ошибок методом перебора это, похоже, работает:
function backhand($data,$method='POST') {
$url = BACKEND_URL;
// Make sure the backend knows which session in the db to connect to
//$data['session_id'] = session_id();
// Backend will send this back in session so we can see the the connection still works.
$data['session_test'] = rand();
$ch = curl_init();
if ('POST' == $method) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$get_url = sprintf("%s?%s", $url, http_build_query($data));
$_SESSION['diag']['backend-stuff'][] = $get_url;
if ('GET' == $method) {
curl_setopt($ch, CURLOPT_HTTPGET, 1);
$url = $get_url;
}
// Optional Authentication:
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
// required or it writes the data directly into document instead of putting it in a var below
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
#curl_setopt($ch, CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']);
// Retrieving session ID
$strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';
// We pass the sessionid of the browser within the curl request
curl_setopt( $ch, CURLOPT_COOKIE, $strCookie );
curl_setopt($ch, CURLOPT_COOKIEJAR, 'somefile');
curl_setopt($ch, CURLOPT_COOKIEFILE, APP_ROOT.'/cookie.txt');
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000);
// Have to pause the session or the backend wipes the front
session_write_close();
if (!$result = curl_exec($ch)) {
pre_r(curl_getinfo($ch));
echo 'Cerr: '.curl_error($ch);
}
@session_start();
curl_close($ch);
// "true" makes it return an array
return json_decode($result,true);
}