UXP Web socket under HTTP/2?

Hello everyone,

I am currently in the process of building a plugin for Photoshop 22+. I have reached a point where I need to implement socket updates. However, upon further research, I have discovered that the UXP does not support the HTTP/HTTP2 event source.
Also tried to use WebSocket to connect without any luck…

Has anyone else encountered this issue? If so, what were your solutions for resolving it?
The socket is based on Mercure

Any help, hint or advice would be greatly appreciated.

EDIT: Also tested with a Polyfil for EventSource.
Only what we get is a “pending”, no data fetched…

Thank you in advance.

Best regards, Angel.

This topic shud be considered as a BUG or MISSING for UXP, there is no way to handle a new type of socket, no way to handle Even sources in UXP at all!

With the best result from polyfill Yaffle EventSource
Scraping comp app for later time WHEN ADOBE IS READY…

Is it only my or this WebSocket in UXP is not working at all…

Can someone make a simple test to connect to the test server socket, as an example:
https://socketsbay.com/test-websockets

What I get is only closed 1005, cannot get any ‘connect’ in UXP

Did you try searching the forum? There are a few topics with successful sockets use

Yes, even tested several times the published example for socket.
Now I will verify this one: “doesn’t appear to work on Windows”

Your second link is for XD, but I guess it also might help.
Anyway, the very first forum search for socket link leads to this topic with a solution. Worth checking out

Scraping this socket io as an option, we will not make downgrading of our infrastructure for a single plugin …

After an indescribable struggle to find a solution to read Server Side Event (SSE) ended to a code:

import {TextDecoder} from 'text-encoding-utf-8'; // polyfill 

    let response;
    try {
        response = await window.fetch(mercureUrl, {
            keepalive: true,
            method: 'GET',
            headers: {
                'Authorization': `Bearer ${jwtToken}`,
                'Accept': 'text/event-stream',
            },
        });
    } catch (e) {
        console.error(e)
        return
    }

    console.log(response)

    // handle the response stream
    const reader = response.body.getReader();
    let buffer = '';
    while(true) {
        const {done, value} = await reader.read();
        if(done) {
            console.log('Connection closed')
            break;
        }
        // add the received data to the buffer
        buffer += new TextDecoder('utf-8').decode(value);
        // split the buffer into lines
        const lines = buffer.split('\n');
        // process each line
        lines.forEach((line) => {
            if(line.startsWith('data:')) {
                // handle received data
                const data = JSON.parse(line.substring(6));
                console.log('Received data:', data);
            }
        });
        // remove the processed lines from the buffer
        buffer = lines.pop();
    }

(The code is ruff example)
Note:
This is how to connect to the Mercure socket, sadly works only on the last PS versions from 2023, for the older versions fetch is not working correctly…

2 Likes

Update:
From Photoshop v23 LTS fetch work fine for socket
Here polished version of the code:


    const headers = {
        Authorization: `Bearer ${token}`,
        Accept: "text/event-stream",
    };

    if(lastProcessedId) {
        headers["Last-Event-ID"] = lastProcessedId;
    }

    // create a fetch request to subscribe to the Mercure hub

    try {
        response = await window.fetch(mercureUrl + topic, {
            keepalive: true,
            method: 'GET',
            headers: headers,
        });
    } catch (e) {
        console.error(e)
        return
    }


    // handle the response stream
    reader = response.body.getReader();
    let buffer = '';
    while(true) {
        const {done, value} = await reader.read();
        if(done) {
            console.log('Connection closed');
            break;
        }
        buffer += new TextDecoder('utf-8').decode(value);


        const messages = buffer.split('\n');
        messages.forEach(contents => {

            //
            // Capture update data
            if(contents.startsWith('data:')) {
                const message = contents.substring("data: ".length);
                try {
                    callback(JSON.parse(message))
                } catch (e) {
                    // bypass errors of JSON, since content cen be incomplete
                    console.warn('Incomplete JSON message!')
                }
            }

        })
        console.log(messages);
        buffer = messages.pop();


    }
1 Like