Fix: EventSource's response has a charset ("iso-8859-1") that is not UTF-8. Aborting the connection.
Fix: EventSource’s response has a charset (“iso-8859-1”) that is not UTF-8. Aborting the connection.
The issue is with the mismatch charset. You have default charset charset : iso-8859-1 and you are trying to use content which have charset=UTF-8.
To fix the error you need to set the charset=UTF-8 in which you have set the header. In my case, I have fix the error by setting the charset=UTF-8 in header. Check below code for reference:
Every quest deserves to have a side-quest or two, tonight was one of those.
While I have reviewed many wedding venues for Event Source this year, when Hockey Hall of Fame came up as a party that needed someone to cover it, I jumped a the opportunity. It was refreshing to do something outside of the wedding world and what better place than with this epic piece of our Canadian Identity.
Plus interviewing people is pretty darned fun! Especially for vendors at these events, asking questions seems to bring a sense of purpose to all of us and helps elevate the mood regardless of the answers.
The HHOF made a proud Canadian out of me today, Any side-quest that includes meeting the Stanley Cup is welcome in my books. Read the entire blog on Eventsource right here:
So I should probably write this down so I don't forget it. Maybe someone else will benefit from this as well.
If you want to do server-sent events in Hapi, it's actually possible and not that difficult, but it's not as intuitive because apparently nobody likes server-sent events.
So this is literally what it says. You obtain a stream in some way. If you will manage the writing to the stream yourself (which you probably will), you can do this:
const Stream = require('stream') function createStream() { let stream = new Stream.PassThrough() setTimeout(() => { stream.write('data: Hello there!\n\n', 'utf-8') }, 1000) setTimeout(() => { stream.write('data: Here\'s more data!\n\n', 'utf-8') }, 3000) return stream }
Of course this is a bit dumbed down, but that's the simplest way to do it. Streams just seem like the right tool for the job, even though they don't seem to be designed to be used in JS directly.
I am not 100% sure why this part is here, but I think there was something weird with disconnections not closing the stream and leaking memory, essentially. Please do drop me a line if this is not correct.
I feel like this is pretty self-explanatory, but I want to go over the Transfer-Encoding: identity bit. By default Hapi sends streams using the chunked encoding, which is what you likely need when you're sending streams not generated by your code. However that means that bytes go over the wire like this:
14 data: thing 1 14 data: thing 2
Before the actual data the server sends how many characters will the data take up. This is better for dealing with binary data and such, but apparently browsers don't like the chunked encoding when dealing with EventSource. They expect a flat, simple stream like this:
data: thing 1 data: thing 2
My limited testing revealed that the content length prefix makes the browser not accept such data as a valid event source. 1
Content-Encoding: identity ensures that the data won't be compressed with gzip or whatever your browser requests. That also seems to break the stream.
Although the standard specifies that identity shouldn't be explicitly used as a Content-Encoding value, this is the only way to make Hapi send streams as-is without chunking.
Anyway, that's how I did event streams for a previous project of mine. Do let me know if something's not working or has changed since I last checked.
Edit 2016-12-28
After a bit of using this solution, I've found a problem -- Hapi (gracefully) closes stream responses if there is no data written for 2 minutes. Therefore you should implement some sort of a keepalive mechanism if you want to use a single EventStream (to prevent data loss, most likely).
The code examples were also updated slightly since browsers like when both Transfer-Encoding and Content-Encoding are set to identity. Using gzipping will not really work with event streams.
Of course, please note that this might have changed in recent Hapi versions, or the browsers might have changed their behaviour. As I said, my testing was limited. ↩︎
I’ve been working on an SSE server and wanted to test how many connections it could accept. The eventsource library seemed like a simple way to create SSE clients, so I wrote a small nodejs app to create a bunch of connections to a channel, send a message and print ‘WORKS’ if they all got it. You can run it by cloning the repo ($ git clone https://github.com/arpith/sse-test) and then, in the directory, running $ babel-node main.js
var EventSource = require('eventsource'); var request = require('request');
process.env lets you read environment variables, in this case a maximum number of clients, a token (for the POST request to the SSE server) and a URL for the server.
var maxClientCount = process.env.CLIENT_COUNT; var token = process.env.TOKEN; var satelliteUrl = process.env.SATELLITE_URL + "/broadcast";
Defining a class in ES6 is pretty straightforward, writing a constructor method lets you initialise the object (this.es is the actual SSE client).
There are two things to note about receiveMessage(): one is the two arrow functions (i.e., ((arg1, arg2) => { statement;}) instead of function(arg1, arg2) { statement; }) that I’ve used, and the other is the Promise (read more) that it returns. The first arrow function (passed to the Promise object) is written this way so that the this in this.es.onmessage refers to the this of the class, while the second arrow function (assigned to this.es.onmessage) is just to keep things brief.
I used a promise so that I could do something when the client receives the sent message (or rather, when all the clients in the test do). A promise object takes a function that gets passed two functions as arguments, resolve and reject.
When things work out (in this case, one of the messages received by the eventsource object is the message we are interested in) call resolve() and the promise will resolve (and whatever you want to do next can take place).
reject is a function you can call if things don’t work out (and you want to pass on the error, for example). I’m not using it because eventsource clients conveniently retry connections, so an error isn’t really a failure. Skip to the end if you want to see how this promise (that we’re returning) is used.
I need a random string to use as the channel name:
var randomString = function() { var crypto = require('crypto') , shasum = crypto.createHash('sha1'); shasum.update(Math.random().toString()); return shasum.digest('hex'); }
And a random number of clients to try sending a message to:
And here’s the actual test, where I create a bunch of clients and store them in an array, before using Promise.all to log “WORKS” if all the clients receive the message. Promise.all takes an array of promises, and returns a promise that has a then method that takes two functions, the first one to be called if Promise.all() resolves and a second one that will be called if it doesn’t (someone used reject()).
var startTest = function () { var msg = 'PONG' var channelUrl = satelliteUrl+'/'+randomString(); var clientCount = randomClientCount(); var clients = []; for (let i=0; i<clientCount; i++) { clients.push(new Client(channelUrl)); } Promise.all(clients.map(c => c.receiveMessage(msg))) .then(function(response) { console.log("WORKS for "+clientCount+" clients"); clients.map(c => c.close()); }, function(error) { //this function won't be called, we haven't used reject anywhere }); request.post(channelUrl).form({'token':token,'message':msg}); }
As mentioned earlier, all this is to be able to log when all clients have received the message that is now going to be POST’d. Now I just have to run test() every second or so.
This guide compares active, open-source Event Sourcing libraries in Ruby. It doesn't make any specific recommendations, just specific comparisons that will hopefully save programmers some time in making a decision.
I'm currently working on implementing and deploying a facebook application.
Its a simple TicTacToe game. However I'm trying to implement it as a multiplayer game and publish it in facebook. Potentially having lots of players playing it online.
Important bits for me on this projects are :
- Event sourcing
- Message Queuing
- Multiplayer game
- Facebook app
- NodeJS and Socket.io
- Deployment scripts to AWS
So I'm going to learn a lot and hopefully ship a real application soon.
Check this project out at : https://github.com/bamdadd/tictactoe