Forum Discussion

BenoitB's avatar
BenoitB
Community Hero
5 years ago
Solved

GetHeader and multiple same key

I need to retrieve a cookie after a call to a Rest api.

Not a problem i thought, i'll use aqHttpResponse.GetHeader("Set-Cookie");

But how to retrieve the wanted one if multple Set-Cookie are in the response ?

 

All headers sent back:

Connection: keep-alive
Date: Mon, 16 Mar 2020 15:36:13 GMT
Content-Length: 3235
Content-Type: text/html;charset=UTF-8
Server: nginx
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Sun, 15-Mar-2020 15:36:13 GMT
Set-Cookie: JSESSIONID=E525712AB14D70C27C8C13F4F063A5B3; Path=/; Secure; HttpOnly
X-Robots-Tag: noindex, nofollow
Strict-Transport-Security: max-age=31536000

 

I want the JSESSIONID

 

If i use the GetHeader i have ony the  rememberMe.

 

I know that a solution is aqHttpResponse.AllHeaders and i parse it to find my JSESSIONID but is there any simplier and more elegant solution to achieve that ?

 

 

 

 

 

  • BenoitB's avatar
    BenoitB
    5 years ago

    So it's bullet-proof working now ...

     

    On same headers, call of extractKeyValueFromHeaders(aqHttpResponse.AllHeaders, "JSESSIONID")

    returns

    "5119F6E864B904735B8870DA08215BCD"


    Call of extractKeyValueFromHeaders(aqHttpResponse.AllHeaders, "JSESSIONID", true)

    returns

    "JSESSIONID=5119F6E864B904735B8870DA08215BCD; Path=/; Secure; HttpOnly"

     

    The revised code is (algorithm working, optimization possible) :

    function extractKeyValueFromHeaders(Headers = "", Key = "", AllValues = false) {
      if (Headers == "")
        throw Error("extractKeyValueFromHeaders() - Header is empty");
      if (Key == "")
        throw Error("extractKeyValueFromHeaders() - Key is missing");
      let headerValue = "";
      Headers = Headers.replace(/\r/g, '');
      let data = Headers.split("\n");
      let pos1, pos2, len;
      for (let i = 0; i < data.length; i++) {
        if (data[i] != "") {
          pos1 = aqString.Find(data[i], ":");
          if (pos1 != -1) {
            pos1 = aqString.Find(data[i], Key, pos1);
            if (pos1 != -1) {
              if (AllValues) {
                pos2 = data[i].length;
                len = pos1;  
              }
              else {
                pos2 = aqString.Find(data[i], ";", pos1);
                if (pos2 == -1)
                  pos2 = data[i].length;
                len = pos1 + Key.length + 1;  
              }
              headerValue = data[i].substr(len, pos2 - len);
              break;
            }  
          }
        }
      }
      return headerValue;
    }

9 Replies

  • AlexKaras's avatar
    AlexKaras
    Champion Level 3

    Hi,

     

     is there any simplier and more elegant solution to achieve that ?

    Nothing exept this is documented, so I think .AllHeaders is the only way to go.

     

  • BenoitB's avatar
    BenoitB
    Community Hero

    Ok, thanks for confirmation.

     

    So i do the needed function, hope it can help others :

     

    /**
     *  Get a specific header value
     *  @author Biache Benoit
     *  @memberof webtools
     *  @function
     *  @param {string} Headers - The data of the http response headers (usually the <i>aqHttpResponse.AllHeaders</i>)
     *  @param {string} Key - The key to look value for
     *  @returns {string} Return empty string if <i>Key</i> not found or the value of <i>Key</i><br>
     *  If no headers nor key are valid an exception is throw.
     */
    function extractKeyValueFromHeaders(Headers = "", Key = "") {
      if (Headers == "")
        throw Error("extractKeyValueFromHeaders() - Header is empty");
      if (Key == "")
        throw Error("extractKeyValueFromHeaders() - Key is missing");
      let headerValue = "";
      let pos1        = aqString.Find(Headers, Key, 0, true);
      if (pos1 != -1) {
        let pos2 = aqString.Find(Headers, ";", pos1, true);
        // The ';' could be missing if it's last value
        // In this case (last value) the caller must clean the value of \r and \n that can be returned
        if (pos2 == -1)
          pos2 = Headers.length;
        // Dont forget the '='
        let len     = pos1 + Key.length + 1;  
        headerValue = Headers.substr(len, pos2 - len);
      }  
      return headerValue;
    }
    • AlexKaras's avatar
      AlexKaras
      Champion Level 3

      Hi,

       

      I did not execute your code but I hope that it works for you.

      Nevertheless, my doubts from just skimming your code:

      -- Does it work for your case when you are looking for the second instance of Set-Cookie header?

      -- The code searches for ';' as a delimiter, so

        -- for Set-Cookie I expect that it will return just ' rememberMe=deleteMe' (note the space at the start) and will lose Path, Max-Age and all other cookie's fields;

        -- For any other header that does not contain ';' in its value, the result will contain extra characters (for example, for the X-Robots-Tag header I expect ' noindex, nofollow\n\rStrict-Transport-Security: max-age=31536000' to be returned).

       

      • BenoitB's avatar
        BenoitB
        Community Hero

        It works very well for my current need (single value) but you get the point !

         

        Need to make a split instead and then loop into the array to find what we need. I'll post a new revision later.

         

        But about cleansing and tailoring of returned data, it's caller responsability because we don't know in advance what the caller need exactly.