Ask a Question

GetHeader and multiple same key

SOLVED
BenoitB
Community Hero

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 ?

 

 

 

 

 

Un sourire et ça repart

9 REPLIES 9
AlexKaras
Champion Level 2

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.

 

Regards,
  /Alex [Community Champion]
____
[Community Champions] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Champions]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Champion] signature is assigned on quarterly basis and is used with permission by SmartBear Software.
https://community.smartbear.com/t5/Community-Champions/About-the-Community-Champions-Program/gpm-p/252662
================================
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;
}

Un sourire et ça repart

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).

 

Regards,
  /Alex [Community Champion]
____
[Community Champions] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Champions]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Champion] signature is assigned on quarterly basis and is used with permission by SmartBear Software.
https://community.smartbear.com/t5/Community-Champions/About-the-Community-Champions-Program/gpm-p/252662
================================

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.

 

 

 

 

Un sourire et ça repart

Hi,

 

about cleansing and tailoring of returned data

If I am correct with the expectation that

' noindex, nofollow\n\rStrict-Transport-Security: max-age=31536000'

will be returned for the X-Robots-Tag header, than this is not a cleansing case, but the case of incorrect return (more than one header is returned).

 

I would suggest to consider that by definition:

-- headers section of response is delimited by two CRLFs from the response body (if any); and

-- every header ends with one CRLF and consists of a header name, colon, space and header data (up to CRLF).

 

You may consider aqString.GetListItem() and related methods to iterate through the list of headers and then use .split(': ') to get the value.

(Or consider regular expressions... Though this may be an overkill 🙂 )

Just my suggestion...

 

Regards,
  /Alex [Community Champion]
____
[Community Champions] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Champions]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Champion] signature is assigned on quarterly basis and is used with permission by SmartBear Software.
https://community.smartbear.com/t5/Community-Champions/About-the-Community-Champions-Program/gpm-p/252662
================================

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;
}

Un sourire et ça repart

> extractKeyValueFromHeaders(aqHttpResponse.AllHeaders, "JSESSIONID")

Ah, now I got your logic... OK then 🙂

 

Regards,
  /Alex [Community Champion]
____
[Community Champions] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Champions]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Champion] signature is assigned on quarterly basis and is used with permission by SmartBear Software.
https://community.smartbear.com/t5/Community-Champions/About-the-Community-Champions-Program/gpm-p/252662
================================

I noticed that u didnt see my need (only value of the key itself) but thanks to u i improved the code to be more generic..

This is good team work 😉

 

So do u agree on my last proposal ?

Un sourire et ça repart

do u agree on my last proposal ?

Yep 🙂

 

Regards,
  /Alex [Community Champion]
____
[Community Champions] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Champions]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Champion] signature is assigned on quarterly basis and is used with permission by SmartBear Software.
https://community.smartbear.com/t5/Community-Champions/About-the-Community-Champions-Program/gpm-p/252662
================================
cancel
Showing results for 
Search instead for 
Did you mean: