Parse-SDK-JS icon indicating copy to clipboard operation
Parse-SDK-JS copied to clipboard

The request in Parse.Object.saveAll() does not have a reverse proxy

Open roger28200901 opened this issue 2 years ago • 10 comments

New Issue Checklist

Issue Description

I was wondering about the practical method behind Parse.Object.saveAll, If my Parse Server I want to redirect through Proxy ex: 192.168.1.1/api -> 192.168.1.1:4000/parse then, here is the problem.

on the parse/lib/node/ParseObject.js line:2388

return RESTController.request('POST', 'batch', {
              requests: batch.map(obj => {
                const params = obj._getSaveParams();
                params.path = getServerUrlPath() + params.path;
                return params;
              })
            }, options);

And here is the problem, After the above code, my input data format will be like this:

{
  "requests": [
    {
      "method": "PUT",
      "path": "/api/classes/{{className}}/{{ objectId }}",
      "body": {
         {{ Here is the object body}}
       }
    }
  ]
}

and then, as you can see the RESTController will send a axios POST for url -> 192.168.1.1/api/batch and then proxy server (nginx), will let the request send to the 192.168.1.1:4000/parse/batch, but in my requests body, the path only show it to /api/classes/{{className}}/{{objectId}} , it wont through the nginx setting to let the redirect change to /parse/classes/{{className}}/{{objectId}}

Steps to reproduce

//config.js
const parseUrl = process.env.PARSE_URL || 'http://192.168.1.1/api'; // the nginx will let the 192.168.1.1/api turn into 192.168.1.1:4000/parse
const appId = 'test';
const masterKey = 'test-key';
const initParse = () => {
  Parse.initialize(appId, null, masterKey);
  Parse.serverURL = parseUrl;
  Parse.User.enableUnsafeCurrentUser();
};
const query = new Parse.Query(Tests);
const tests = await query.findAll()
tests.forEach((test) => {
 test.set('name', 'something');
})
await Parse.Object.saveAll(tests); // And then show the error code 206

Actual Outcome

format : Parse Error: cannot route batch path: /api/classes/{{className}}/{{objectId}} { code: 111 }

real outcome: ParseError: cannot route batch path /api/classes/tests/6ab89f70-addf-11ed-b17e-f98dadf7fe5c at C:\Users.......\node_modules\parse\lib\node\ParseObject.js:3047:34 at processTicksAndRejections (node:internal/process/task_queues:96:5) { code: 111 }, . . .

Expected Outcome

Expected it can saveAll and the response won't fail

Environment

Nginx

location /api/ {
    #proxy_redirect off;
    #proxy_set_header Host $host;
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS';
    add_header Access-Control-Allow-Headers 'Content-Type, X-DP-Token, X-DP-Application-Id';
    #proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.1.1:4000/parse/;
    client_max_body_size 16M;
  }

Server

  • Parse Server version: 6.2.0
  • Operating system: linux

Database

  • MongoDB

Client

  • Parse JS SDK version: 4.1.0

roger28200901 avatar Jun 14 '23 01:06 roger28200901

Thanks for opening this issue!

  • 🚀 You can help us to fix this issue faster by opening a pull request with a failing test. See our Contribution Guide for how to make a pull request, or read our New Contributor's Guide if this is your first time contributing.

Could you please complete the issue template (I've re-added the headlines) and ensure that you follow the checklist at the top?

mtrezza avatar Jun 14 '23 08:06 mtrezza

Could you please complete the issue template (I've re-added the headlines) and ensure that you follow the checklist at the top?

I already fix it, and very sorry about didn't follow the issue template, cause this is the first time I try to send the issue.

roger28200901 avatar Jun 14 '23 10:06 roger28200901

No worries, thanks for reporting the issue. The template just helps others to easier understand the issue.

In the steps to reproduce you are first querying tests and then saving all users. How are tests and users related?

mtrezza avatar Jun 14 '23 20:06 mtrezza

sorry, it was tests not users. I already edited it. and also add setting code about the nginx setting. and you can check it.

roger28200901 avatar Jun 15 '23 01:06 roger28200901

Could you please correct the code and make sure it's complete?

mtrezza avatar Jun 15 '23 06:06 mtrezza

Could you please correct the code and make sure it's complete?

I corrected it. Here are some additions, where my parse server is set on port :4000/parse on docker, so you can see above that I use an nginx as a reverse proxy to /api -> :4000/parse

roger28200901 avatar Jun 15 '23 07:06 roger28200901

Could you post the line from ParseObject.js:3047:34?

mtrezza avatar Jun 15 '23 08:06 mtrezza

 (0, _promiseUtils.when)(batchReady).then(() => {
            // Kick off the batch request
            return RESTController.request('POST', 'batch', {
              requests: batch.map(obj => {
                const params = obj._getSaveParams();
                params.path = getServerUrlPath() + params.path;
                return params;
              })
            }, options);
          }).then(batchReturned.resolve, error => {
            batchReturned.reject(new _ParseError.default(_ParseError.default.INCORRECT_TYPE, error.message));
          });

The error show up on the batchReturned ... this line and then I see the function getServerUrlPath() how it works,

function getServerUrlPath() {
  let serverUrl = _CoreManager.default.get('SERVER_URL');
  if (serverUrl[serverUrl.length - 1] !== '/') {
    serverUrl += '/';
  }
  const url = serverUrl.replace(/https?:\/\//, '');
  return url.substr(url.indexOf('/'));
}

so as you can see, if my parseUrl is 'http://192.168.1.1/api' and I use a reverse proxy to make this url to redirect on the Parse Server (this is setup on the docker url: '192.168.1.1:4000/parse'), and I can see the request is sending to the url 'http://192.168.1.1/api' and then turn into the 'https://192.168.1.1:4000/parse', but the getServerUrlPath() didn't know I was trying to use reverse proxy skill, so params.path = getServerUrlPath() + params.path; it will show up like /api/classes/{className}/{objectId} and not like this /parse/classes/{className}/{objectId},

for example:

{
        "requests": [
          {
            "method": "POST",
            "path": "/api/classes/GameScore",
            "body": {
              "score": 1337,
              "playerName": "Sean Plott"
            }
          },
          {
            "method": "POST",
            "path": "/api/classes/GameScore",
            "body": {
              "score": 1338,
              "playerName": "ZeroCool"
            }
          }
        ]
      }' 
  request url : https://192.168.1.1/api/ -> and then proxy will send into https://192.168.1.1:4000/parse
  request method: post
  but the every request object's attribute 'path' won't change to /parse/....

Sorry for my english is not very good so please forgive me :( if i didn't explain clearly

roger28200901 avatar Jun 15 '23 14:06 roger28200901

Thanks for providing more details, let's see if someone in the community has an idea...

mtrezza avatar Jun 16 '23 01:06 mtrezza