Я пытаюсь реализовать собственный сервер CardDAV поверх NWebDAV и ASP. NET Core 3.1, используя существующую базу данных в качестве фактического источника данных для контактов. (NWebDAV, похоже, имеет отличную поддержку основных c понятий WebDAV, таких как ответ на PROPFIND
. Из коробки запуск его примера проекта для обслуживания вашего домашнего каталога, похоже, отлично работает. OTOH, такие вещи, как REPORT
, по-видимому, отсутствуют , и я еще не уверен, сколько работы это будет.)
Я использую iOS 13 в качестве основного клиента для тестирования.
Я успешно получил его:
- пройти «проверку» при добавлении моего сервера в качестве учетной записи (включая Basi c auth)
- показать несколько адресных книг, которые я обслуживаю, в представлении «Группы» приложения «Контакты»
Итак, я знаю, что он анализирует мои PROPFIND
ответы на точку. Но потом ничего. Насколько я понимаю, он должен выдать какой-то запрос REPORT
к моему серверу, либо сначала выполнить полную синхронизацию c, либо - при вводе чего-либо в поле поиска - запросить определенные контакты. Кажется, он никогда не пытается.
Я даю ему что-то вроде:
<addressbook-home-set xmlns="urn:ietf:params:xml:ns:carddav">
<D:href>/addressbooks/sample/108</D:href>
<D:href>/addressbooks/sample/109</D:href>
</addressbook-home-set>
И он выдает запрос PROPFIND
к каждой из этих адресных книг, например:
<?xml version="1.0" encoding="utf-8"?>
<A:propfind xmlns:A="DAV:">
<A:prop>
<A:add-member />
<E:bulk-requests xmlns:E="http://me.com/_namespace/" />
<A:current-user-privilege-set />
<A:displayname />
<E:guardian-restricted xmlns:E="http://me.com/_namespace/" />
<D:max-image-size xmlns:D="urn:ietf:params:xml:ns:carddav" />
<D:max-resource-size xmlns:D="urn:ietf:params:xml:ns:carddav" />
<C:me-card xmlns:C="http://calendarserver.org/ns/" />
<A:owner />
<C:push-transports xmlns:C="http://calendarserver.org/ns/" />
<C:pushkey xmlns:C="http://calendarserver.org/ns/" />
<A:quota-available-bytes />
<A:quota-used-bytes />
<A:resource-id />
<A:resourcetype />
<A:supported-report-set />
<A:sync-token />
</A:prop>
</A:propfind>
Я отвечаю на это следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:">
<D:response>
<D:href>http://localhost:55946/addressbooks/sample/108</D:href>
<D:propstat>
<D:prop>
<D:add-member />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}add-member is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<bulk-requests xmlns="http://me.com/_namespace/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://me.com/_namespace/}bulk-requests is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<guardian-restricted xmlns="http://me.com/_namespace/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://me.com/_namespace/}guardian-restricted is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<max-image-size xmlns="urn:ietf:params:xml:ns:carddav" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {urn:ietf:params:xml:ns:carddav}max-image-size is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<max-resource-size xmlns="urn:ietf:params:xml:ns:carddav" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {urn:ietf:params:xml:ns:carddav}max-resource-size is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:owner />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}owner is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<push-transports xmlns="http://calendarserver.org/ns/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://calendarserver.org/ns/}push-transports is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<pushkey xmlns="http://calendarserver.org/ns/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://calendarserver.org/ns/}pushkey is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:quota-available-bytes />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}quota-available-bytes is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:quota-used-bytes />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}quota-used-bytes is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:resource-id />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}resource-id is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:sync-token />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}sync-token is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:current-user-privilege-set>
<D:privilege>
<D:read />
</D:privilege>
<D:privilege>
<D:read-acl />
</D:privilege>
<D:privilege>
<D:read-current-user-privilege-set />
</D:privilege>
<D:privilege>
<D:write />
</D:privilege>
<D:privilege>
<D:bind />
</D:privilege>
</D:current-user-privilege-set>
<D:displayname>SampleContacts108</D:displayname>
<me-card xmlns="http://calendarserver.org/ns/">
<D:href>/addressbooks/sample/108/contact-49191/</D:href>
</me-card>
<D:resourcetype>
<D:collection />
<addressbook xmlns="urn:ietf:params:xml:ns:carddav" />
</D:resourcetype>
<D:supported-report-set>
<D:supported-report>
<addressbook-query xmlns="urn:ietf:params:xml:ns:carddav" />
</D:supported-report>
<D:supported-report>
<addressbook-multiget xmlns="urn:ietf:params:xml:ns:carddav" />
</D:supported-report>
<D:supported-report>
<D:expand-property />
</D:supported-report>
</D:supported-report-set>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
<D:response>
<D:href>http://localhost:55946/addressbooks/sample/108/Bar,Foo</D:href>
<D:propstat>
<D:prop>
<D:add-member />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}add-member is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<bulk-requests xmlns="http://me.com/_namespace/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://me.com/_namespace/}bulk-requests is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:current-user-privilege-set />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}current-user-privilege-set is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<guardian-restricted xmlns="http://me.com/_namespace/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://me.com/_namespace/}guardian-restricted is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<max-image-size xmlns="urn:ietf:params:xml:ns:carddav" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {urn:ietf:params:xml:ns:carddav}max-image-size is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<max-resource-size xmlns="urn:ietf:params:xml:ns:carddav" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {urn:ietf:params:xml:ns:carddav}max-resource-size is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<me-card xmlns="http://calendarserver.org/ns/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://calendarserver.org/ns/}me-card is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:owner />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}owner is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<push-transports xmlns="http://calendarserver.org/ns/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://calendarserver.org/ns/}push-transports is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<pushkey xmlns="http://calendarserver.org/ns/" />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {http://calendarserver.org/ns/}pushkey is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:quota-available-bytes />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}quota-available-bytes is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:quota-used-bytes />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}quota-used-bytes is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:resource-id />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}resource-id is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:resourcetype />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}resourcetype is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:supported-report-set />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}supported-report-set is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:sync-token />
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
<D:responsedescription>Property {DAV:}sync-token is not supported.</D:responsedescription>
</D:propstat>
<D:propstat>
<D:prop>
<D:displayname>Bar, Foo</D:displayname>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>
(Я реализовал me-card
, потому что кто-то сказал, что его невыполнение может привести к sh iOS Контакты, и в надежде, что это подскажет От iOS до хотя бы попытайтесь получить карту меня. Но увы.)
Этот ответ включает метаданные как для самой адресной книги, так и для образца контакта внутри. Я не уверен, что это правильно, но отсутствие этого контакта, похоже, ничего не меняет.
Я поддерживаю отчеты addessbook-query
и addressbook-multiget
. Мое чтение 8. Отчеты адресной книги в spe c говорят о том, что этого должно быть достаточно для соответствия стандарту.
Меня озадачивает то, что там просто… ничего. Нет ошибок, с которыми сталкивается пользователь, нет дополнительных запросов, et c.
Я нашел кое-что в консоли:
com.apple.dataaccess debug 10:52:13.523530+0200 dataaccessd <private>: There are no server side items to grab, so I'm outta here
Но я не знаю, относится ли это к этот аккаунт (может быть другой сервер). Если да, то мне бы хотелось узнать, что привело iOS к такому выводу?
Итак, мой главный вопрос: правильно ли я полагаю c, что клиент CardDAV должен в конечном итоге отправить запрос REPORT
для запроса контактов?