We can connect to LiveQueryServer via ws, but not via wss. How can we configure it using via wss?

Hi,
I am using a local virtual Bitnami Parse Server. Everything works normally. I can connect to ParseServer with HTTPS. I can connect to LiveQuery via ws:// but not via wss://.
How can I configure LiveQuery Server with WSS?

ParseServer version: 4.9.3
/opt/bitnami/parse/config.json like this:
{
“appId”: “xxx”,
“masterKey”: “xxxx”,
“appName”: “parse-server”,
“mountPath”: “/parse”,
“port”: “1337”,
“host”: “0.0.0.0”,
“serverURL”: “https://xxx/parse”,
“publicServerURL”: “https://xxxx/parse”,
“databaseURI”: “mongodb://bn_parse:[email protected]:27017/bitnami_parse”,
“liveQuery”: {
“classNames”: [“class1”,“class2”]
},
“startLiveQueryServer”: “true”,
“liveQueryServerOptions”: {
“appId”: “xxxx”,
“serverURL”: “wss://xxxx:1337”,
“masterKey”: “xxxx”,
“logLevel”: “VERBOSE”
}
}

Would you mind to share the code that you are using to connect from client and also the error message that you have?

Client error message:
…
flutter: ╭-- Parse Request
flutter: curl -X GET -H ‘user-agent: Flutter Parse SDK 2.1.0’ -H …
…

flutter: LiveQuery: : Error: HandshakeException: Handshake error in client (OS Error:
WRONG_VERSION_NUMBER(tls_record.cc:242))
flutter: ╭-- Parse Response
Class: LiveQuery
Function: ParseApiRQ.liveQuery
Status Code: -1
Type: UnknownError
Exception: HandshakeException: Handshake error in client (OS Error:
WRONG_VERSION_NUMBER(tls_record.cc:242))
╰–
flutter: LiveQueryReconnectingController: Retrytimer set to 500ms
flutter: LiveQueryReconnectingController: LiveQueryClientEvent.DISCONNECTED

Client:
parse_server_sdk_flutter: ^2.1.0
Like this Widget:

ParseLiveListWidget<ParseObject>(
  query: query,
  lazyLoading: true,
  preloadedColumns: ["test1", "sender.username"],
  childBuilder:
      (BuildContext context, ParseLiveListElementSnapshot<ParseObject> snapshot) {
    if (snapshot.failed) {
      return const Text('something went wrong!');
    } else if (snapshot.hasData) {
      return ListTile(
        title: Text(
          snapshot.loadedData.get<String>("text"),
        ),
      );
    } else {
      return ListTile(
        title: Text(
          "loading comment from: ${snapshot.preLoadedData?.get<ParseObject>("sender")?.get<String>("username")}",
        ),
      );
    }
  },
);

I guess, this is livequery server certificate issue. How can I bind the certificate to livequeryserver?

Could you share the code that you are using to initlize Parse/Live Query sdk?

ParseServer SDK initialize:
// Initialize parse
await Parse().initialize(
APPKEY,
APIURL,
masterKey: “”,
clientKey: “”,
liveQueryUrl:“wss://fqdn:1337”,
debug: true,
autoSendSessionId: true,
appName: kIsWeb ? “X” : null,
appVersion: kIsWeb ? “Version 1.0” : null,
appPackageName: kIsWeb ? “fqdn” : null
);

What is the address that you are using to perform the https request to the rest api?

the address:
https://api02.westeurope.cloudapp.azure.com/parse
wss://api02.westeurope.cloudapp.azure.com:1337

They should be in the same port. Have you tried live query with wss://api02.westeurope.cloudapp.azure.com?

I changed to wss://api02.westeurope.cloudapp.azure.com

same as client side and server side: wss://api02.westeurope.cloudapp.azure.com

“liveQuery”:{
“classQuery”: [“Class1”,“Class2”]
},
“startLiveQueryServer”: “true”,
“liveQueryServerOptions”:{
“appId”: “xxxx”,
“serverURL”: “wss://api02.westeurope.cloudapp.azure.com”,
“masterKey”: “xxx”
}

Error message changed:

