Wednesday, 6 June 2018

Resolve Curls double header when requesting from a digest authentication source in an xslt pipeline

When using curl to make a request against a source that uses digest authentication the response will contain a double header, the first is a 401 response followed by the actual response of the request. This is because using the --digest flag with curl, the request will firstly return a 401 to get the nonce etc to be able to do the second request that would get the real data.

A sample request would be something like:

curl --digest -u user:pw --dump-header headers.txt

An example of the response from such a request is shown below:

HTTP/1.1 401 Unauthorized
Server: MarkLogic
WWW-Authenticate: Digest realm="public", qop="auth", nonce="563c5b25a3dbad7b6aa54cdc7dc0d294", opaque="56e3687fefa06c25"
Content-Type: text/html; charset=utf-8
Content-Length: 209
Connection: Keep-Alive
Keep-Alive: timeout=5

HTTP/1.1 200 OK
Server: MarkLogic
Content-Type: application/xml; charset=UTF-8
Content-Length: 175
Connection: Keep-Alive
Keep-Alive: timeout=5

When this is a part of an xml/xslt workflow then which makes use of the header file that is returned then the following code will resolve to the correct header with the following considerations:

  • This is merely a code snippet that requires to be employed within an xslt stylesheet
  • The code makes use of functions from the library (xmlns:functx="")
  • The $actualHeader variable is the header that is required

<xsl:variable name="unparsedText"  select="unparsed-text(resolve-uri('headers.txt', resolve-uri('mydir', static-base-uri())))"/>
<xsl:variable name="actualHeader"  
  select="if (tokenize($unparsedText, 'HTTP')[3]) then 
       substring($unparsedText, functx:index-of-string-last($unparsedText,'HTTP')) 
   else $unparsedText"/>

<xsl:function name="functx:index-of-string-last" as="xs:integer?">
  <xsl:param name="arg" as="xs:string?"/>
  <xsl:param name="substring" as="xs:string"/>

  <xsl:sequence select="
  functx:index-of-string($arg, $substring)[last()]


<xsl:function name="functx:index-of-string" as="xs:integer*">

  <xsl:sequence select="
  if (contains($arg, $substring))
  then (string-length(substring-before($arg, $substring))+1,
        for $other in
           functx:index-of-string(substring-after($arg, $substring),
          $other +
          string-length(substring-before($arg, $substring)) +
  else ()