I am using azure-storage node module.
I would like to send JSON on my queue and get it into my queue on azure function.
I send message in queue. I stringify my message to put in queue.
// This is my service who send message to queue via node lib azure-storage
const queueMsg = {
userId,
token: tokenNotif
};
queueSvc.createMessage(Config.REGISTRATION_FCM_PUSH_NOTIFICATION_QUEUE, JSON.stringify(queueMsg), (err) => {
if (!error) {
this._logger.info(`User ${userId} has register this push notification token`);
resolve(true);
} else {
reject(false);
}
});
And in the queue function i have an error because the function think isn't a string and push the message text on xx-queue-poison
{"userId":"a6c8a103-dacc-4b15-bffd-60693105f131","token":"xxxx"}
I don't know why the quote is replaced by ASCII code on queue ?
I have tested something else!
From my service i call a Http Azure function, and this function call the Queue Storage and it's work by this way :s ..
The HttpTrigger function call queue
context.bindings.notificationQueue = [{ userId: name, token }];
And queue received data
context.log(`Received userId ${queueItem.userId} :: ${queueItem.token}`);
Why by using HttpTrigger function to QueueTrigger function it's working, but when i am using the lib "azure-storage" is not working ?
Thx
I don't know why the quote is replaced by ASCII code on queue ?
Basically the SDK is converting the string message to make it XML safe. If you look at the code in the SDK, by default it uses TextXmlQueueMessageEncoder as the message encoder. The encode function replaces " with " to make it XML safe.
From the SDK code (partial code snippets):
QueueService.prototype.createMessage = function (queue, messageText, optionsOrCallback, callback) {
var userOptions;
azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; });
validate.validateArgs('createMessage', function (v) {
v.string(queue, 'queue');
v.queueNameIsValid(queue);
v.callback(callback);
});
var xmlMessageDescriptor = QueueMessageResult.serialize(messageText, this.messageEncoder);
function TextXmlQueueMessageEncoder(){
}
util.inherits(TextXmlQueueMessageEncoder, QueueMessageEncoder);
/**
* Encode utf-8 string by escaping the xml markup characters.
* #this TextXmlQueueMessageEncoder
*
* #param {string} [input] The target to be encoded.
*
* #return {string}
*/
TextXmlQueueMessageEncoder.prototype.encode = function(input){
return input.replace(/&/gm, '&')
.replace(/</gm, '<')
.replace(/>/gm, '>')
.replace(/"/gm, '"')
.replace(/'/gm, ''');
};
One possible solution would be to convert the string to a base64 encoded string as you suggested. However if you're using the SDK to retrieve the messages, you should not see these " in your message body as the SDK takes care of decoding the message.
Related
I have an azure function which makes a promise based http post request and gets a response; now I want to send this response to a service bus and to a different event hub (the azure function is being triggered by a different event hub).
function says it has been executed successfully in the case of event hub, but no events are being sent.
In the case of service bus I am getting this error NamespaceConnectionString should not contain EntityPath.
module.exports = async function (context, eventHubMessages) {
context.log(`JavaScript eventhub trigger function called for message array ${eventHubMessages}`);
var completeData = '';
eventHubMessages.forEach((message, index) => {
context.log(`Processed message ${message}`);
completeData = message;
});
var output = '';
const axios = require('axios');
try {
const response = await axios.post('http://fake-endpoint',
{ data-json : completeData
})
context.log(`statusCode: ${response.statusCode}`);
context.log(response.data);
output += response.data;
var time = new Date().toString();
context.log('Event Hub message created at: ', time);
context.bindings.outputEventHubMessage = out;
context.bindings.outputSbMsg = out;
context.done()
return response.data; // or return a custom object using properties from response
} catch (error) {
// If the promise rejects, an error will be thrown and caught here
context.done(error);
}
};
Expected output: successful execution; data available on service bus and event hub to receive.
Actual output: Error: NamespaceConnectionString should not contain EntityPath.
As the error message says, you need to look at your connection string and remove the EntityPath variable. This is included if you copy the connection string when viewing a specific topic or queue as opposed to copying it from the main Service Bus blade.
Endpoint=sb://{servicebus-name}.servicebus.windows.net/;SharedAccessKeyName=test-queue-sender;SharedAccessKey={SharedAccessKey}=;EntityPath=test-queue;
vs
Endpoint=sb://{servicebus-name}.servicebus.windows.net/;SharedAccessKeyName=test-queue-sender;SharedAccessKey={SharedAccessKey};
I'm trying to write an azure function that supports 'retries' or future calls based on a service bus queue. It seems that the output bindings don't support any brokerProperties in the payload, is this correct or am I simply doing it wrong?
I'm able to do future calls in the queue with the following:
const azure = require('azure-sb');
const moment = require('moment');
const scheduled_time = moment().utc().add(5, 'm').format('M/D/YYYY H:mm:ss A');
const msg =
{
body: "Testing",
brokerProperties: {
ScheduledEnqueueTimeUtc: scheduled_time
}
};
sbService.sendQueueMessage(queueName, msg, function (err) {
if (err) {
console.log('Failed Tx: ', err);
} else {
console.log('Sent ' + msg);
}
});
However, simply passing the same msg object to the output binding the brokerProperties seem to be ignored. I HAVE confirmed that the function output binding works in general (properly configured).
context.done(null,
{
body: "Testing",
brokerProperties: {
ScheduledEnqueueTimeUtc: scheduled_time
}
});
Is it possible to leverage output bindings to do this or do I really need to add azure-sb and all this code for such a simple parameter? Is there a better way to call an azure function in the future?
The Node SDK docs don't even include ScheduledEnqueueTimeUtc property so it's been impossible to find any info in the docs.
It is does not seems to be supported ATM, see this Github Issue:
Enhancement: Add Scheduled Queue Messages to Service Bus Binding Documentation
I have an Azure Function that I have configured that listens for incoming messages to an Azure Service Bus. I can receive the messages without a problem. But when I try to route the request onto another service for processing, I am getting an error stating that the POST data is empty.
public static void Run(BrokeredMessage message, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {message.MessageId}");
if (message != null)
{
//MessageObjectEntity is a custom object
Common.Entities.MessageObjectEntity messageObject = message?.GetBody<Common.Entities.MessageObjectEntity>();
string msgType = messageObject?.MessageType;
var msgContent = messageObject?.MessageContent; // MessageContent is of type object to allow any object to be sent
using (var client = new HttpClient())
{
string url = $"http://mycompany.azurewebsites.net/api/routingtasks?formname={msgType}";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(subscriber, token);
HttpContent content = new StringContent((string)msgContent, Encoding.UTF8, "application/json");
var response = client.PostAsync(new Uri(url), content); // at this point content is valid
// I am getting a BadRequest returned here as the target service has not received the POST data
// that was sent in via the content variable
}
log.Info("Completing message.");
}
It appears that the POST data sent in the variable content is not received despite it being sent.
UPDATE
When I inspect the JSON sent to my Azure Function in the logger it looks like this.
{"FormName":"UpdateMileage","FormData":[{"Key":"enteredmileage","Value":100},{"Key":"todaysdate","Value":"01/01/2017"}],"Profile":{"EmailAddress":"unittest#mycompany.co.uk","ID":9999999}}
Which doesn't work.
But if I hard code the following JSON from my Azure Function it works correctly (the double quotes are needed to escape the back-slashes).
"\"{\\\"FormName\\\":\\\"UpdateMileage\\\","\\\"FormData\\\":"[{\\\"Key\\\":\\\"enteredmileage\\\",\\\"Value\\\":100},"{\\\"Key\\\":\\\"todaysdate\\\",\\\"Value\\\":\\\"01/01/2017\\\"}],"\\\"Profile\\\":"{\\\"EmailAddress\\\":\\\"unittest#mycompany.co.uk\\\","\\\"ID\\\":9999999}}\""
The problem therefore appears to be the formatting of the JSON that is being sent from my Azure Function, but I don't how I would convert my JSON into this format.
The problem was caused by the fact that I was sending JSON to my ASP.NET Web API service, but sending it as a string type. This is wrong.
The following article explains the correct approach when sending JSON data as a POST request.
I am trying to send text to all my peers and I found this function "sendDirectlyToAll".
For your convenience, I put the function information here:
sendDirectlyToAll(channelLabel, messageType, payload) - broadcasts a
message to all peers in the room via a dataChannel.
string channelLabel - the label for the dataChannel to send on.
string messageType - the key for the type of message being sent.
object payload - an arbitrary value or object to send to peers.
I do not understand the meaning of 2nd and 3rd parameters. Could you kindly show me an example how to use this function?
Thanks
Derek
Here is my example showing how i managed to get it working:
/**
* send directly to all other peers
*/
oSimpleWebRTC.sendDirectlyToAll(
'meta', // sLabel
'info', // sType - will become oData.sType
{"foo": "bar"} // oData - will become oData.payload
);
/**
* Handle incoming dataChannel messages sent by "sendDirectlyToAll"
* #param {object} oPeer The Remote sending Peer Object
* #param {string} sLabel A Label, e.g.: 'meta'
* #param {object} oData Object containing the relevant Data
*/
oSimpleWebRTC.on('channelMessage', function (oPeer, sLabel, oData) {
// e.g. we want label "hark" to be ignored, as it fires continiously.
if ('hark' === sLabel) {
return true;
}
if ('meta' === sLabel) {
if ('info' === oData.type)
{
// do your stuff
console.log(oData.payload.foo);
}
}
}
Also, There are Answers to this question at the official SimpleWebRTC issues Tracker: https://github.com/andyet/SimpleWebRTC/issues/450
See my blog post to this example: https://blog.ueffing.net/post/2017/02/22/simplewebrtc-usage-example-of-senddirectlytoall/
Under normal circumstances messages with a response will be published to the response.inq, I understand that and it's a nifty way to notify other parties that "something" has happened. But, when using the RPC pattern, the response goes back to the temp queue and disappears. Is this correct? Is there a convenient way, short of publishing another message, to achieve this behavior, of auto-notification?
The Message Workflow docs in describes the normal message workflow for calling a Service via ServiceStack.RabbitMQ:
Request / Reply
The Request/Reply alters the default message flow by specifying its own ReplyTo address to change the queue where the response gets published, e.g:
const string replyToMq = mqClient.GetTempQueueName();
mqClient.Publish(new Message<Hello>(new Hello { Name = "World" }) {
ReplyTo = replyToMq
});
IMessage<HelloResponse> responseMsg = mqClient.Get<HelloResponse>(replyToMq);
mqClient.Ack(responseMsg);
responseMsg.GetBody().Result //= Hello, World!
When using the Request/Reply pattern no other message is published in any other RabbitMQ topic/queue, to alert other subscribers the client would need to republish the message.
RabbitMqServer callbacks
Another way to find out when a message has been published or received is to use the PublishMessageFilter and GetMessageFilter callbacks on the RabbitMqServer and Client which lets you inspect each message that they sent or received, e.g:
var mqServer = new RabbitMqServer("localhost")
{
PublishMessageFilter = (queueName, properties, msg) => {
//...
},
GetMessageFilter = (queueName, basicMsg) => {
//...
}
};