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

Match topic selector on subscription endpoint #947

Open
oxodao opened this issue Sep 2, 2024 · 2 comments
Open

Match topic selector on subscription endpoint #947

oxodao opened this issue Sep 2, 2024 · 2 comments

Comments

@oxodao
Copy link

oxodao commented Sep 2, 2024

Hi,

I've been trying to get a list of users connected, and thought of using the subscription endpoint alongside with its SSE topics to be able to keep a list of online user by checking for subscriptions against /users/1234/notifications, where 1234 is the user id, which is a topic everyone on the app is always subscribing to.

On the worker which will be checking those, I'm generating a JWT with the subscribe * permissions then I call the endpoint:

$resp = $this->httpClient->request(
            'GET',
            'http://mercure/.well-known/mercure/subscriptions',
            [
                'headers' => [
                    'Authorization' => 'Bearer ' .$mercureJwt,
                ],
            ],
        );

I indeed get all the logged in users. But when I try to specify a topic selector to have only those subscription and not every subscription for every topic, I get an empty response...

 $resp = $this->httpClient->request(
            'GET',
            'http://mercure/.well-known/mercure/subscriptions/' . urlencode('/users/{*}/notifications'), // I've also tried with urlencode('/users/{id}/notifications') and urlencode('/users/*/notifications')
            [
                'headers' => [
                    'Authorization' => 'Bearer ' .$mercureJwt,
                ],
            ],
        );

Am I missing something or is there an issue ? I've seen this GH issue #706 but the proposed PR is merged and I'm running latest caddy/mercure hub

@dunglas
Copy link
Owner

dunglas commented Sep 2, 2024

Hi,

First of all, you need to use the absolute URI templates. Relative URLs will not work.

Aslo, prefer encoding with rawurlencode() instead of urlencode(), even if on this case this shouldn't matter.

If this doesn't fix the issue, could you please copy the full request and response please? (they are available in the HttpClient tab of the Symfony profiler).

Thanks,

@oxodao
Copy link
Author

oxodao commented Sep 3, 2024

Hi
Thanks for the answer, I was using the same topic on the submit and the subscription part, as the specs was saying a full iri was only recommended but I've updated my code to use a full URL and rawurlencode and I'm still having the issue.

The request from the browser is pretty standard:

GET /.well-known/mercure?topic=https%3A%2F%2Fapi.example.fr%2Fusers%2F447%2Fnotifications&topic=https%3A%2F%2Fapi.example.fr%2Fusers%2F447%2Froles HTTP/1.1
Accept: text/event-stream
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: fr-FR,fr;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Cookie: mercureAuthorization=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjUzNjU0NjAuNDA4NzMxLCJtZXJjdXJlIjp7InB1Ymxpc2giOltdLCJzdWJzY3JpYmUiOlsiaHR0cHM6Ly9hcGkuZXhhbXBsZS5mci91c2Vycy80NDcvbm90aWZpY2F0aW9ucyIsImh0dHBzOi8vYXBpLmV4YW1wbGUuZnIvdXNlcnMvNDQ3L3JvbGVzIl0sInBheWxvYWQiOnsidXNlcl9pZCI6NDQ3fX19.HL491qVWQMcFf5wSmw9RQNlcq4OCmDc4qHbc99hSgkE
Host: localhost:81
Origin: http://localhost:5173
Referer: http://localhost:5173/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"

Its response:

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:5173
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0
Connection: keep-alive
Content-Security-Policy: default-src 'self' mercure.rocks cdn.jsdelivr.net
Content-Type: text/event-stream
Expire: 0
Pragma: no-cache
Server: Caddy
Vary: Origin
X-Accel-Buffering: no
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Xss-Protection: 1; mode=block
Date: Tue, 03 Sep 2024 12:01:09 GMT
Transfer-Encoding: chunked

My call to the subscription API, while having a react app subscribed to "https://api.example.fr/users/447/notifications":

Request:
http://mercure/.well-known/mercure/subscriptions/https%3A%2F%2Fapi.example.fr%2Fusers%2F%2A%2Fnotifications

[▼
  "headers" => [▼
    "Authorization" => "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjUzNjU3NDUuMjM2NjU1LCJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdLCJzdWJzY3JpYmUiOlsiKiJdLCJwYXlsb2FkIjp7ImNvbW1hbmQiOiJteWNvbW1uZCJ9fX0.jmWBBXv90mTY5Eng59wVv4cYuUWUbMgs_0WS1m3Dqaw"
  ]
]

Response:

[▼
  "info" => [▼
    "header_size" => 345
    "request_size" => 444
    "total_time" => 0.003674
    "namelookup_time" => 0.001725
    "connect_time" => 0.002012
    "pretransfer_time" => 0.002075
    "size_download" => 263.0
    "speed_download" => 71584.0
    "download_content_length" => 263.0
    "starttransfer_time" => 0.002933
    "primary_ip" => "172.22.0.5"
    "primary_port" => 80
    "local_ip" => "172.22.0.7"
    "local_port" => 34924
    "http_version" => 2
    "protocol" => 1
    "scheme" => "HTTP"
    "connect_time_us" => 2012
    "namelookup_time_us" => 1725
    "pretransfer_time_us" => 2075
    "starttransfer_time_us" => 2933
    "total_time_us" => 3674
    "effective_method" => "GET"
    "capath" => "/etc/ssl/certs"
    "cainfo" => "/etc/ssl/certs/ca-certificates.crt"
    "start_time" => 1725365145.2405
    "original_url" => "http://mercure/.well-known/mercure/subscriptions/https%3A%2F%2Fapi.example.fr%2Fusers%2F%2A%2Fnotifications"
    "pause_handler" => [Closure(float $duration)](file:///application/vendor/symfony/http-client/Response/CurlResponse.php#L102) {#1007 ▶}
    "debug" => """
      *   Trying 172.22.0.5:80...
      * Connected to mercure (172.22.0.5) port 80 (#0)
      > GET /.well-known/mercure/subscriptions/https%3A%2F%2Fapi.example.fr%2Fusers%2F%2A%2Fnotifications HTTP/1.1
      Host: mercure
      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjUzNjU3NDUuMjM2NjU1LCJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdLCJzdWJzY3JpYmUiOlsiKiJdLCJwYXlsb2FkIjp7ImNvbW1hbmQiOiJteWNvbW1uZCJ9fX0.jmWBBXv90mTY5Eng59wVv4cYuUWUbMgs_0WS1m3Dqaw
      Accept: */*
      User-Agent: Symfony HttpClient (Curl)
      Accept-Encoding: gzip
      < HTTP/1.1 200 OK
      < Content-Security-Policy: default-src 'self' mercure.rocks cdn.jsdelivr.net
      < Content-Type: application/ld+json
      < Etag: urn:uuid:1a64bc80-2b6b-42e8-afbe-d169d9593e02
      < Server: Caddy
      < X-Content-Type-Options: nosniff
      < X-Frame-Options: DENY
      < X-Xss-Protection: 1; mode=block
      < Date: Tue, 03 Sep 2024 12:05:45 GMT
      < Content-Length: 263
      < 
      """
  ]
  "response_headers" => [▼
    "HTTP/1.1 200 OK"
    "Content-Security-Policy: default-src 'self' mercure.rocks cdn.jsdelivr.net"
    "Content-Type: application/ld+json"
    "Etag: urn:uuid:1a64bc80-2b6b-42e8-afbe-d169d9593e02"
    "Server: Caddy"
    "X-Content-Type-Options: nosniff"
    "X-Frame-Options: DENY"
    "X-Xss-Protection: 1; mode=block"
    "Date: Tue, 03 Sep 2024 12:05:45 GMT"
    "Content-Length: 263"
  ]
  "response_content" => [▼
    """
      {
        "@context": "https://mercure.rocks/",
        "id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fapi.example.fr%2Fusers%2F%2A%2Fnotifications",
        "type": "Subscriptions",
        "lastEventID": "urn:uuid:1a64bc80-2b6b-42e8-afbe-d169d9593e02",
        "subscriptions": []
      }
      """
  ]
]

One thing to note, is that when I am subscribed to the https://api.example.fr/users/*/notifications topic on my react app, I do see this subscription in the API call so my guess is that the * in the API call does not match 447 that the user is subscribed to for some reason. I've also tried with an {id} in place of the * but it does not work either

By the way, if I understood the specs correctly, I should be able to subscribe to the subscription event from my server but I'm not sure what the topic should be ? Having the EventSourceHttpClient url like https://mercure/.well-known/mercure?topic=/.well-known/mercure/subscriptions/https://api.example.fr/users/*/notifications with the topic url encoded ?

EDIT: According to the uri template tester, I should use the {id} instead of * but that does not work either

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

No branches or pull requests

2 participants