-
Notifications
You must be signed in to change notification settings - Fork 955
Description
[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:
- Set the host to
0.0.0.0
to listen for connections on all interfaces by setting the host infirebase.json
:
"emulators": {
"database": {
"host": "0.0.0.0",
"port": 9000
},
}
- Run the database emulator.
- Connect to it using a client on another computer by calling
database().useEmulator(hostname, 9000)
. - 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.
- 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:
firebase-js-sdk/packages/database/src/core/RepoManager.ts
Lines 70 to 88 in b6080a8
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(); | |
} | |
} |