Hallo Leute, bin derzeit dabei einen Rails basierten CalDAV Server zu entwickeln. Seit geraumer Zeit sitze ich allerdings an einem Problem, das ich weder lösen , noch irgendwie eingrenzen kann. Wie die Meisten sicherlich wissen, setzt CalDAV auf dem WebDAV Standard auf und nutzt XML zum Informationsaustausch. In manchen Fällen ist eine Multistatus Response notwendig. Zu Testzwecken realisiere ich das so: render :text => my_xml_response, :status => 207 iCal verhält sich aber leider nicht so wie erwartet, sondern liefert eine Fehlermeldung Request und Response überwache ich mit dem HTTP Sniffer HTTP Scoop. Schaut man sich den betreffenden Vorgang an wird deutlich, dass die TCP Verbindung zwischen iCal und der Rails Anwendung unerwartet abbricht. Beim gleichen Vorgang zwischen iCal und dem Apple CalendarServer verläuft alles wie geplant und die Verbindung wird korrekt terminiert. Ändere ich nun meinen Code in render :text => my_xml_response, :status => 200 bekomme ich zwar einen Fehler in iCal (weil die XML Response nicht zum 200er Status passt), aber die TCP Verbindung wird nicht unerwartet terminiert. Hat jemand von Euch Erfahrung mit CalDAV oder WebDAV unter Rails? Gibt es etwas, dass ich bei der Verwendung des 207er Status beachten muss? Oder ist dieses Verhalten ein Bug? Bin für jede Hilfe Dankbar. ML
on 2009-06-25 23:47
on 2009-06-26 15:39
Lindhorst Matthias wrote: > Zu Testzwecken realisiere ich das so: > render :text => my_xml_response, :status => 207 wird der Content-Type hier korrekt auf XML gesetzt, oder liefert der Server das XML als text/plain aus? > Schaut man sich den betreffenden Vorgang an wird deutlich, dass die > TCP Verbindung zwischen iCal und der Rails Anwendung unerwartet > abbricht. Möglicherweise macht iCal die Verbindung sofort zu, wenn es erkennt, dass es mit dem Content nichts anfangen kann. > Hat jemand von Euch Erfahrung mit CalDAV oder WebDAV unter Rails? Nicht mit Rails, aber mit CalDAV/WebDAV ;-) > Gibt es etwas, dass ich bei der Verwendung des 207er Status beachten > muss? Siehe oben. Am besten du schickst mal den Dump vom HTTP Traffic zwischen iCal und deinem Server. Gruss, Helge -- http://zideone.com/
on 2009-06-28 14:53
Hi Helge, vielen Dank für die schnelle Antwort. > wird der Content-Type hier korrekt auf XML gesetzt, oder liefert der > Server das XML als text/plain aus? Habe den Content-Type explizit auf text/xml gesetzt, iCal zeigt aber dennoch das gleiche verhalten. > Möglicherweise macht iCal die Verbindung sofort zu, wenn es erkennt, > dass es mit dem Content nichts anfangen kann. Dann müsste iCal aber auch die Verbindung schließen, wenn es einen 200er Status bekommt, da sich die Daten ja nicht ändern, oder? Ich bin mir außerdem nicht sicher, warum iCal den Response Body parsen sollte, bevor dieser vollständig ist. Hatte vor geraumer Zeit ein ähnliches Szenario aufgebaut, allerdings nicht mit PROPFIND und iCal, sondern per GET mit Firefox. Auch hier wurde die Verbindung beendet, bevor die Übertragung zu Ende war. Den Body konnte der Browser dann darstellen, aber die Header Informationen waren teilweise nicht vorhanden. > Am besten du schickst mal den Dump vom HTTP Traffic zwischen > iCal und deinem Server. ----------------------------------------------------------------- Fall 1 (iCal + Apple CalendarServer ) ----------------------------------------------------------------- ----------------------------------------------------------------- REQUEST ----------------------------------------------------------------- Method: PROPFIND URL: http://localhost:8008/principals/users/admin/ Headers: User-Agent: DAVKit/3.0.6 (661); CalendarStore/3.0.7 (858); iCal/3.0.7 (1284); Mac OS X/10.5.7 (9J61) Host: localhost:8008 Depth: 0 Authorization: Digest username="admin", realm="Test Realm", nonce="100045035610880960381959273727", uri="/principals/users/ admin/", response="65720e9b3f2c6cf498b8c29e452b62a9", algorithm="md5" Content-Type: text/xml Content-Length: 374 Connection: keep-alive Post Data: <?xml version="1.0" encoding="utf-8"?> <x0:propfind xmlns:x2="http://calendarserver.org/ns/" xmlns:x1="urn:ietf:params:xml:ns:caldav " xmlns:x0="DAV:"> <x0:prop> <x1:calendar-home-set/> <x1:calendar-user-address-set/> <x1:schedule-inbox-URL/> <x1:schedule-outbox-URL/> <x2:dropbox-home-URL/> <x2:notifications-URL/> <x0:displayname/> </x0:prop> </x0:propfind> ----------------------------------------------------------------- RESPONSE ----------------------------------------------------------------- Headers: Accept-Ranges: bytes Server: Twisted/2.5.0+rUnknown TwistedWeb/[twisted.web2, version 0.2.0 (SVN rUnknown)] DAV: 1, access-control, calendar-access, calendar-schedule, calendar- auto-schedule, calendar-availability, inbox-availability, calendar- proxy, calendarserver-private-events, calendarserver-private-comments, calendarserver-principal-property-search Content-Length: 1762 Date: Sun, 28 Jun 2009 12:07:41 GMT Content-Type: text/xml Last-Modified: Fri, 26 Jun 2009 16:37:35 GMT Body: <?xml version='1.0' encoding='UTF-8'?> <multistatus xmlns='DAV:'> <response> <href>/principals/users/admin/</href> <propstat> <prop> <calendar-home-set xmlns='urn:ietf:params:xml:ns:caldav'> <href xmlns='DAV:'>/calendars/__uids__/admin</href> </calendar-home-set> <calendar-user-address-set xmlns='urn:ietf:params:xml:ns:caldav' > <href xmlns='DAV:'>urn:uuid:admin</href> <href xmlns='DAV:'>http://Aton:8008/principals/__uids__/admin/ </href> <href xmlns='DAV:'>http://Aton:8008/principals/users/admin/ </href> <href xmlns='DAV:'>https://Aton:8443/principals/__uids__/admin/ </href> <href xmlns='DAV:'>/principals/users/admin/</href> <href xmlns='DAV:'>https://Aton:8443/principals/users/admin/ </href> <href xmlns='DAV:'>/principals/__uids__/admin/</href> </calendar-user-address-set> <schedule-inbox-URL xmlns='urn:ietf:params:xml:ns:caldav'> <href xmlns='DAV:'>/calendars/__uids__/admin/inbox/</href> </schedule-inbox-URL> <schedule-outbox-URL xmlns='urn:ietf:params:xml:ns:caldav'> <href xmlns='DAV:'>/calendars/__uids__/admin/outbox/</href> </schedule-outbox-URL> <dropbox-home-URL xmlns='http://calendarserver.org/ns/'> <href xmlns='DAV:'>/calendars/__uids__/admin/dropbox/</href> </dropbox-home-URL> <displayname>Super User</displayname> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <notifications-URL xmlns='http://calendarserver.org/ns/'/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> </multistatus> ----------------------------------------------------------------- Fall 2 (iCal + Rails ) ----------------------------------------------------------------- ----------------------------------------------------------------- REQUEST ----------------------------------------------------------------- Method: PROPFIND URL: http://localhost:8008/principals/users/admin/ Headers: User-Agent: DAVKit/3.0.6 (661); CalendarStore/3.0.7 (858); iCal/3.0.7 (1284); Mac OS X/10.5.7 (9J61) Content-Type: text/xml Host: localhost:3000 Depth: 0 Content-Length: 374 Connection: close Post Data: <?xml version="1.0" encoding="utf-8"?> <x0:propfind xmlns:x2="http://calendarserver.org/ns/" xmlns:x1="urn:ietf:params:xml:ns:caldav " xmlns:x0="DAV:"> <x0:prop> <x1:calendar-home-set/> <x1:calendar-user-address-set/> <x1:schedule-inbox-URL/> <x1:schedule-outbox-URL/> <x2:dropbox-home-URL/> <x2:notifications-URL/> <x0:displayname/> </x0:prop> </x0:propfind> ----------------------------------------------------------------- RESPONSE ----------------------------------------------------------------- Closed by peer Habe mit Packet Peeper noch 2 TCP Dumps gemacht und diese angehängt. Die Dateien sollten sich aber auch mit ireshark öffnen lassen. Könnte es sein, dass Rails einen Bug hat, der beim 207er Status die Verbindung unterbricht, bevor die Antwort gesendet wurde? Gruß Matthias
on 2009-06-28 15:18
Lindhorst Matthias wrote: > Dann müsste iCal aber auch die Verbindung schließen, wenn es einen > 200er Status bekommt, da sich die Daten ja nicht ändern, oder? Nein, warum? Kommt im Endeffekt auf die Implementierung an. Ich glaube aber nicht, dass es ein iCal Problem ist, eher ein Rails Problem. Ich würde iCal auch erstmal komplett aussen vor lassen und mit 'curl' iCal simulieren bis es klappt, zB: ---snip--- curl --request PROPFIND -v \ --insecure --digest \ --header "Content-Type: text/xml" \ --header "Depth: 0" \ --data-binary "@principal-props.xml" \ --user "test:pwd" \ "http://railsserver/principals/users/test/" ---snap--- In die Datei 'principal-props.xml' packst du das XML aus dem iCal Request. > Ich bin mir außerdem nicht sicher, warum iCal den Response Body parsen > sollte, bevor dieser vollständig ist. Eigentlich parsen alle vernünftigen Bibliotheken die Daten inkrementell sobald sie reinkommen (bei XML zB via SAX). Reduziert Speicherverbrauch und Latenzzeit. Gerade die REPORT Requests auf mehrere Termine können ja recht gross werden. > Method: PROPFIND > URL: http://localhost:8008/principals/users/admin/ Und auf Port 8008 läuft deine Rails App. Hinter einem HTTP Server, oder ist das direkt ein Rails Prozess? Wie hast du /principals/users/admin/ im Rails auf deinen Controller gemapped? > RESPONSE > Closed by peer Hm, im packet dump sieht es so aus, also ob du dem iCal etwas schickst. Auf den ersten Blick fällt auf, dass die HTTP response Zeile kaputt scheint (Frame 9). Anscheinend generiert Rails hier sowas: HTTP/1.1[space]207[space][cr][lf] Richtig ist eigentlich sowas: HTTP/1.1[space]207[space]Multistatus[cr][lf] Eventuell stört dass den HTTP Layer von MacOS schon. Vermutlich hat Rails per Default kein Mapping von 207 auf einen Text. Bei 200 wird er korrekt "HTTP/1.1 200 OK" generieren. Gruss, Helge
on 2009-06-28 16:05
Hi Helge, Danke für Deine Hilfe, werde das gleich mal mit curl checken. > Nein, warum? Kommt im Endeffekt auf die Implementierung an. Ich glaube > aber nicht, dass es ein iCal Problem ist, eher ein Rails Problem. Ich gehe ja auch davon aus, dass es ein Rails Problem ist, deswegen die Anfrage auf der Rails-ug Liste *g*. > Und auf Port 8008 läuft deine Rails App. Hinter einem HTTP Server, > oder > ist das direkt ein Rails Prozess? Wie hast du /principals/users/admin/ > im Rails auf deinen Controller gemapped? Nein, auf 8008 läuft der CalendarServer von Apple, meine RailsApp läuft via Mongrel auf Port 3000. Das Mapping auf den Principials Controller habe ich mit ActionController::Routing::HTTP_METHODS << 'propfind'.to_sym [...] 'map.connect /principals/:principal_type/:name/', :controller => 'principals' realisiert. Rails lehnt normaler Weise PROPFIND und andere zusätzliche HTTP Methoden ab, deswegen musste ich ihm diese erst in der environment.rb "bekannt" machen: # Enable WebDAV HTTP methods WEBDAV_HTTP_METHODS = %w(propfind report) WEBDAV_HTTP_METHOD_LOOKUP = WEBDAV_HTTP_METHODS.inject({}) { |h, m| h[m] = h[m.upcase] = m.to_sym; h} ActionController::Request::HTTP_METHODS.concat(WEBDAV_HTTP_METHODS) ActionController::Request::HTTP_METHOD_LOOKUP.merge! (WEBDAV_HTTP_METHOD_LOOKUP) > Vermutlich hat Rails per Default kein Mapping von 207 auf einen Text. > Bei 200 wird er korrekt "HTTP/1.1 200 OK" generieren. Was mich bei der Antwort von Rails in Frame 9 auch stutzig macht, ist: >> HTTP/1.1 207 ..Connection: close << Wirkt auf mich, also würde Rails die Verbindung als beendet ansehen, bevor überhaupt ein Responsebody gesendet wurde. Gruß Matthias
on 2009-06-28 16:13
Lindhorst Matthias wrote: > Ich gehe ja auch davon aus, dass es ein Rails Problem ist, deswegen > die Anfrage auf der Rails-ug Liste *g*. Yup ;-) Eventuell hilft es ja deine Frage konkreter zu stellen und eine Rails-Antwort zu bekommen. >> Vermutlich hat Rails per Default kein Mapping von 207 auf einen Text. >> Bei 200 wird er korrekt "HTTP/1.1 200 OK" generieren. Ich denke du musst dieses Problem beheben, dann wirds klappen ;-) Sieht mir nach einem (kleinen) Rails Bug aus. > Was mich bei der Antwort von Rails in Frame 9 auch stutzig macht, ist: > >> HTTP/1.1 207 ..Connection: close << > Wirkt auf mich, also w�rde Rails die Verbindung als beendet ansehen, > bevor �berhaupt ein Responsebody gesendet wurde. Nein, das ist OK und üblich. Der Connection 'close' header sagt dem Client, dass er _nach dem Lesen der Response_ die Verbindung kappen soll (also keine persistenten HTTP Connections verwendet). Gruss, Helge
on 2009-06-30 10:48
Hi Helge, habe jetzt mal ein paar Test laufen lassen und fest gestellt, dass HTTP Scoop anscheinend das Problem ist. Wenn der Status so aussieht HTTP/1.1[space]207[space][cr][lf] erkennt HTTP Scoop diesen fälschlicher Weise nicht als gültigen HTTP Status. Habe die xml resonse des Apple CalendarServers kopiert und Rails dazu veranlasst diese mit dem Status 207 zu rendern. iCal hat darauf wie erwartet reagiert und versucht die angegebenen URLs von Calendar Home Set etc. zu erreichen Also lag der Fehler von Anfang an nicht bei Rails oder iCal, sondern an HTTP Scoop ;) Sorry für den Aufwand und vielen Dank für die Hilfe ! Gruß Matthias Helge Heß schrieb:
on 2009-06-30 11:02
Ah ja, prima ;-) Ich bin interessiert an dem 'CalDAV-on-Rails' Projekt. Ist das nur etwas für den internen Gebrauch, oder wird es da auch öffentliche Software geben? Was benutzt du unter RoR um iCal/vCard zu generieren / zu parsen? Gruss, Helge
on 2009-06-30 12:21
Das 'CalDAV-on-Rails' Projekt ist der Grundstein für ein größeres Projekt. Im derzeitigen. sehr frühen Entwicklungsstadium ist es erstmal nicht öffentlich. Da ich aber ein sehr großer Freund von OpenSource bin, wird zumindest der CalDAV Teil des Projektes in absehbarer Zukunft unter eine entsprechende Lizenz gestellt und auch öffentlich entwickelt. Habe mich bis jetzt noch nicht mit dem Parsing des iCalendar Formates beschäftigt, es scheint aber mehrere Bibliotheken zu geben, die diese Funktionalität bieten. Kannst Du mir eine empfehlen, oder lohnt es sich eher über eine Eigenentwicklung nach zu denken? Falls Du daran interessiert bist bei der Entwicklung des CalDAV on Rails Projektes mit zu wirken, können wir uns gerne mal darüber unterhalten. Matthias Helge Heß schrieb:
on 2009-06-30 12:28
Matthias Lindhorst wrote: > Das 'CalDAV-on-Rails' Projekt ist der Grundstein f�r ein gr��eres Projekt. > Im derzeitigen. sehr fr�hen Entwicklungsstadium ist es erstmal nicht > �ffentlich. OK. > Da ich aber ein sehr gro�er Freund von OpenSource bin, wird zumindest > der CalDAV Teil des Projektes in absehbarer Zukunft unter eine > entsprechende Lizenz gestellt und auch �ffentlich entwickelt. Klingt gut. > Kannst Du mir eine empfehlen, oder lohnt es sich eher �ber eine > Eigenentwicklung nach zu denken? Kann ich bzgl Ruby nichts zu sagen. > Falls Du daran interessiert bist bei der Entwicklung des CalDAV on Rails > Projektes mit zu wirken, k�nnen wir uns gerne mal dar�ber unterhalten. Ich helfe gerne mit sachdienlichen CalDAV Informationen, an der Ruby Entwicklung selbst werde ich aber nicht mitwirken ;-) Gruss, Helge PS: mehr zum Thema dann wohl am besten via me-at-helgehess-eu.
on 2009-06-30 16:34
vielleicht helfen diese beiden posts ja weiter: http://blog.funkensturm.de/2008/02/10/finally-railsicalendar-ical-ics-publish-with-ruby-on-rails/ http://blog.funkensturm.de/2009/06/08/funkenrailsdav-webdav-with-rails-eg-for-ical/ Gruß Manuel Am 30.06.2009 um 12:20 schrieb Matthias Lindhorst:
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.