Parse-server: Unable to query classes in cloud functions when we define multiple apps.

Created on 28 Aug 2019  路  5Comments  路  Source: parse-community/parse-server

Issue Description

I have created 2 apps using parse-server and parse-dashboard. Both the apps have different mongodb uris.

var api_app2 = new ParseServer({
  databaseURI: process.env.databaseURI, // Connection string for your MongoDB database
  cloud: process.env.CLOUD_CODE_MAIN || __dirname + "/cloud/main.js",
  appId: 'app2',
  masterKey: process.env.masterKey,
  serverURL: `${process.env.serverUrl}/parse`,
});
app.use('/parse/app2', api_app2);

var cwapp = new ParseServer({
  databaseURI: "mongodb://......../cw-app",
  cloud: process.env.CLOUD_CODE_MAIN || __dirname + "/cloud/cwapp/main.js",
  appId: 'cwapp',
  masterKey: process.env.masterKey,
  serverURL: `${process.env.serverUrl}/parse`,
});
app.use('/parse/cwapp', cwapp);

I have verified in API Console, which returns the results of the class successfully.

curl -X GET \
-H "X-Parse-Application-Id: cwapp" \
-H "X-Parse-Master-Key: MASTER_KEY" \
http://localhost:1337/parse/cwapp/classes/TestDB

But I am trying to write cloud function for one app ('cwapp').

  1. Working fine while invoking this cloud function using sample provided by the parse docs:
Parse.Cloud.define('Hello', function(req,res){
    return {"success":"200"};
})

Curl command :

curl -X POST \
-H "X-Parse-Application-Id: cwapp" \
-H "X-Parse-Master-Key: MASTER_KEY" \
http://localhost:1337/parse/cwapp/functions/Hello

But while i am trying to query the class within the cloud function it throws an error.

Here is my cloud function code in the same file (cloud/cwapp/main.js)

Parse.Cloud.define('getTestData', async (req,res) => {
    try{
        let itemQuery = new Parse.Query("TestDB");
        const result = await itemQuery.find({useMasterKey:true});
        return result;
    } catch(error){
        console.log(error);
        return error;
    }
})
curl -X POST \
-H "X-Parse-Application-Id: cwapp" \
-H "X-Parse-Master-Key: MASTER_KEY" \
http://localhost:1337/parse/cwapp/functions/getTestData

{
    "result": {
        "message": "Received an error with invalid JSON from Parse: <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot POST /parse/classes/TestDB</pre>\n</body>\n</html>\n",
        "code": 107
    }
}



md5-984810492a4d281c65fda289b9cfe87c



{
    "result": {
        "message": "Received an error with invalid JSON from Parse: <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot POST /parse/classes/TestDB</pre>\n</body>\n</html>\n",
        "code": 107
    }
}

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : ^3.7.2
    • Operating System: Mac
    • Hardware:
    • Localhost or remote server? : Local
  • Database

    • MongoDB version: 3.2.0
    • Storage engine: mLab
    • Hardware: [FILL THIS OUT]
    • Localhost or remote server? mLab

      Logs/Trace

info: Ran cloud function getTestData for user undefined with:
Input: {}
Result: {"message":"Received an error with invalid JSON from Parse: \n\n\n\nError\n\n\n

Cannot POST /parse/classes/TestDB
\n\n\n","code":107} {"functionName":"getTestData","params":{}}

needs more info

Most helpful comment

Thanks for sending the detailed information. I've just gone through your code and I've figured out that it will actually not work.

Since the apps are instantiated under the same Node.js process, they are sharing the same Parse JS SDK. But the JS SDK was designed to connect to a single server URL as you can see here. The Parse.serverURL is a static member that is used in the Parse initialization here. It means that, at each initialization, the server url will be overridden. So all your cloud code functions, when using the Parse SDK, will actually connect to the last Parse Server you instantiated.

So here it goes your options:

Since this issue is actually the same of https://github.com/parse-community/parse-server/blob/master/src/ParseServer.js#L66, I will close this one and we can keep following up the other.

All 5 comments

I think the problem happens because the second app is mounted in a nested route. Try to mount the second app in another route, maybe: app.use('/parseapp2', api_app2);

Hi @davimacedo , thanks for the response. I have tried as you mentioned, but no luck.. :(

tried this one also :

app.use('/parse/cwapp', cwapp);

Can you please share your most updated code including the lines that you are using to initiate Parse Server and the ones that you are mounting the apis to your Express.js app? I will try to simulate the problem.

Hi @davimacedo, Please find the logs what i have tried and also attached app.js

cloud function POST method refers to /cwapp/functions/getTestDB, But

Query in cloud function is referring to /app1/classes instead of /cwapp/classes
GET /app1/classes/TestDB 200 5879.092 ms - 14

POST /cwapp/functions/getTestDB 400 1.865 ms - 54
GET /app1/classes/TestDB 200 5879.092 ms - 14
info: Ran cloud function getTestData for user undefined with:
  Input: {}
  Result: [] {"functionName":"getTestData","params":{}}
POST /cwapp/functions/getTestData 200 5887.392 ms - 13

I have added app.js content in the below attachment. i have also added mlab url for reference too.

Only cwapp is pointing to mLab url, rest of the apps to local mongodb url

.env file :

databaseURI=mongodb://localhost/test
appId=APP_ID
masterKey=MASTER_KEY
javascriptKey=javascriptKey
restAPIKey=REST_API_KEY
serverUrl=http://localhost:1337
appName=MyDemo
masterUsername=masterUsername
masterPassword=masterPassword

package.json :

{
  "name": "parseserverdashboard",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cloud": "^2.0.2",
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "dotenv": "^8.0.0",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "jade": "~1.11.0",
    "morgan": "~1.9.1",
    "parse-dashboard": "^1.4.3",
    "parse-server": "^3.7.2"
  }
}

Cloud Function: cloud/cwapp/main.js

Parse.Cloud.define('getTestData', async (req,res) => {
    try{
        let itemQuery = new Parse.Query("TestDB");
        const result = await itemQuery.find({useMasterKey:true});
        return result;
    } catch(error){
        console.log(error);
        return error;
    }
});

Note: if i am changing the order from
app.use('/parse/cwapp', cwapp);
app.use('/parse/app1', app1);

to
app.use('/parse/app1', app1);
app.use('/parse/cwapp', cwapp);

works fine....but app1 got effected this time.

Thanks for sending the detailed information. I've just gone through your code and I've figured out that it will actually not work.

Since the apps are instantiated under the same Node.js process, they are sharing the same Parse JS SDK. But the JS SDK was designed to connect to a single server URL as you can see here. The Parse.serverURL is a static member that is used in the Parse initialization here. It means that, at each initialization, the server url will be overridden. So all your cloud code functions, when using the Parse SDK, will actually connect to the last Parse Server you instantiated.

So here it goes your options:

Since this issue is actually the same of https://github.com/parse-community/parse-server/blob/master/src/ParseServer.js#L66, I will close this one and we can keep following up the other.

Was this page helpful?
0 / 5 - 0 ratings