Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] parseDatabaseUrl removes path from URL #1091

Open
luchillo17 opened this issue Jun 3, 2023 · 12 comments
Open

[Bug] parseDatabaseUrl removes path from URL #1091

luchillo17 opened this issue Jun 3, 2023 · 12 comments

Comments

@luchillo17
Copy link

luchillo17 commented Jun 3, 2023

Bug Report

The parseDatabaseUrl function completely ignores the path, these URLs are stripped from path resulting in the wrong web socket request, this happens when we use Ingress to serve the load balancer from a path deeper than the root:

  • neo4j://localhost/neo4j/bolt gets transformed into localhost:7687, the port change kind of makes sense since the driver assumes the default port, but the path is missing.
  • neo4j://localhost:80/neo4j/bolt gets transformed into localhost:80 which breaks because I expected the web socket request to land in ws://localhost:80/neo4j/bolt.

To be more precise what I'm doing is deploying the neo4j helm chart & then using Ingress to put the load balancer service behind a path in the cluster, it is clear in the function the query is never introduced again into the URL:

image

Please note that query is being passed down but the path isn't.

Location of the function: https://github.com/neo4j/neo4j-javascript-driver/blob/5.0/packages/core/src/internal/url-util.ts#L93-L108

My Environment

image

software name version
OS Windows 10 WSL2 Ubuntu
Web browser Chrome 113.0.5672.129
node.js lts/gallium 16.20.0
npm 8.19.4
yarn 1.22.19
Neo4j Browser neo4j/neo4j-browser#1922
Neo4j -
@luchillo17 luchillo17 added the bug label Jun 3, 2023
@luchillo17
Copy link
Author

In case anyone is curious about my setup, the reason I had to use Ingress is because of a limitation on Docker Desktop on Windows, that doesn't forward the ports of the cluster to the host, however, another use case is what I mentioned, instead of a neo4j database available at root / we could route it with Ingress and put it under a path like example.com/app1/db.

https://gist.github.com/luchillo17/68c7496b0d5b0b9cd791c236f5924ad2

@bigmontz
Copy link
Contributor

bigmontz commented Jun 9, 2023

The driver connection url doesn't support paths.

Since the goal of the driver is keeping parity of functionality between different environments and languages, path in the url is not supported.

Supporting path can be handy for websockets since its api supported it. However, this feature is not supported by regular sockets.

About connection url see:
https://neo4j.com/docs/javascript-manual/current/connect-advanced/
https://neo4j.com/docs/java-manual/current/client-applications/#java-driver-connection-uris

@luchillo17
Copy link
Author

That's a bummer, though I do lack context on the other languages like Java & Python, so basically the closest thing would be to expose the DB with an Ingress that uses a subdomain instead of a path like db.example.com:7467 right?, wonder if I can make it work with nip.io DNS proxy ips...

@bigmontz
Copy link
Contributor

bigmontz commented Jun 9, 2023

Yes, you should use subdomains because they will be resolve via dns.

@luchillo17
Copy link
Author

It worked perfectly, thanks.

@luchillo17
Copy link
Author

luchillo17 commented Jun 10, 2023

Nevermind, Browser works fine, but the Driver doesn't, this is what I get from the error when connecting with the driver and Apollo GraphQL
Ingress HTTP port for browser: http://neo4j.[IP].nip.io/browser/
Ingress TCP port for db connection: bolt://bolt.[IP].nip.io:80
For some reason Browser needs to use bolt:// protocol instead of neo4j:// to connect properly, but no matter what I pass to the driver in my app, I get this error:

"Neo4jError: Server responded HTTP. Make sure you are not trying to connect to the http endpoint (HTTP defaults to port 7474 whereas BOLT defaults to port 7687)",
          "    at new Neo4jError (webpack-internal:///(sc_server)/../../node_modules/.pnpm/[email protected]/node_modules/neo4j-driver-core/lib/error.js:76:16)",
          "    at newError (webpack-internal:///(sc_server)/../../node_modules/.pnpm/[email protected]/node_modules/neo4j-driver-core/lib/error.js:108:12)",
          "    at parseNegotiatedResponse (webpack-internal:///(sc_server)/../../node_modules/.pnpm/[email protected]/node_modules/neo4j-driver-bolt-connection/lib/bolt/handshake.js:59:48)",
          "    at channel.onmessage (webpack-internal:///(sc_server)/../../node_modules/.pnpm/[email protected]/node_modules/neo4j-driver-bolt-connection/lib/bolt/handshake.js:106:39)",
          "    at Socket.eval (webpack-internal:///(sc_server)/../../node_modules/.pnpm/[email protected]/node_modules/neo4j-driver-bolt-connection/lib/channel/node/node-channel.js:167:26)",
          "    at Socket.emit (node:events:513:28)",
          "    at addChunk (node:internal/streams/readable:324:12)",
          "    at readableAddChunk (node:internal/streams/readable:297:9)",
          "    at Readable.push (node:internal/streams/readable:234:10)",
          "    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)",
          "    at TCP.callbackTrampoline (node:internal/async_hooks:130:17)"

@luchillo17
Copy link
Author

Here's what :debug has to say about my subdomain Ingress URL, not sure why Browser works but NodeJS Driver doesn't:
2023-06-10_00h15_27

@bigmontz
Copy link
Contributor

bigmontz commented Jun 19, 2023

This error means the driver is trying to connect to a http server. The NodeJS version of the driver doesn't make use of WebSockets. Neo4j Browser makes use of the javascript driver, but the driver uses websockets on the browsers.

@luchillo17
Copy link
Author

Makes no sense to me why it works ok when using kubectl port-forward svc/neo4j-db-lb-neo4j tcp-bolt http https but if I use Ingress to expose it, then it doesn't work

@luchillo17
Copy link
Author

luchillo17 commented Jun 21, 2023

If the driver can connect properly to the port-forwarded tcp-bolt but not to the same exposed through Ingress, either I'm configuring Ingress wrong or my Ingress implementation (nginx-ingress) can't handle the protocol...

@bigmontz
Copy link
Contributor

bigmontz commented Jun 27, 2023

You can try to curl or telnet bolt://bolt.[IP].nip.io:80, they are probably returning the http header.

@ojhughes
Copy link

ojhughes commented Jun 27, 2023

Hi @luchillo17

I just want to share this draft PR with you as it might be helpful.

We are planning to release a new Helm Chart that provides a thin wrapper over the HAProxy helm chart. This will allow standard Kubernetes Ingress to work well with a Neo4j deployment.
It's not ideal as it means an extra service to manage but it seems to work well so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants