How do I communicate with SSE

Author: Xiao Lu Qing Qing Ming, Gewu Titanium front-end engineer

Some time ago, during the front-end development process of Tensorbay data set management platform, I needed to implement the feature of real-time output of activity log in an action. Suddenly, I came into contact with a new technology, and I couldn’t wait to share it with you!

Also procrastinate less than 2 months, SSE this does not come! 😝

WHAT? What is SSE?

SSE stands for server-sent Events, which literally means that the Server pushes information to the client.

As we know, the communication between client and server is generally through HTTP request, and HTTP request cannot make the server actively push information.

Except a situation, that is, the client tells the server then request this information is the “information flow”, a relatively easy to understand example is in the browser to download files, as set out in the client download a request, the client will tell the server the next request “information flow”, the server will be constantly for sending information to the client, The client does not close the connection and waits to receive the message.

SSE makes use of such a mechanism to realize the function of pushing information from the server to the client.

SSE sounds a bit like WebSocket, but careful friends can find that SSE is a one-way channel, can only realize the server to send information to the client, the client in the first time triggered SSE request can only receive, and can not reply.

The following figure shows the general process of SSE (the author personally copied the work)

HOW? How to use SSE?

Now that we know SSE, how do we use it?

On the client side, all of SSE’s apis are defined in the EventSource object!

An EventSource is an interface to network events pushed by the server. An EventSource instance opens a persistent connection to the HTTP service, sends events in text/event-stream format, and remains open until asked to close. Once the connection is opened, incoming messages from the server are distributed to your code as events. If there is an event field in the received message, the event is fired with the same value as the event field. If no event field exists, a generic event is emitted.

The constructor

EventSource()

pc = new EventSource(url, configuration)
Copy the code

Url is the location of the remote resource, and Configuration provides options for configuring new connections.

attribute
  • Eventsource. onError: Is an event handler called when an error occurs
  • Eventsource. onMessage: Is an event handler called when a message is received
  • Eventsource. onopen: Is an event handler that is called when a link is created
  • Eventsource. close: If the link exists, close the connection with readyState set to closed
  • Eventsource. readyState: Returns a read-only value for the status of the current link
  • Eventsource. url: Returns a read-only value for the URL of the current link

Use SSE to realize real-time output of activity log in action

After understanding THE SSE API in the client, combined with the real-time output log requirements, we can try to use it.

First, we’ll examine the requirement to render an activity’s log in real time on the right side of the screen when it is selected.

So obviously, we need to prepare the following:

  • The most important server-side URL
  • Onmessage callback after message is retrieved

When you’re ready, sort out your logic

  • We will maintain two states in the page, one for the EventSource object and the other for the log content data that needs to be displayed

      const [data, setData] = React.useState<string>('');
      const [event, setEvent] = React.useState<any>(null);
    Copy the code
  • Establish SSE connection with the back end when the log page is rendered

      const newEvent = new EventSourcePolyfill(`urlValue`, { headers });
    Copy the code
  • When the back end pushes the message back, we change the value of data to achieve real-time output

      newEvent.onmessage = (e: any) => {
        logs = logs.concat(`${e.data}\n`);
        setData(logs);
      };
    ​
      newEvent.onerror = () => {
        newEvent.close();
      };
    Copy the code

See here careful friends may notice a detail!

It is!

I didn’t even use the EventSource() mentioned above!

Using what looks like an encapsulated and EventSource()

EventSourcePolyfill()

Why is that? !

The answer is

EventSource does not support passing headers, so it cannot pass the server token. Therefore, I researched EventSourcePolyfill on the all-powerful GayHub and just use it! Pass! The service side! Token!

The final curl is:

curl 'https://gas.fat.graviti.cn/gatewayv2/venom-daemon/v1/activity/83639073cb30496c8a5794e9f9ad9276/logs/?&node_id=wf-i5ruzz -qsclf-1529545071&container=main&follow=true' \ -H 'authority: gas.fat.graviti.cn' \ -H 'sec-ch-ua: " Not; A Brand"; v="99", "Google Chrome"; v="91", "Chromium"; v="91"' \ -H 'accept: text/event-stream' \ -H 'x-token: 7cd82d49be4b468eb746a283121574e9' \ -H 'sec-ch-ua-mobile: ? 0' \ -h 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, Like Gecko) Chrome/91.0.4472.114 Safari/537.36' \ -h 'sec-fetch-site: same-origin' \ -h 'sec-fetch-mode: cors' \ -H 'sec-fetch-dest: empty' \ -H 'referer: https://gas.fat.graviti.cn/dataset/5c2d5481/zj_test/actions/wf/i5ruzz-qsclf?tab=log' \ -H 'accept-language: zh-CN,zh; Q = 0.9, en. Q =0.8' \ -h 'cookie: gr_user_id= a7f2dDE3-1fb7-4f4E-8EF4-ADF94A0F611e; Hm_lvt_88214dfcc23a7cf3e22c61fc2032b3cc=1624525026; _ga = GA1.1.588941179.1620461955; Hm_lpvt_88214dfcc23a7cf3e22c61fc2032b3cc=1625802074; Hm_lvt_16e30fb4f44e9e645bce6c970883ebce = 1625197778162638, 587162712, 443162802, 597; _ga_JMKPTKFK1Q = GS1.1.1625824946.4.0.1625824946.0; Hm_lpvt_16e30fb4f44e9e645bce6c970883ebce=1625985701; X-Token=7cd82d49be4b468eb746a283121574e9; 9383fdc1263bf861_gr_last_sent_sid_with_cs1=46cc67df-d7aa-4e46-9d61-75332ce7016c; 9383fdc1263bf861_gr_last_sent_cs1=bf3f0b777057a26f52b661c1f19eaa86; 9383fdc1263bf861_gr_session_id=46cc67df-d7aa-4e46-9d61-75332ce7016c; 9383fdc1263bf861_gr_session_id_46cc67df-d7aa-4e46-9d61-75332ce7016c=true; 9383fdc1263bf861_gr_cs1=bf3f0b777057a26f52b661c1f19eaa86' \ --compressedCopy the code

The most different is here:

-H 'accept: text/event-stream' \
-H 'x-token: 7cd82d49be4b468eb746a283121574e9' \
Copy the code

Renderings here and here:

Good drop thank you to read patiently, pass by by the way point a small love ❤️

See you next time!

[About Geti] : Positioned as a data platform for machine learning, GeTI Intelligent Technology is committed to creating the next generation of new infrastructure for AI developers, fundamentally changing the way they interact with unstructured data. TensorBay, an unstructured data management tool, and Open Datasets, an Open source data set community, help machine learning teams and individuals reduce the cost of data acquisition, storage and processing, accelerate AI development and product innovation, and provide a solid foundation for AI to empower thousands of industries and drive industrial upgrading.