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

Problem with namespaces and regex #4615

Closed
ksowa opened this issue Jan 26, 2023 · 4 comments
Closed

Problem with namespaces and regex #4615

ksowa opened this issue Jan 26, 2023 · 4 comments
Labels
question Further information is requested
Milestone

Comments

@ksowa
Copy link

ksowa commented Jan 26, 2023

Describe the bug
There seems to be a problem with connection callback on the server if the following occur:

  1. Server uses dynamic namespaces (e.g. io.of(/^.*$/)...)
  2. Server sends a message to the namespace before any client connects to that namespace
  3. When at this point client connects to the server, the connection callback is not triggerred

To Reproduce

Socket.IO server version: 4.5.4

Server

import { Server } from "socket.io";

const io = new Server(3000, {
    cors: {
        origin: (origin, callback) => callback(null, origin),
    },
});

io.of(/^.*$/).on('connection', (socket) => {
    console.log('Connected!', socket.id);
});

io.of('testing/namespace').emit('message', 'testing message');

Socket.IO client version: 4.5.4

Client

import { io } from "socket.io-client";

const socket = io("ws://localhost:3000/testing/namespace", {});

socket.on("connect", () => {
  console.log(`connect ${socket.id}`);
});

Expected behavior

The connection callback should be triggered regardless if the first message has been emitted to the namespace before or after any clients connect to that namespace.

Additional context

If we change the server code to the below, it works without any problem.

(first message emitted after first client connects)

const {Server} = require('socket.io');

const io = new Server(3000, {
    cors: {
        origin: (origin, callback) => callback(null, origin),
    },
});

io.of(/^.*$/).on('connection', (socket) => {
    console.log('Connected!', socket.id);
    io.of('testing/namespace').emit('message', 'test');
});

OR (namespace is not dynamic):

const {Server} = require('socket.io');

const io = new Server(3000, {
    cors: {
        origin: (origin, callback) => callback(null, origin),
    },
});

io.of('testing/namespace').on('connection', (socket) => {
    console.log('Connected!', socket.id);
});

io.of('testing/namespace').emit('message', 'test');

OR (client connecting to another namespace):

import { io } from "socket.io-client";

const socket = io("ws://localhost:3000/some/other/namespace", {});

socket.on("connect", () => {
  console.log(`connect ${socket.id}`);
});
@ksowa ksowa added the to triage Waiting to be triaged by a member of the team label Jan 26, 2023
@darrachequesne
Copy link
Member

I could indeed reproduce the issue, thanks. This is a known limitation with dynamic namespaces, any existing static namespaces have the priority over the dynamic ones.

We could maybe fix this by running the regex against any existing namespaces:

io.of('test1');

io.of(/^.*$/); // add test1 as a child of the parent namespace (since it matches the regex)

io.of('test2'); // add test2 as a child of the parent namespace (since it matches the regex)

That might be a surprising behavior for the end users though. What do you think?

Related: #4164

@darrachequesne darrachequesne added question Further information is requested and removed to triage Waiting to be triaged by a member of the team labels Feb 14, 2023
darrachequesne added a commit that referenced this issue Feb 20, 2023
Namespaces that match the regex of a parent namespace will now be added
as a child of this namespace:

```js
const parentNamespace = io.of(/^\/dynamic-\d+$/);
const childNamespace = io.of("/dynamic-101");
```

Related:

- #4615
- #4164
- #4015
- #3960
@darrachequesne
Copy link
Member

@ksowa this should be fixed by 0d0a7a2, included in version 4.6.1.

A namespace whose name matches the regex of a parent namespace will now be added as a child of this namespace:

const parentNamespace = io.of(/^\/dynamic-\d+$/);

parentNamespace.on("connection", (socket) => {
  console.log(`connection on namespace ${socket.nsp.name}`);
});

And then somewhere else:

io.of("/dynamic-101");

Could you please check?

@darrachequesne darrachequesne added this to the 4.6.1 milestone Feb 20, 2023
@ksowa
Copy link
Author

ksowa commented Feb 20, 2023

@darrachequesne it is indeed fixed in 4.6.1! Thank you for the very fast reaction!

@darrachequesne
Copy link
Member

Awesome, thanks for the feedback 👍

haneenmahd pushed a commit to haneenmahd/socket.io that referenced this issue Apr 15, 2023
Namespaces that match the regex of a parent namespace will now be added
as a child of this namespace:

```js
const parentNamespace = io.of(/^\/dynamic-\d+$/);
const childNamespace = io.of("/dynamic-101");
```

Related:

- socketio#4615
- socketio#4164
- socketio#4015
- socketio#3960
dzad pushed a commit to dzad/socket.io that referenced this issue May 29, 2023
Namespaces that match the regex of a parent namespace will now be added
as a child of this namespace:

```js
const parentNamespace = io.of(/^\/dynamic-\d+$/);
const childNamespace = io.of("/dynamic-101");
```

Related:

- socketio#4615
- socketio#4164
- socketio#4015
- socketio#3960
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants