How to call FIXAPI using any library (fixparser for nodejs)? - node.js

I want to use FIXAPI for one of my application.
I am trying connect "LOGON" api. But i am not getting any error or any Response.
While i was tried with "b2bits simulator", it works.
But Using any library, it does not give me any error or reponse.
I am using "fixparser" library (NodeJS npm library) to call the api.
Any help would be appreciated.
Thanks.
calling fixparser with different versions. and also tried different library (node-quickfix)
var fixparser = require("fixparser");
const fixParser = new FIXParser();
fixParser.connect({
host: HOST,
port: PORT,
protocol: 'tcp',
sender: SENDER,
target: TARGET,
fixVersion: VERSION
});
// Sendlogon function
function sendLogon() {
const logon = fixParser.createMessage(
new Field(Fields.MsgType, Messages.Logon),
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
new Field(Fields.SenderCompID, SENDER),
new Field(Fields.SendingTime, fixParser.getTimestamp()),
new Field(Fields.TargetCompID, TARGET),
new Field(Fields.ResetSeqNumFlag, 'Y'),
new Field(Fields.EncryptMethod, EncryptMethod.None),
new Field(Fields.HeartBtInt, 10)
);
const messages = fixParser.parse(logon.encode());
fixParser.send(logon);
}
// Open connection
fixParser.on('open', async (s, se) => {
console.log("Started....");
sendLogon();
});
// Retrive response
fixParser.on('message', (message) => {
// Received FIX message
// console.log("message",message);
console.log('received message', message.description, message.string);
});
// Close connection
fixParser.on('close', () => {
console.log("closed");
});
I want to get response and error(if any)

Looks like you are trying to connect to Stock Exchange api. So according to their docs: first message sent by client have to be a LOGON message, but FixParser after opening sockets sends heartbeat instead, and api closes connection after unexpected message.

Related

How to safely get the current user id in socket.io/Node.JS?

I am developing a simple API for a chat application on Node.js Express, and by assignment, it is required to make it possible to communicate between two users using socket.іо. I am faced with the problem that I cannot "safely" transfer information about the current user to the socket in any way. Information about the user with whom the correspondence is conducted can be specified in the socket parameters when connecting, which I do, but what about the current user (me)?
For example, I can do this:
const {receiverId, myId} = socket.handshake.query;
That is, specify both ids when connecting. But this is very unsafe because anyone who will join the socket can specify any id and write anything on behalf of someone else (for example, through Postman WebSockets).
Another option I was considering is making a post request in which a connection to the socket will be created using request.user.id and the request parameter. Then the post request will look like this:
router.post('/chat/:receiver', function (req,res){
const {receiver} = req.params
const socket = io.connect('/')
socket.emit('initMyUserId', {
myId: req.user,
});
})
But this option also did not work, because the file where this function is located and the file where the io variable is initialized are different, and I am not sure that it is generally advisable to transfer and use it in this way. Moreover, this approach will not allow me to check the operation of sockets via Postman, because the connection will occur in a post request, and not manually.
Are there working options to safely transfer the current user id with the ability to test it normally in postman? Or at least just safely pass the current user id if it doesn't work with Postman.
Here is the full code snippet for the socket events handlers:
module.exports = function(io) {
io.on('connection', (socket)=>{
const {id} = socket;
console.log(Socket connected: ${id});
const {idUser} = socket.handshake.query;
console.log(Socket idUser: ${idUser});
socket.on('message-to-user', (msg) => {
msg.type = user: ${idUser};
socket.to(idUser).emit('message-to-user', msg);
socket.emit('message-to-user', msg);
});
socket.on('disconnect', () => {
console.log(Socket disconnected: ${id});
});
});
}

Why does my Angular / Express.js Server-Sent Events Code not work?

Goal: Use Server-Sent Events in my Angular App with Express Backend
Problem: Server-Sent Events do not reach the client
Backend Code
router.get('/options/:a/:b/:c', async (req, res) => {
console.log('options endpoint called..', req.params.a,req.params.b,req.params.c);
// ---- SERVER SENT EVENTS ---- //
// Setting Headers
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Connection', 'keep-alive');
res.flushHeaders(); // flush the headers to establish SSE with client
for(let i=0;i<10;i++){
console.log("should now send this response...banane")
res.write('banane!')
}
});
Client Side Code
export class NetworkingService {
BASE_URL;
OPTIONS = 'options'
searchResultSubject: Subject<SearchResults>;
constructor(private http: HttpClient, private ls: LoggingService, private _zone: NgZone) { // shortened }
getOptions(a: string, b: string, c: string) {
this.ls.log("get options endpoint about to be triggered")
this.getServerSentEvent(this.BASE_URL + this.OPTIONS + "/" + a + "/" + b + "/" + c).subscribe(resp => {
this.ls.log("got from server: ", resp)
});
return this.searchResultSubject;
}
getServerSentEvent(url: string): Observable<any> {
console.log('creating an eventsource...')
return new Observable(observer => {
const eventSource = this.getEventSource(url);
eventSource.onopen = event => {
console.log('opening connection', eventSource.readyState)
};
eventSource.onmessage = event => {
console.log('event from server..')
this._zone.run(() => {
observer.next(event);
});
};
eventSource.onerror = error => {
console.log('error from server..')
this._zone.run(() => {
observer.error(error);
});
};
});
}
private getEventSource(url: string): EventSource {
return new EventSource(url);
}
}
Server Side log output (as expected)
options endpoint called.. A B C
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
Client Side log output (NOT as expected)
get options endpoint about to be triggered
creating an eventsource...
opening connection 1
...and then nothing.
What have I tried?
I fail to see how I differ from these: so-question, tutorial, tutorial
In the Networks Tab in Dev Tools I see a Status 200, type eventsource line entry with the correct headers. But only one!
I think I am making a really obvious mistake, since it is ALMOST working and seems to be straightforward from the examples.
My Angular is 10.1.6 and express is 4.17.1
I am new to interacting directly with ngZone is there a potential error?
The problem persists even when I comment out the compression library or use res.flush(), as suggested here.
I was having the same problem, I was not getting the response on the client.
After a number of changes it seems to be working.
First I set the headers:
response.setHeader('Cache-Control', 'no-cache');
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Connection', 'keep alive');
response.setHeader('X-Accel-Buffering', 'no');
response.flushHeaders(); // flush headers to establish SSE with client
If you are using the compress middleware, it is necessary that when sending the data to the client, you put
response.flush();
example
response.write(`event: ${event}\ndata: ${data}\n\n`);
response.flush();
It seems that the client receives messages from the generated event,
that is, if you send the client the following response
response.write(`event: some_event\ndata: some_data\n\n`);
the client should have a code similar to this:
const eventSource = new EventSource(url);
eventSource.addEventListener('some_event', listener => {
console.log(listener);
...
}, false);
I hope to be helpful
What worked for me was similar to what daacdev said, but not entirely.
Serverside I used:
res.setHeader('Cache-Control', 'no-cache, no-transform'); // Notice the no-transform!
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Connection', 'keep-alive');
res.flushHeaders(); // Flush the headers to establish SSE with client
// Do some stuff...
// Like sending an event with data
res.write('event: fooEvent\n'); // Note the 1 newline after the event name
res.write(`data: ${JSON.stringify({ foo: 'bar' })}\n\n`); // Note the 2 newlines after the data
// And when you're done, end it
res.end();
And clientside, we have eventListeners for event types:
const eventSource = new EventSource('/api/foo');
eventSource.addEventListener('fooEvent', event => {
console.log('Got fooEvent: ', event.data); // event.data has your data
eventSource.close(); // Close the eventSource if the client is done
});
You can leave out the event type altogether and only send 'data' in your res.write(). In which case your client listens for event type-less messages like this:
eventSource.onmessage = event => {
console.log('Got some data: ', event.data); // event.data has your data
eventSource.close(); // Close the eventSource if the client is done
Noteworthy:
The Cache-Control header needed 'no-transform' aside from 'no-cache'. Before I did that, the client would only get the messages after the server ended the whole thing
I did not need to flush after every write
You can't only send an event type. It always needs data to follow it. So if you simply want to send a message, do something like:
res.write('event: doubleProcesses\n');
res.write('data: doubleProcesses\n\n');
You must adhere to the defined structure: the optional 'event' (followed by a colon, a name, and 1 newline) and the required 'data' (followed by a colon, your data as a string, and 2 newlines). You cannot simply put anything in your res.write.
That last point is for sure what you were missing.
Docs here:
https://developer.mozilla.org/en-US/docs/Web/API/EventSource
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
For anyone who landed here after searching similar issues, what our problem turns out to be is that our node.js app is being hosted on Azure windows, and it is using IIS under the hood. The handler iisnode has a default setting of buffering response, which is the reason why response from our server was never received at the client side. All we had to do was to edit the web.config files according to this Microsoft guide
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-nodejs-best-practices-and-troubleshoot-guide
pay attention to the
flushResponse section

Botkit Slackbot responds with 401 error every time

I'm trying to create a very simple Slack bot using botkit and Google App Engine, but for some reason I keep getting 401 errors any time I message the bot. The weird thing is that the Slack Event Subscription URL (the one ending in /api/messages) validates correctly, and I get a 200 response in GAE logs and validation within Slack.
But whenever I actually message the bot it always gets a 401 error with no message explaining the error at all. I've tried various combinations of the code below, and have now stripped it down to the bare minimum as found here. Aside from dependencies and a code to decrypt credentials (which I've verified is working as expected), this is my full code at the moment:
botInit();
async function botInit () {
const credentialsRaw = await getCredentials();
const credentials = JSON.parse(credentialsRaw);
const adapter = new SlackAdapter(credentials);
const controller = new Botkit({
adapter: adapter
});
controller.on('message', async(bot, message) => {
await bot.reply(message, 'I heard a message!');
});
}
I have also tried this for the messaging function:
controller.ready(() => {
controller.hears(['hello', 'hi'], ['message', 'direct_message'],
async (bot, message) => {
await bot.reply(message, 'Meow. :smile_cat:')
})
})
and this for setting up the controller:
const controller = new Botkit({
webhook_uri: '/api/messages',
adapter: adapter
});
And everything gives back the same exact 401 error, despite all of them working with the Event Subscription URL verification on Slack.
I had same issue but figured out the problem.
I had been using Client Secret as clientSigningSecret
But I should use Signing Secret !

How to close connection with mqtt client node.js

I'm doing a method that works as follows:
When I press a button, I want to be continuously getting messages from the topic I'm subscribed to, and when I press another button I want to close connection and not receive any more messages. I think the connection closes correctly because the client.on('close') event is executed, however I continue receiving messages from the topic.
What should I do to not receive any more messages?
startStop is a boolean, it is true when I want to receive messages and false when I want to stop receiving them. What am I doing wrong?
Here's my code:
mqttClientSubscribeToTraceability(reguladorId, startStop) {
const tls = (Meteor.settings.mqttConfigClient.mqtt.port === 8883) || Meteor.settings.mqttConfigClient.mqtt.ca;
const client = mqtt.connect(`${tls ? 'mqtts' : 'mqtt'}://${Meteor.settings.mqttConfigClient.mqtt.host}:${Meteor.settings.mqttConfigClient.mqtt.port}`,
{ keyPath: Meteor.settings.mqttConfigClient.mqtt.key,
certPath: Meteor.settings.mqttConfigClient.mqtt.cert,
ca: [Meteor.settings.mqttConfigClient.mqtt.ca],
rejectUnauthorized: false
});
const topic = `in/1.0/trafficLights/${global.region}/${reguladorId}`;
const json = {};
if (startStop) {
client.on('connect', () => {
client.subscribe(topic);
});
client.on('message', (topic, message) => {
const msg = JSON.parse(message);
console.log('msg', msg);
});
} else {
client.end();
client.on('close', () => {
client.unsubscribe(topic);
});
}
}
The problem is that you are creating the connection object every time you call the function and not keeping a persistent reference to it.
This means when you call the function with startstop equal to true, you will create a new client object, subscribe to the topic and then attach the message callback. You then throw away the reference to the client object so there is no way to get it back.
When you call the function with startstop set to false, you still create a new client object, but then immediately close it. (Also calling unsubscribe after the client has been closed will achieve nothing except maybe throwing an error).
Given you have another variable (the reguladorId) you probably need to use an object which uses that as the key to hold separate client instances.

What's a valid #MessagePattern for NestJS MQTT microservice?

I'm trying to setup a MQTT Microservice using NestJS according to the docs.
I've started a working Mosquitto Broker using Docker and verified it's operability using various MQTT clients. Now, when I start the NestJS service it seems to be connecting correctly (mqqt.fx shows new client), yet I am unable to receive any messages in my controllers.
This is my bootstrapping, just like in the docs:
main.ts
async function bootstrap() {
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.MQTT,
options: {
host: 'localhost',
port: 1883,
protocol: 'tcp'
}
});
app.listen(() => console.log('Microservice is listening'));
}
bootstrap();
app.controller.ts
#Controller()
export class AppController {
#MessagePattern('mytopic') // tried {cmd:'mytopic'} or {topic:'mytopic'}
root(msg: Buffer) {
console.log('received: ', msg)
}
}
Am I using the message-pattern decorator wrongly or is my concept wrong of what a NestJS MQTT microservice even is supposed to do? I thought it might subscribe to the topic I pass to the decorator. My only other source of information being the corresponding unit tests
nest.js Pattern Handler
On nest.js side we have the following pattern handler:
#MessagePattern('sum')
sum(data: number[]): number {
return data.reduce((a, b) => a + b, 0);
}
As #Alexandre explained, this will actually listen to sum_ack.
Non-nest.js Client
A non-nest.js client could look like this (just save as client.js, run npm install mqtt and run the program with node client.js):
var mqtt = require('mqtt')
var client = mqtt.connect('mqtt://localhost:1883')
client.on('connect', function () {
client.subscribe('sum_res', function (err) {
if (!err) {
client.publish('sum_ack', '{"data": [2, 3]}');
}
})
})
client.on('message', function (topic, message) {
console.log(message.toString())
client.end()
})
It sends a message on the topic sum_ack and listens to messages on sum_res. When it receives a message on sum_res, it logs the message and ends the program. nest.js expects the message format to be {data: myData} and then call the param handler sum(myData).
// Log:
{"err":null,"response":5} // This is the response from sum()
{"isDisposed":true} // Internal "complete event" (according to unit test)
Of course, this is not very convenient...
nest.js Client
That is because this is meant to be used with another nest.js client rather than a normal mqtt client. The nest.js client abstracts all the internal logic away. See this answer, which describes the client for redis (only two lines need to be changed for mqtt).
async onModuleInit() {
await this.client.connect();
// no 'sum_ack' or {data: [0, 2, 3]} needed
this.client.send('sum', [0, 2, 3]).toPromise();
}
The documentation is not very clear, but it seem that for mqtt if you have #MessagePattern('mytopic') you can publish a command on the topic mytopic_ack and you will get response on mytopic_res. I am still trying to find out how to publish to the mqtt broker from a service.
See https://github.com/nestjs/nest/blob/e019afa472c432ffe9e7330dc786539221652412/packages/microservices/server/server-mqtt.ts#L99
public getAckQueueName(pattern: string): string {
return `${pattern}_ack`;
}
public getResQueueName(pattern: string): string {
return `${pattern}_res`;
}
#Tanas is right. Nestjs/Microservice now listens to your $[topic] and answer to $[topic]/reply. The postfix _ack and _res are deprecated.
For example:
#MessagePattern('helloWorld')
getHello(): string {
console.log("hello world")
return this.appService.getHello();
}
Listens now on Topic: helloWorld
Replies now on Topic helloWorld/reply
Regarding ID
You should also provide an id within the payload (See #Hakier) and Nestjs will reply with an answer, containing your id.
If you don't have any id, there still won't be any reply but the corresponding logic will still trigger.
For example (Using the snipped from above):
your msg:
{"data":"foo","id":"bar"}
Nestjs reply:
{"response":"Hello World!","isDisposed":true,"id":"bar"}
Without ID:
your message:
{"data":"foo"} or {}
No reply but Hello World in Terminal
I was fighting with MQTT today and this helped me a little, but I had more problems and below you can see my findings:
Wrong way of configuration broker URL
In my case when I used non-local MQTT server I started with this:
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.MQTT,
options: {
host: 'test.mosquitto.org',
port: 1883,
protocol: 'tcp',
},
});
await app.listenAsync();
but like you can read in a constructor of ServerMqtt they use url option only (when not provided it fallbacks to 'mqtt://localhost:1883'. While I do not have local MQTT it will never resolve app.listenAsync() which is resolved only on connect and will also not run any handler.
It started to work when I adjusted code to use url option.
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.MQTT,
options: {
url: 'mqtt://test.mosquitto.org:1883',
},
});
await app.listenAsync();
Messages require id property
Second very weird problem was that when I used Non-nest.js Client script from #KimKern I had to register two MessagePatterns: sum and sum_ack:
#MessagePattern('sum')
sum(data: number[]): number {
return data.reduce((a, b) => a + b, 0);
}
#MessagePattern('sum_ack')
sumAck(data: number[]): number {
return data.reduce((a, b) => a + b, 0);
}
When I used console.log I discovered that the latter is being run but only when the first one is present. You can push the same message to the broker using mqtt cli tool to check it:
mqtt pub -t 'sum_ack' -h 'test.mosquitto.org' -m '{"data":[1,2]}'
But the biggest problem was that it didn't reply (publish sum_res).
The solution was to provide also id while sending a message.
mqtt pub -t 'sum_ack' -h 'test.mosquitto.org' -m '{"data":[1,2], "id":"any-id"}'
Then we could remove 'sum_ack' MessagePattern and leave only this code:
#MessagePattern('sum')
sum(data: number[]): number {
return data.reduce((a, b) => a + b, 0);
}
The reason for this was hidden inside handleMessage method of ServerMqtt which will not publish response from a handler if a message didn't have id.
TL/DR
Specify url to message broker using url option only and always provide id for a message.
I hope that will save some time to others.
Happy hacking!

Resources