这是indexloc提供的服务,不要输入任何密码
Skip to content

Long Polling is using the wrong hostname rather than the one specified in useEmulator #4603

@aameen951

Description

@aameen951

[REQUIRED] Describe your environment

  • Operating System version: Windows NT 10.0; Win64; x64
  • Browser version: Chrome/88.0.4324.190
  • Firebase SDK version: 8.2.3
  • Firebase Product: database

[REQUIRED] Describe the problem

When using the emulator your are supposed to call useEmulator and pass it the hostname and the port number as follows:

// 192.168.1.16 is another compute on the local network
app.database().useEmulator('192.168.1.16', 9000);

The database SDK is then supposed to use that hostname for connecting to the database.

The SDK has two connection methods: Websockets and Long Polling.
Websocket connection is working as expected but long polling is not.

The first request in long polling is connecting to the correct hostname as specified by useEmulator and its sending the following request:

http://192.168.1.16:9000/.lp?start=t&ser=25520194&cb=1&v=5&p=1:851885969054:web:424a0562e499959d70b58f&ns=project-id-default-rtdb

and the response is something like the following:

function pLPCommand(c, a1, a2, a3, a4) {
parent.window["pLPCommand1"] && parent.window["pLPCommand1"](c, a1, a2, a3, a4);
}
function pRTLPCB(pN, data) {
parent.window["pRTLPCB1"] && parent.window["pRTLPCB1"](pN, data);
}
         pLPCommand('start','35','FR2NN15XmK');
pRTLPCB(0,[{"t":"c","d":{"t":"h","d":{"ts":1615310373486,"v":"5","h":"localhost:9000","s":"hH3sdSBSPZIjMcyS1p29r8oVNx0SKTw3"}}}]);

All following requests are using the hostname that arrived in the previous response which is 'localhost', and they are all failing because localhost refers to the wrong computer when used on the client.

This problem will only happen if you try to connect to the database from a different computer. Using the same computer it would still work because 'localhost' is referring to both the client and the database.

The fix for this could be to ignore the incoming hostname and port number if using an emulator.

Steps to reproduce:

  1. Set the host to 0.0.0.0 to listen for connections on all interfaces by setting the host in firebase.json:
"emulators": {
    "database": {
      "host": "0.0.0.0",
      "port": 9000
    },
}
  1. Run the database emulator.
  2. Connect to it using a client on another computer by calling database().useEmulator(hostname, 9000).
  3. I don't know of a way to force using long polling instead of websockets. For me, I just drop the websocket connection and the SDK will automatically attempt to connect using long polling.
  4. Look in the network tab and you will see that the first request to /.lp will succeed and following requests will fail.

Relevant Code:

This is the code that changes the hostname based on the first response:

export function repoManagerApplyEmulatorSettings(
repo: Repo,
host: string,
port: number
): void {
repo.repoInfo_ = new RepoInfo(
`${host}:${port}`,
/* secure= */ false,
repo.repoInfo_.namespace,
repo.repoInfo_.webSocketOnly,
repo.repoInfo_.nodeAdmin,
repo.repoInfo_.persistenceKey,
repo.repoInfo_.includeNamespaceInQueryParams
);
if (repo.repoInfo_.nodeAdmin) {
repo.authTokenProvider_ = new EmulatorAdminTokenProvider();
}
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions