How to test server-sent-events with REST-Assured? - rest-assured

How can I test a sever sent events endpoint with REST-Assured?
I have tried the following, but the test doesn't terminate:
val stream = RestAssured.given()
.contentType(MediaType.SERVER_SENT_EVENTS)
.get("/status/stream").asInputStream()
myService.publish(SomeEvent())
val line = stream.reader().readText()
stream.close()
assertEquals("my-event", line)
myService.publish() pushes an object as the data payload to the SSE stream, which is validated by another test.
The assertion here is only exemplary. The problem is how to receive data from the stream.

You can read SSE urls with javax.ws.rs.sse.SseEventSource.

Related

Access session value in gatling checks

I use gatling to send data to an ActiveMQ. The payload is generated in a separate method. The response should also be validated. However, how can I access the session data within the checks
check(bodyString.is()) or simpleCheck(...)? I have also thought about storing the current payload in a separate global variable, but I don't know if this is the right approach. My code's setup looks like this at the moment:
val scn = scenario("Example ActiveMQ Scenario")
.exec(jms("Test").requestReply
.queue(...)
.textMessage{ session => val message = createPayload(); session.set("payload", payload); message}
.check(simpleCheck{message => customCheck(message, ?????? )})) //access stored payload value, alternative: check(bodystring.is(?????)
def customCheck(m: Message, string: String) = {
// check logic goes here
}
Disclaimer: providing example in Java as you don't seem to be a Scala developper, so Java would be a better fit for you (supported since Gatling 3.7).
The way you want to do things can't possibly work.
.textMessage(session -> {
String message = createPayload();
session.set("payload", payload);
return message;
}
)
As explained in the documentation, Session is immutable, so in a function that's supposed to return the payload, you can't also return a new Session.
What you would have to do it first store the payload in the session, then fetch it:
.exec(session -> session.set("payload", createPayload()))
...
.textMessage("#{payload}")
Regarding writing your check, simpleCheck doesn't have access to the Session. You have to use check(bodyString.is()) and pass a function to is, again as explained in the documentation.

How to parse attachment values with strongGrid inbound webhook

Hello there I have setup successfully inbound webhook with strongGrid in net core 3.1.
The endpoint gets called and I want to parse value inside the attachment which is csv file.
The code I am using is following
var parser = new WebhookParser();
var inboundEmail = await parser.ParseInboundEmailWebhookAsync(Request.Body).ConfigureAwait(false);
await _emailSender.SendEmailAsyncWithSendGrid("info#mydomain.com", "ParseWebhook1", inboundEmail.Attachments.First().Data.ToString());
Please note I am sending an email as I don t know how to debug webhook with sendgrid as I am not aware of any cli.
but this line apparently is not what I am looking for
inboundEmail.Attachments.First().Data.ToString()
I am getting this on my email
Id = a3e6a543-2aee-4ffe-a36a-a53k95921998, Tag = HttpMultipartParser.MultipartFormDataParser.ParseStreamAsync, Length = 530 bytes
the csv I need to parse has 3 fields Sku productname and quantity I'd like to get sku values.
Any help would be appreciated.
The .Data property contains a Stream and invoking ToString on a stream object does not return its content. The proper way to read the content of a stream in C# is something like this:
var streamReader = new StreamReader(inboundEmail.Attachments.First().Data);
var attachmentContent = await streamReader.ReadToEndAsync().ConfigureAwait(false);
As far as parsing the CSV, there are literally thousands of projects on GitHub and hundreds on NuGet with the keyword 'CSV'. I'm sure one of them will fit your needs.

Twitter API v2 Streaming with Retrofit or OkHttp

