Calling 3rd-party API using ixsl:schedule-action/@http-request
Fix Committed on JS Branch:
The task I have is to update bibliographic references in an XML document with identifiers sourced from third party databases (e.g. CrossRef DOIs).
I thought Saxon-JS could be used to achieve this using just XSLT, by
- building an HTTP request map from a bib reference
- using ixsl:schedule-action/@http-request, parsing the response,
- incorporating the result back into the bib reference.
But when I attempt this, I get an error in the browser "Cross-Origin Request Blocked". Because the HTTP request feature is only available in Saxon-JS, I have to run the code (attached) in a browser, which spots that the server running the code is trying to scrape data from another server, and blocks this action.
So my questions are:
- Have I missed a parameter of some kind that would make this work?
- 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)
- Or is the COR security issue a fundamental obstacle to making this work?
- Status changed from New to AwaitingInfo
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.
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.
Possible workarounds in the browser:
Configuring your server to allow the access of third-party sites (XSS), but this is not advised due to security issues.
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.
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.
Thanks O'Neil, that's helpful.
I'm not going to try and get around the security issues!
The doc() function will work with the CrossRef API, but other APIs work differently.
For example, Web of Science requires authentication via a HTTP header 'Authorization', which returns a session ID.
Then, a WoS API request requires an HTTP header 'Cookie' with the session ID.
So I think we need more than the doc() function to access the WoS API.
EXPath looks like it has a feature for this - http://expath.org/modules/http-client/ - but it looks like this is not implemented in Saxon-EE
As regards the question,
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)
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.
Thanks Michael - if it helps, it's the HTTP request (with headers) that I'm interested in, not the asynchronous-ness (-nosity?)
Had a quick go at submitting a "preflight" request:
<xsl:variable name="http-preflight-headers" as="map(*)">
<xsl:map-entry key="'Access-Control-Request-Method'" select="'GET'"/>
<xsl:map-entry key="'Access-Control-Request-Headers'" select="'Content-Type'"/>
<xsl:map-entry key="'Origin'" select="'http://127.0.0.1'"/>
<xsl:variable name="http-preflight" as="map(*)">
<xsl:map-entry key="'method'" select="'OPTIONS'"/>
<xsl:map-entry key="'href'" select="'https://doi.crossref.org'"/>
<xsl:map-entry key="'headers'" select="$http-preflight-headers"/>
<xsl:context-item as="map(*)" use="required"/>
<xsl:message>HTTP response status: <xsl:sequence select="serialize(?status)"/></xsl:message>
<xsl:message>HTTP response headers: <xsl:sequence select="serialize(?headers)"/></xsl:message>
Got some new error messages, reported by Saxon-JS:
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
- Project changed from Saxon to SaxonJS
- Status changed from AwaitingInfo to Closed
Closing this as a result of the passage of time. Improvements to ixsl:schedule-action are on the Saxon-JS roadmap.
Please register to edit this issue
Also available in: Atom