flutter: LiveQueryReconnectingController: Retrytimer set to 500ms
flutter: LiveQueryReconnectingController: LiveQueryClientEvent.DISCONNECTED
flutter: LiveQuery: : Error: WebSocketException: Connection to ‘https://api02.westeurope.cloudapp.azure.com:0#’ was not upgraded to websocket
flutter: ╭-- Parse Response
Class: LiveQuery
Function: ParseApiRQ.liveQuery
Status Code: -1
Type: UnknownError
Exception: WebSocketException: Connection to ‘https://api02.westeurope.cloudapp.azure.com:0#’ was not upgraded to websocket

I am also having the same issue, @ParseServerCandir did you able to resolve it? If so, could you post it here. Thanks in advance

No, not yet. I think we will solve the problem with @davimacedo’s support, or maybe others.

Could you please share the code that you are using to mount parse api and live query on express.js?

Server:

const ParseServer = require('parse-server').ParseServer;
const RedisCacheAdapter = require('parse-server').RedisCacheAdapter
const http = require('http');
const firebaseAuthAdapter = require('parse-server-firebase-auth-adapter');

const databaseUri = process.env.DATABASE_URI;
const cloudCodeMain = process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js';
const appId = process.env.APP_ID;
const masterKey = process.env.MASTER_KEY;
const serverURL = process.env.SERVER_URL || 'http://localhost:1337/parse'
const cacheRedisURL = process.env.CACHE_REDIS_URL;
const liveQueryRedisURL = process.env.LIVE_QUERY_REDIS_URL;
const port = process.env.PORT || 1337;
const mountPath = process.env.MOUNT_PATH || '/parse';
const mode = process.env.SERVER_MODE || '';
const gcsProjectId = process.env.GCS_PROJECTID || '';
const gcsBucket = process.env.GCS_BUCKET || '';


const config = {
    databaseURI: databaseUri,
    cloud: cloudCodeMain,
    appId: appId,
    masterKey: masterKey,
    serverURL: serverURL,
    cacheAdapter: new RedisCacheAdapter({
        url: cacheRedisURL,
    }),
    liveQuery: {
        classNames: ['MyClass'],
        redisURL: liveQueryRedisURL,
    },
    filesAdapter : {
       module: "@parse/gcs-files-adapter",
       options: {
           projectId: gcsProjectId,
           bucket: gcsBucket
       }
    },
    auth: {
        firebase: firebaseAuthAdapter
    }
}

console.log(JSON.stringify(config));

let enableLiveQuery = false;
if (mode === 'liveQuery') {
    enableLiveQuery = true;
}
const app = express();

const api = new ParseServer(config);
app.use(mountPath, api);

const httpServer = http.createServer(app);
httpServer.listen(port,()=>{
    console.log('server running on port ' + port);
});
if (enableLiveQuery) {
    console.log('livequery server is running..');
    ParseServer.createLiveQueryServer(httpServer, {
        appId: appId,
        masterKey: masterKey,
        serverURL: serverURL,
        redisURL: liveQueryRedisURL,
    });
}

module.exports = {
  app,
  config,
};

Flutter Parse:

await Parse().initialize(
    keyParseApplicationId,
    keyParseServerUrl,
    debug: true,
    liveQueryUrl: keyLiveQueryUrl,
    coreStore: await CoreStoreSharedPrefsImp.getInstance(),
    autoSendSessionId: true,
  );

@yp19 what is the value of ‘keyLiveQueryUrl’?

liveQueryUrl: keyLiveQueryUrl

like mine?

it is https://livequery.domain.com

flutter log:

I/flutter ( 8004): LiveQuery: : Socket opened
I/flutter ( 8004): LiveQuery: : ConnectMessage: {op: connect, applicationId: appid, sessionToken: r:token}
I/flutter ( 8004): LiveQuery: : Done
I/flutter ( 8004): LiveQueryReconnectingController: Retrytimer set to 10000ms
I/flutter ( 8004): LiveQueryReconnectingController: LiveQueryClientEvent.DISCONNECTED

@yp19 well, what is the value of ‘redisURL: liveQueryRedisURL’?
and ‘serverURL: serverURL’?

redisURL: hostRedisServerURL
serverURL: https://objstore.domain.com

By the way, the above setup is working properly with Javascript. I have a Javascript test client, it is receiving the new objects created with LiveQueries