{"id":117,"date":"2019-02-26T22:49:17","date_gmt":"2019-02-26T22:49:17","guid":{"rendered":"http:\/\/buki.io\/?p=117"},"modified":"2019-02-27T00:15:29","modified_gmt":"2019-02-26T23:15:29","slug":"building-a-caldav-client-with-web-components","status":"publish","type":"post","link":"http:\/\/buki.io\/?p=117","title":{"rendered":"Building a CalDAV client with web components"},"content":{"rendered":"<p>Some steps and pitfalls on my way creating a CalDAV client with webcomponents<br \/>\n1. If you want to use moment.js include it this way<br \/>\nimport moment from &#8218;moment&#8216;; window.moment = moment;\u00a0<br \/>\n2. The template for the \u201eREPORT\u201c request should look like this, e.g. to get the events for a time range. Mind, there MUST NOT BE any whitespace between the backtick and the start of the xml declaration.<br \/>\nconst query = (start,end) => `<?xml version=\"1.0\" encoding=\"utf-8\" ?> <c:calendar-query xmlns:c=\"urn:ietf:params:xml:ns:caldav\"> \u00a0 <d:prop xmlns:d=\"DAV:\"> \u00a0 \u00a0 <d:getetag\/> \u00a0 \u00a0 <c:calendar-data\/> \u00a0 <\/d:prop> \u00a0 <c:filter> \u00a0 \u00a0 <c:comp-filter name=\"VCALENDAR\"> \u00a0 \u00a0 \u00a0 <c:comp-filter name=\"VEVENT\"> \u00a0 \u00a0 \u00a0 \u00a0 <c:time-range \u00a0start=\"${start}\" end=\"${end}\"\/> \u00a0 \u00a0 \u00a0 <\/c:comp-filter> \u00a0 \u00a0 <\/c:comp-filter> \u00a0 <\/c:filter> <\/c:calendar-query> `;<br \/>\n3. I had to start Chrome like this to get rid of CORS issues<br \/>\nopen -a Google Chrome &#8211;args &#8211;disable-web-security &#8211;user-data-dir=\u201e&#8220;<br \/>\n4. The fetch request should look like this<br \/>\n \u00a0\tlet start = moment().subtract(5,&#8217;days&#8216;); \u00a0 \u00a0 \u00a0 \u00a0 let end = moment(); \u00a0 \u00a0 \u00a0 \u00a0 let startString = \u00a0start.format(&#8222;YYYYMMDD[T]000000[Z]&#8220;); \u00a0 \u00a0 \u00a0 \u00a0 let endString = end.format(&#8222;YYYYMMDD[T]000000[Z]&#8220;); \u00a0 \u00a0 \u00a0 \u00a0 let myHeaders = new Headers(); \u00a0 \u00a0 \u00a0 \u00a0 myHeaders.append(&#8222;DEPTH&#8220;,&#8220;1&#8243;); \u00a0 \u00a0 \u00a0 \u00a0 myHeaders.append(&#8222;Authorization&#8220;,&#8220;Basic &#8220; + authentication);<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 console.log(&#8218;caldaving&#8216;, startString,endString)<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 fetch(url,{ \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 method: &#8222;REPORT&#8220;, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 headers : myHeaders, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 body : query(startString,endString) \u00a0 \u00a0 \u00a0 \u00a0 }) \u00a0 \u00a0 \u00a0 \u00a0 .then(response => { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 console.log(&#8222;reso&#8220;, response) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 let xml = response.text(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 console.log(&#8218;Got appointments&#8216;, xml); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return xml; \u00a0 \u00a0 \u00a0 \u00a0 }).then(xml => console.log(&#8218;xml&#8216;,xml))<br \/>\n5. To get the authentication as base64 use \u201e echo -n user:password | base64\u201c Mind the \u201e-n\u201c otherwise you get a line break at the end!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some steps and pitfalls on my way creating a CalDAV client with webcomponents 1. If you want to use moment.js include it this way import moment from &#8218;moment&#8216;; window.moment = moment;\u00a0 2. The template for the \u201eREPORT\u201c request should look like this, e.g. to get the events for a time range. Mind, there MUST NOT &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/buki.io\/?p=117\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8222;Building a CalDAV client with web components&#8220;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[3],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7N2pi-1T","_links":{"self":[{"href":"http:\/\/buki.io\/index.php?rest_route=\/wp\/v2\/posts\/117"}],"collection":[{"href":"http:\/\/buki.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/buki.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/buki.io\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/buki.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=117"}],"version-history":[{"count":0,"href":"http:\/\/buki.io\/index.php?rest_route=\/wp\/v2\/posts\/117\/revisions"}],"wp:attachment":[{"href":"http:\/\/buki.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=117"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/buki.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=117"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/buki.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=117"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}