Как интегрировать сабредав в контроллер laravel?
Я пытаюсь создать SabreDAV-сервер в маршруте Laravel. Следующий код показывает, что я пытался:
Illuminate\Routing\Router::$verbs = [
'GET',
'HEAD',
'POST',
'PUT',
'PATCH',
'DELETE',
'PROPFIND',
'PROPPATCH',
'MKCOL',
'COPY',
'MOVE',
'LOCK',
'UNLOCK'
];
Route::match(['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH', 'PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK'], 'carddav{test}', function()
{
date_default_timezone_set('Europe/Berlin');
$baseUri = '/carddav';
$pdo = new PDO('mysql:host=localhost;dbname=dav', 'root', 'root');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$authBackend = new \Sabre\DAV\Auth\Backend\PDO($pdo);
$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo);
$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);
$nodes = [
new \Sabre\DAVACL\PrincipalCollection($principalBackend),
new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend)
];
$server = new \Sabre\DAV\Server($nodes);
$server->setBaseUri($baseUri);
$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, 'SabreDAV'));
$server->addPlugin(new \Sabre\DAV\Browser\Plugin());
$server->addPlugin(new \Sabre\CardDAV\Plugin());
$server->addPlugin(new \Sabre\DAVACL\Plugin());
$server->addPlugin(new \Sabre\DAV\Sync\Plugin());
$server->exec();
})->where('path', '(.)*';
Но если я пытаюсь вызвать его в браузере, возникает ошибка:
<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
<s:sabredav-version>2.0.4</s:sabredav-version>
<s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
<s:message>No digest authentication headers were found</s:message>
</d:error>
Не было запроса на аутентификацию.
Если я пытаюсь подключиться из Evolution, появляется сообщение: "Метод не разрешен".
Кто-нибудь знает, в чем проблема?
Спасибо Пепе
1 ответ
Проблема в отправленном коде статуса HTTP. Независимо от ответа от SabreDAV, маршрутизатор Laravel всегда устанавливает код состояния HTTP на 200, поэтому ни один клиент CardDAV никогда не узнает, что ему нужно авторизовать запросы - игнорируя Basic Auth Challenge.
Мое решение может быть не самым элегантным, но оно работает. Просто оберните $server->exec() в теги ob_start() и ob_end() и выведите содержимое с реальным ответом Laravel:
ob_start();
$server->exec();
$status = $server->httpResponse->getStatus();
$content = ob_get_contents();
ob_end_clean();
return response($content, $status);
Общее руководство:
- Используйте "почтальон" (Google Chrome App) для тестирования запросов, вы увидите, что они работают при отправке заголовков авторизации заранее.
- Используйте прокси-сервер для отладки, такой как "Charles", чтобы отслеживать фактические тела запросов и ответов.