https://saxonica.plan.io/https://saxonica.plan.io/favicon.ico2020-02-25T11:25:38ZSaxonica Developer CommunitySaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=149422020-02-25T11:25:38ZO'Neil Delprattoneil@saxonica.com
<ul><li><strong>Status</strong> changed from <i>New</i> to <i>AwaitingInfo</i></li></ul><p>Hi,</p>
<p>Due to cross-site scripting restrictions the ixsl:schedule-action/@http-request feature will not allow you to access third-party sites to retrieve XML.</p>
<p>Implementing ixsl:schedule-action and HTTP requests in Saxon-EE is not something we need as the doc function can be used for simple URLs.</p>
<p>Possible workarounds in the browser:</p>
<ol>
<li>
<p>Configuring your server to allow the access of third-party sites (XSS), but this is not advised due to security issues.</p>
</li>
<li>
<p>Proxy the third-party sites access via your server. You could in fact use Saxon on the server-side with some server like Servlex to process the HTTP request and use the doc function with simple URLs to retrieve the XML document which then can be sent back to the client using Saxon-JS ixsl:schedule-action/@http-request feature.</p>
</li>
<li>
<p>If the third-party sites allows you to return the data as JSON instead of XML with Saxon-JS you could use the function json-doc from the client-side stylesheet. JSON is exempt from the XSS rules. You can convert the JSON to a map in the XSLT.</p>
</li>
</ol> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=149432020-02-25T12:00:11ZMark Dunnmark.dunn@oup.com
<ul></ul><p>Thanks O'Neil, that's helpful.</p>
<p>I'm not going to try and get around the security issues!</p>
<p>The doc() function will work with the CrossRef API, but other APIs work differently.</p>
<p>For example, Web of Science requires authentication via a HTTP header 'Authorization', which returns a session ID.</p>
<p>Then, a WoS API request requires an HTTP header 'Cookie' with the session ID.</p>
<p><a href="http://wokinfo.com/media/pdf/WebServicesLiteguide.pdf" class="external">http://wokinfo.com/media/pdf/WebServicesLiteguide.pdf</a></p>
<p>So I think we need more than the doc() function to access the WoS API.</p>
<p>EXPath looks like it has a feature for this - <a href="http://expath.org/modules/http-client/" class="external">http://expath.org/modules/http-client/</a> - but it looks like this is not implemented in Saxon-EE</p> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=149452020-02-25T12:39:11ZMichael Kaymike@saxonica.com
<ul></ul><p>Also relevant is CORS, see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external">https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS</a> which ought to work with Saxon-JS but I don't think we've actually tried it.</p> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=149462020-02-25T12:41:52ZMichael Kaymike@saxonica.com
<ul></ul><p>As regards the question,</p>
<p><em>Is it feasible to include ixsl:schedule-action and HTTP requests in Saxon-EE? (so I'm not tied to using a browser for this)</em></p>
<p>The answer is yes, it's feasible, but it's significant effort (mainly testing effort). I think we would initially do synchronous HTTP requests only.</p> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=149472020-02-25T12:44:25ZMark Dunnmark.dunn@oup.com
<ul></ul><p>Thanks Michael - if it helps, it's the HTTP request (with headers) that I'm interested in, not the asynchronous-ness (-nosity?)</p> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=149482020-02-25T13:13:37ZMark Dunnmark.dunn@oup.com
<ul></ul><p>Had a quick go at submitting a "preflight" request:</p>
<pre><code class="xml syntaxhl" data-language="xml"><span class="nt"><xsl:variable</span> <span class="na">name=</span><span class="s">"http-preflight-headers"</span> <span class="na">as=</span><span class="s">"map(*)"</span><span class="nt">></span>
<span class="nt"><xsl:map></span>
<span class="nt"><xsl:map-entry</span> <span class="na">key=</span><span class="s">"'Access-Control-Request-Method'"</span> <span class="na">select=</span><span class="s">"'GET'"</span><span class="nt">/></span>
<span class="nt"><xsl:map-entry</span> <span class="na">key=</span><span class="s">"'Access-Control-Request-Headers'"</span> <span class="na">select=</span><span class="s">"'Content-Type'"</span><span class="nt">/></span>
<span class="nt"><xsl:map-entry</span> <span class="na">key=</span><span class="s">"'Origin'"</span> <span class="na">select=</span><span class="s">"'http://127.0.0.1'"</span><span class="nt">/></span>
<span class="nt"></xsl:map></span>
<span class="nt"></xsl:variable></span>
<span class="nt"><xsl:variable</span> <span class="na">name=</span><span class="s">"http-preflight"</span> <span class="na">as=</span><span class="s">"map(*)"</span><span class="nt">></span>
<span class="nt"><xsl:map></span>
<span class="nt"><xsl:map-entry</span> <span class="na">key=</span><span class="s">"'method'"</span> <span class="na">select=</span><span class="s">"'OPTIONS'"</span><span class="nt">/></span>
<span class="nt"><xsl:map-entry</span> <span class="na">key=</span><span class="s">"'href'"</span> <span class="na">select=</span><span class="s">"'https://doi.crossref.org'"</span><span class="nt">/></span>
<span class="nt"><xsl:map-entry</span> <span class="na">key=</span><span class="s">"'headers'"</span> <span class="na">select=</span><span class="s">"$http-preflight-headers"</span><span class="nt">/></span>
<span class="nt"></xsl:map></span>
<span class="nt"></xsl:variable></span>
<span class="nt"><ixsl:schedule-action</span> <span class="na">http-request=</span><span class="s">"$http-preflight"</span><span class="nt">></span>
<span class="nt"><xsl:call-template</span> <span class="na">name=</span><span class="s">"handle-preflight-response"</span><span class="nt">/></span>
<span class="nt"></ixsl:schedule-action></span>
<span class="nt"><xsl:template</span> <span class="na">name=</span><span class="s">"handle-preflight-response"</span><span class="nt">></span>
<span class="nt"><xsl:context-item</span> <span class="na">as=</span><span class="s">"map(*)"</span> <span class="na">use=</span><span class="s">"required"</span><span class="nt">/></span>
<span class="nt"><xsl:message></span>HTTP response status: <span class="nt"><xsl:sequence</span> <span class="na">select=</span><span class="s">"serialize(?status)"</span><span class="nt">/></xsl:message></span>
<span class="nt"><xsl:message></span>HTTP response headers: <span class="nt"><xsl:sequence</span> <span class="na">select=</span><span class="s">"serialize(?headers)"</span><span class="nt">/></xsl:message></span>
<span class="nt"></xsl:template></span>
</code></pre>
<p>Got some new error messages, reported by Saxon-JS:</p>
<p>Attempt to set a forbidden header was denied: Origin
Attempt to set a forbidden header was denied: Access-Control-Request-Headers
Attempt to set a forbidden header was denied: Access-Control-Request-Method</p> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=152362020-04-12T20:19:28ZDavid Priest
<ul></ul><p>From the research I've been doing re: the same issue, there's no need to do the preflight: your browser will do it automatically when you submit a "complex" request. See: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external">https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS</a></p> SaxonJS - Feature #4464: Calling 3rd-party API using ixsl:schedule-action/@http-requesthttps://saxonica.plan.io/issues/4464?journal_id=176962021-03-31T18:48:17ZMichael Kaymike@saxonica.com
<ul><li><strong>Project</strong> changed from <i>Saxon</i> to <i>SaxonJS</i></li><li><strong>Status</strong> changed from <i>AwaitingInfo</i> to <i>Closed</i></li></ul><p>Closing this as a result of the passage of time. Improvements to ixsl:schedule-action are on the Saxon-JS roadmap.</p>