I am trying integrate the new Twitter API specifically the streaming tweets part in my android app, I am using Retrofit for my http calls.
When I try to make the call to get the streaming tweets it just hangs and does not return anything.
this is my retrofit call
#Streaming
#GET("tweets/search/stream")
suspend fun getFilteredStream(#Header("Authorization") token:String)
I then tried making a call with just OkHttp as shown in the documentation I get a successful response but I dont know how to stream the data.
I can make the call successfully via a curl call and see the data no problem.
How do I stream the data via retrofit or OkHttp
Update:
With OkHttp I was able to get data by doing this
val client: OkHttpClient = OkHttpClient().newBuilder()
.build()
val request: Request = Request.Builder()
.url("https://api.twitter.com/2/tweets/search/stream")
.method("GET", null)
.build()
val response: Response = client.newCall(request).execute()
val source = response.body?.source()
val buffer = Buffer()
while(!source!!.exhausted()){
response.body?.source()?.read(buffer, 8192)
val data = buffer.readString(Charset.defaultCharset())
}
data holds the string data representation of multiple tweet objects but how do I read one tweet at a time, or parse the response like this?
From the docs, I think you'll need to combine the two examples you have.
https://github.com/square/retrofit/blob/108fe23964b986107aed352ba467cd2007d15208/retrofit/src/main/java/retrofit2/http/Streaming.java
Treat the response body on methods returning {#link ResponseBody ResponseBody} as is, i.e. without converting the body to {#code byte[]}.
And example calling code
https://github.com/square/retrofit/blob/108fe23964b986107aed352ba467cd2007d15208/retrofit/src/test/java/retrofit2/CallTest.java#L599
I suspect, dependending on the JSON API you use you may be able to use a Streaming API from the response body. But if not you could split on either just newline or newline followed by { on next line and parse individually. Sorry I can't help here.
See https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON

Batch delete SQS messages after batch receiving in boto3

I am using boto3 to receive_message() in batches. This returns a dict item as specified in the boto3 documentation.
After receiving the batch of message, I process them one by one and want to batch delete them after they are all processed. I do not want to delete them one by one after processing each single item.
The delete_message_batch() function has a slightly different syntax than the response from the receive_message() function, so I need to reformat the response dict from receive_message() into a suitable format (only using Id and ReceiptHandle).
Is there any easier way to directly use the response from receive_message() for batch deletion?
Here is how I handle the messages. I create a list with the ids and the receipt handles. The ids are not mandatory, you could insert the output of range(10). Also, there is no error checking so you need to take care of that.
response = SQS.receive_message(
QueueUrl=queue_url,
AttributeNames=[],
MaxNumberOfMessages=10,
MessageAttributeNames=['All'],
)
delete_batch = []
for message in response.get('Messages') or []:
# do stuff with each message
delete_batch.append(
{'Id': message['MessageId'], 'ReceiptHandle': message['ReceiptHandle']}
)
if delete_batch:
SQS.delete_message_batch(QueueUrl=queue_url, Entries=delete_batch)
In Boto3 you can use the Queue resource to delete batches of messages in one call. Here's some code (from a larger example in GitHub) that shows how:
import logging
import boto3
from botocore.exceptions import ClientError
logger = logging.getLogger(__name__)
sqs = boto3.resource('sqs')
def delete_messages(queue, messages):
"""
Delete a batch of messages from a queue in a single request.
:param queue: The queue from which to delete the messages.
:param messages: The list of messages to delete.
:return: The response from SQS that contains the list of successful and failed
deletions.
"""
try:
entries = [{
'Id': str(ind),
'ReceiptHandle': msg.receipt_handle
} for ind, msg in enumerate(messages)]
response = queue.delete_messages(Entries=entries)
if 'Successful' in response:
for msg_meta in response['Successful']:
logger.info("Deleted %s", messages[int(msg_meta['Id'])].receipt_handle)
if 'Failed' in response:
for msg_meta in response['Failed']:
logger.warning(
"Could not delete %s",
messages[int(msg_meta['Id'])].receipt_handle
)
except ClientError:
logger.exception("Couldn't delete messages from queue %s", queue)
else:
return response
queue = sqs.get_queue_by_name(QueueName=name)
messages = queue.receive_messages(
MessageAttributeNames=['All'],
MaxNumberOfMessages=max_number,
WaitTimeSeconds=wait_time
)
delete_messages(queue, messages)
There is also an option to purge the queue. Not sure if it will fit your use case but here is the reference:
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sqs.html#SQS.Queue.purge
and the code example:
import boto3
REGION_NAME = 'us-east-01'
QUEUE_NAME = 'my-queue01-example'
sqs = boto3.resource('sqs', REGION_NAME)
queue = sqs.get_queue_by_name(QueueName=QUEUE_NAME)
response = queue.purge()

How to get Response from another channel in mirth

We have two channels called channelA and channelB.
In channelA we have two destinations
a. first destination will invoke the channelB with XML data as input and get the response from the channelB in XML format.
b. retrieve the response of first destination in xml format and process it.
var dest1 = responseMap.get("destination1");
var resMessage = dest1.getMessage();
I am getting channelB response as "Message routed successfully".
How I will get actual XML from channelB instead of "Message routed successfully" message.
We are doing above steps to define generic channels such that we can reuse it in different scenarios in the mirth application.
We using mirth 2.2.1.5861 version.
We are doing something very similar to what you described. In our case, destination1 is a SOAP sender (SOAP uses XML for its send and receive envelopes). Here's the syntax we are successfully using in destination2 JavaScript Writer:
var dest1 = responseMap.get("destination1");
var resMessage = dest1.getStatus().toString();
if (resMessage == "SUCCESS")
{
var stringResponse = dest1.getMessage();
channelMap.put('stringResponse',stringResponse);
var xmlResponse = new XML(stringResponse);
// use e4x notation to parse xmlResponse
}
If your destination1 is not a SOAP sender, then the XML response from channelB might be getting packaged up in some way that you need to extract from "stringResponse." You can see the contents of the channelMap variable "stringResponse" after running the message through the channel. Go to the dashboard, double-click the channel, find a message that has been sent, and then look at the mappings tab. What does the content of "stringResponse" actually look like? Is it just "Message routed successfully?" Or is that text followed by the XML that you're after?
Create ChannelB having source data type as an XML, and put source as a channel reader.
You have to make a single destination on ChannelA as a Channel Writer, and put ChannelB in the details.
This way whatever message you get in the form of an XML in ChannelAwill be routed to ChannelB.

Resources