Hi,
This is related to my other 'cookie' post - but that other post has side tracked onto another issue I need to solve - so I've created a second post with a specific issue.
A while back @nmrao created the script assertion below to extract the 'Set-Cookie' http header values and write them to corresponding 'Cookie' http headers, so if 4 'Set-Cookie' headers are included on the initial request, 4 'Cookie' headers with the relevant values (including all the additional header value attributes) are added to the nextStep.
//Courtesy of Rao
//This script assetion reads the http response, //collect the cookies for the next http request //Provide the next step name where you want to set the Cookie to the request or //Use property expansion for below def nextStepName = 'REST Request' def nextRequest = context.testCase.testSteps[nextStepName].httpRequest def headers = nextRequest.requestHeaders if (messageExchange.responseHeaders.containsKey('Set-Cookie')) { log.info "Found Cookie in the response headers" def cookiez = messageExchange.responseHeaders['Set-Cookie'].value def list = [] cookiez.each { cookies -> //def (name, value) = cookies.toString().split('=',2) list.add(cookies.toString()) } headers['Cookie'] = list } else { log.warn "Not Found Cookie in the response headers" } nextRequest.requestHeaders =
The above is great - exactly what I was told I needed - however, what the developers have now told me is that what I need is slighlty different from the above - despite them saying the above gave me what I need! aah! frustrating!
The http Set-Cookie/Cookie theory (according to the following links (link1 and link2) indicates that the 'Set-Cookie' header values (without the additional attributes) are used to populate the follow up single Cookie header value.
so if we receive in the initial message
Set-Cookie: returnurl=345678; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly Set-Cookie: authtype=234567; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly Set-Cookie: state=123456; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly Set-Cookie: nonce=456789; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly
The follow up request would have ONE individual 'Cookie' http header and the value would be made up of the semi colon delimited Set-Cookie values without the additional attributes - so the follow up message's 'Cookie' header would appear as follows:
Cookie: returnurl=345678; authtype=234567; state=123456; nonce=456789
Apparently what I've described above is standard http Set-Cookie/Cookie handling and I was told I should've known about this already!
I'm stuck updating the script.
Essentially I need to concatenate all the Set-Cookie header VALUES into a single string (semi colon delimiter for each value) - but strip out the additional attributes like Max-Age, Expires, http, secure etc.
Can anyone help out? I know I'm asking a lot here - especially when everyone's already helped so much already
I need to pass the 4 'Set-Cookie' header values into the 1 'Cookie' value (stripping out all the attributes so the only the Set Cookie header values are included - apparently this is supposed to be how http 'Set-Cookie' and http 'Cookie' headers work. The server sends the Set-Cookie headers to tell the client to send a single Cookie http header and the value populating the Cookie are.
Thanks guys - really!
richie
Solved! Go to Solution.
Finally, simulated the issue.
Here you go:
def nextStepName = 'REST Request' def headerToLook = 'Set-Cookie' def headerToSet = 'Cookie' def nextRequest = context.testCase.testSteps[nextStepName].httpRequest def headers = nextRequest.requestHeaders def showHeaderCount = {msg -> log.info "Header count ${msg} is: headers.size()" } showHeaderCount('before') if (headerToSet in headers.getKeys()) { headers.remove(headerToSet) showHeaderCount('after') } if (messageExchange.responseHeaders.containsKey(headerToLook)) { log.info "Found ${headerToLook} in the response headers" def cookiez = messageExchange.getResponseHeaders().get(headerToLook) def computedValue = cookiez.collect { it.split(';').first()}.join('; ') log.info "Value for Cookie header is evaluated to : ${computedValue}" headers.put(headerToSet, computedValue) log.info 'Headers updated' nextRequest.requestHeaders = headers log.info headers } else { log.warn "Not Found ${headerToLook} in the response headers" }
You mean, below header is expected for the following request(s)?
Cookie: returnurl=345678; authtype=234567; state=123456; nonce=456789
What does it show if you add below statement after
"def cookiez = messageExchange.responseHeaders['Set-Cookie'].value"
log.info cookiez.size()
Also you may try adding below instead of "list.add(cookies.toString())"
list.add(cookies.split().first())
Hey @nmrao
exactly - the individual 'Set-Cookie' values (without the additional attribute name/values pair properties) sourced via the initial request's response are apparently concatenated into a single http 'Cookie' header which is then used in the follow up request
So using my genuine detail from a request - the RAW details for the initial response are as follows:
Set-Cookie: returnurl=881d9208ca983dcf9a2cc1971d02a8465eefd47cccdeafb751826e947204b8626f505fa6cf1e06dd9f9ceed91a8f0390dfbdf4077b308be6eb91306b6620ad2fd92d06c68387cddcc87a19c9909218dc-87b5428103f85588; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly Set-Cookie: authtype=b1a5ce49f6c1d7d0b3ccf284e38b9f377ae00744db3862e50c1a78a0c6cd2ad5-58170217357c5777; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly Set-Cookie: state=968a0b1b4944485e8d2b371d9bde404687b8bb939af05837d52c90c54844d3645b46ff6702dd6ff389e5d05d47917e6da5f2752dd5543e6cd7f4fe8e4d6c624f-707229dfb48ff182; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly Set-Cookie: nonce=2eee71dfa7b10994120ec98ffe927a47ae41d13409c484a936288463be1dc938-314d577578aaf35d; Max-Age=3600; Expires=Tue, 18-Jun-2019 22:58:30 GMT; Path=/; Secure; HttpOnly
Should generate the 'Cookie' http header for the following request as
Cookie: returnurl=881d9208ca983dcf9a2cc1971d02a8465eefd47cccdeafb751826e947204b8626f505fa6cf1e06dd9f9ceed91a8f0390dfbdf4077b308be6eb91306b6620ad2fd92d06c68387cddcc87a19c9909218dc-87b5428103f85588; authtype=b1a5ce49f6c1d7d0b3ccf284e38b9f377ae00744db3862e50c1a78a0c6cd2ad5-58170217357c5777; state=968a0b1b4944485e8d2b371d9bde404687b8bb939af05837d52c90c54844d3645b46ff6702dd6ff389e5d05d47917e6da5f2752dd5543e6cd7f4fe8e4d6c624f-707229dfb48ff182; nonce=2eee71dfa7b10994120ec98ffe927a47ae41d13409c484a936288463be1dc938-314d577578aaf35d
Am I being clear enough?
thanks guys 🙂
rich
Hey!
@nmrao adding the following
log.info cookiez.size()
immediately after
def cookiez = messageExchange.responseHeaders['Set-Cookie'].value
Returned the following:
Wed Jun 19 01:08:49 BST 2019: INFO: Found Cookie in the response headers Wed Jun 19 19:53:36 BST 2019: INFO: Found Cookie in the response headers Wed Jun 19 19:53:36 BST 2019: INFO: 4
but when I commented out
list.add(cookies.toString())
and replaced with
list.add(cookies.split().first())
I got an assertion failure on the script assertion - it was a nullpointer - I've attached the stacktrace if it helps at all.
Currently the script assertion is as follows:
//Courtesy of Rao //This script assetion reads the http response, //collect the cookies for the next http request //Provide the next step name where you want to set the Cookie to the request or //Use property expansion for below def nextStepName = 'REST Request' def nextRequest = context.testCase.testSteps[nextStepName].httpRequest def headers = nextRequest.requestHeaders if (messageExchange.responseHeaders.containsKey('Set-Cookie')) { log.info "Found Cookie in the response headers" def cookiez = messageExchange.responseHeaders['Set-Cookie'].value log.info cookiez.size() def list = [] cookiez.each { cookies -> //def (name, value) = cookies.toString().split('=',2) list.add(cookies.toString()) //list.add(cookies.split().first()) } headers['Cookie'] = list } else { log.warn "Not Found Cookie in the response headers" } nextRequest.requestHeaders = headers
Thanks guys - Im sorry I cant do anymore to help - feels a bit cheeky - but I just dont know how to proceed!
rich
Would you please try below?
def nextStepName = 'REST Request' def nextRequest = context.testCase.testSteps[nextStepName].httpRequest def headers = nextRequest.requestHeaders if (messageExchange.responseHeaders.containsKey('Set-Cookie')) { log.info "Found Cookie in the response headers" def cookiez = messageExchange.responseHeaders['Set-Cookie'].value def computedValue = [] computedValue << cookiez.flatten().collect { it.split(';').first()}.join('; ') headers['Cookie'] = computedValue } else { log.warn "Not Found Cookie in the response headers" } log.info headers nextRequest.requestHeaders = headers
Hey man - unfortunately the script assertion failed with the following snippet from the stacktrace 😞
Thu Jun 20 23:18:43 BST 2019: ERROR: Error in assertion script of the [GET Cookies] test step Thu Jun 20 23:18:43 BST 2019: ERROR: groovy.lang.MissingMethodException: No signature of method: java.lang.Character.split() is applicable for argument types: (java.lang.String) values: [;] Possible solutions: split(groovy.lang.Closure), wait(), wait(long), print(java.io.PrintWriter), plus(java.lang.Character), sprintf(java.lang.String, [Ljava.lang.Object;) groovy.lang.MissingMethodException: No signature of method: java.lang.Character.split() is applicable for argument types: (java.lang.String) values: [;] Possible solutions: split(groovy.lang.Closure), wait(), wait(long), print(java.io.PrintWriter), plus(java.lang.Character), sprintf(java.lang.String, [Ljava.lang.Object;)
I got real excited when I thought this was it - this is the last piece in my ridiculous 16 step authentication process!
As always - I really appreciate the help - feels like you're doing all the work (which you are) - so please dont think I dont appreciate what you're doing,
nice one,
richie
Finally, simulated the issue.
Here you go:
def nextStepName = 'REST Request' def headerToLook = 'Set-Cookie' def headerToSet = 'Cookie' def nextRequest = context.testCase.testSteps[nextStepName].httpRequest def headers = nextRequest.requestHeaders def showHeaderCount = {msg -> log.info "Header count ${msg} is: headers.size()" } showHeaderCount('before') if (headerToSet in headers.getKeys()) { headers.remove(headerToSet) showHeaderCount('after') } if (messageExchange.responseHeaders.containsKey(headerToLook)) { log.info "Found ${headerToLook} in the response headers" def cookiez = messageExchange.getResponseHeaders().get(headerToLook) def computedValue = cookiez.collect { it.split(';').first()}.join('; ') log.info "Value for Cookie header is evaluated to : ${computedValue}" headers.put(headerToSet, computedValue) log.info 'Headers updated' nextRequest.requestHeaders = headers log.info headers } else { log.warn "Not Found ${headerToLook} in the response headers" }
But if the 'Cookie' header is required for all following test requests (irrespective of test cases), it needs to be changed. Ignore if that is not the case.
Subject | Author | Latest Post |
---|---|---|