Symfony 5.4 - 我应该如何使用 symfony 正确启动 mercure
Symfony 5.4 - How am i supposed to properly start mercure using symfony
我按照文档中的说明使用以下命令安装了 mercure:
composer require mercure
之后,我应该启动 mercure 服务器,问题是:如何?
Symfony 的文档没有说明这一点。
Mercure 的文档也没有说明任何相关内容,尤其是使用在 /config/packages/mercure.yaml
.
中生成的配置文件
我发现我需要下载一个单独的二进制文件(针对我的特定平台),然后我应该使用以下命令从 Powershell 启动服务器:
.\/bin/mercure run
但是,如果我尝试传递 -envfile ".env"
,那么它甚至不会尝试使用其中的任何变量。
最重要的是,它似乎根本没有使用任何环境变量,即使是我在 cmd 中定义的变量。
还有其他事情,比如我如何允许 CORS,因为我的配置文件中没有我可以更改的东西,它不是我可以传递给二进制文件的参数,我不能将它添加为一个环境变量。
如果我尝试订阅该事件(这是在 2019 端口上完成的,导致之前的问题),404 和 CORS 将被返回。
这也是我用 .\/bin/mercure run
:
得到的
我的.env
:
现在我想知道我应该如何使用 mercure,我看了几个 symfony 5.4 的视频,它们基本上都在 linux 上并且它以某种方式对他们有用或者它被标记作为配置更改、语法更改和其他的过时原因...
文档在这方面也没有任何帮助,这让我后悔尝试使用 mercure。
编辑:
有人告诉我尝试摆弄 Caddy 配置,但 mercure 似乎也没有尝试使用它们,甚至尝试使用 -config
.
指定配置
结果:
- 端口未设置为 3000
- 没有allow_corsheader
Caddyfile:
# Learn how to configure the Mercure.rocks Hub on https://mercure.rocks/docs/hub/config
{
{$GLOBAL_OPTIONS}
http_port 3000
https_port 3000
}
localhost:3000
route {
encode zstd gzip
@origin header Origin http://localhost:8000
header @origin Access-Control-Allow-Origin "http://localhost:8000"
header @origin Access-Control-Request-Method GET
header Access-Control-Allow-Credentials "true"
mercure {
# Publisher JWT key
publisher_jwt "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdfX0.iHLdpAEjX4BqCsHJEegxRmO-Y6sMxXwNATrQyRNt3GY"
subscriber_jwt "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyIqIl19fQ.0J4jgLQSHzPMTZ5jiYM8Yv7jmTANRgILG5FKY98LgEU"
publish_origins *
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
respond /healthz 200
respond "Not Found" 404
}
在这一点上,我觉得我正在使用书中的所有技巧,但它仍然不起作用,我可能最终会改用定期获取,可靠且实际工作。
更新 1:
- 服务器在端口 3000 上启动
- 现在允许 CORS
- 401 每当我尝试请求一个主题时
更新 2:
没有 HTTP 错误,事件显然是从 mercure 所说的订阅,但没有收到任何东西,告诉我 mercure 不支持语义
更新 3:
在更新中设置了诸如/update/test/{0}
的主题,事件源和yaml配置,客户端没有收到更新
更新 4:
无论有没有语义,我根本无法让更新工作,这是我的配置和路由 atm:
mercure.yaml :
mercure:
hubs:
default:
url: '%env(MERCURE_URL)%'
public_url: '%env(MERCURE_PUBLIC_URL)%'
jwt:
secret: '%env(MERCURE_JWT_SECRET)%'
publish: '["/update/test/*"]'
subscribe: '["/update/test/*"]'
我的路线(默认控制器):
#[Route('/update/test/{id}', name: 'test')]
public function test(HubInterface $hub, ?int $id): Response
{
$update = new Update("localhost:8000/update/test/{$id}",
son_encode(
array(
"result" => "success",
"data" => "User is in Room {$id}"
)
)
);
$hub->publish($update);
return new Response("Success");
}
我会给你一个 mercure 运行ning over windows 不使用 Docker 的例子,对不起我的英语好吗?!!
我将从使用 SSL 虚拟主机安装 symfony 5.4 开始:https://myshop.local 和 MercureBundle。
目标是当新产品进入商店库存时通知所有经过身份验证的用户。
首先:mercure hub 和您的站点必须 运行 在同一域或子域上,否则无法共享 auth cookie;所以我们的 mercure hub 将 运行 on https://myshop.local:3000(同一个域,但另一个端口,检查你的防火墙)
其次:需要设置合适的环境变量,所以在你的.env.local
:
###> symfony/mercure-bundle ###
# See https://symfony.com/doc/current/mercure.html#configuration
# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
MERCURE_URL=https://myshop.local:3000/.well-known/mercure
# The public URL of the Mercure hub, used by the browser to connect
MERCURE_PUBLIC_URL=https://myshop.local:3000/.well-known/mercure
# The secret used to sign the JWTs
MERCURE_JWT_SECRET=m3rcu353cr37pa55pra53DEV
###< symfony/mercure-bundle ###
第三:Mercure 它基于主题概念(如频道),因此您的 mercure.yaml
食谱:
mercure:
hubs:
default:
url: '%env(MERCURE_URL)%'
public_url: '%env(MERCURE_PUBLIC_URL)%'
jwt:
secret: '%env(MERCURE_JWT_SECRET)%'
publish: ['notif/new-on-stock'] # the topic or topics where the notifications will be published coming from the mercure hub.
subscribe: ['notif/new-on-stock'] # the topic or topics to which users will subscribe to receive notifications.
第四:需要下载mercure的Windows二进制文件,并在Caddy文件中设置一些配置:
# Learn how to configure the Mercure.rocks Hub on https://mercure.rocks/docs/hub/config
{
{$GLOBAL_OPTIONS}
}
{$SERVER_NAME:myshop.local:3000}
log
tls C:\wamp64\bin\apache\apache2.4.41\conf\ssl\myshop.local.crt C:\wamp64\bin\apache\apache2.4.41\conf\ssl\myshop.local.key
route {
encode zstd gzip
mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt://mercure.db}
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
cors_origins https://myshop.local
publish_origins https://myshop.local
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
respond /healthz 200
respond "Not Found" 404
}
这里有三个重要方面:
- $SERVER_NAME
- tls 指令:您必须设置 .crt 和 .key 的路径
您的虚拟主机的 SSL 证书文件。
- cors_origins 和 publish_origins 必须将您的 webapp 域设置为
避免 CORS 错误
第五:你必须 运行 你的 mercure 服务器 shell;从你的 mercure 二进制目录 运行: $env:MERCURE_PUBLISHER_JWT_KEY='m3rcu353cr37pa55pra53DEV';$env:MERCURE_SUBSCRIBER_JWT_KEY='m3rcu353cr37pa55pra53DEV';.\mercure.exe run -config .\Caddyfile
重要!!: 该密钥与环境变量 MERCURE_JWT_SECRET
相同
现在,您必须从控制器发布关于主题的通知:
public function publishNewProductAction(Symfony\Component\Mercure\HubInterface $mercureHub):Response{
/** insert new product to a database **/
...
$em->persist($newProduct);
$em->flush();
$data=['productName'=>$newProduct->getName(), 'productPrice'=>$newProduct->getPrice()];
$update = new Symfony\Component\Mercure\Update();
$hubUpdate = new Symfony\Component\Mercure\Update(
'notif/new-on-stock', # the topic where you go to publish
\json_encode($data), # the data that you want to publish on the mercure hub
true # indicate that need auth
);
return new Response('A new product has been registered!!'); # its the normal response to user that insert a product (admin user for exmple)
}
重要:symfony 创建 real-time 通知系统的真正力量在于将 Messenger 组件和异步队列与 Mercure 相结合。你可以调查一下。
因此,例如在客户端:
<script type="text/javascript">
$(document).ready(function () {
const eventSource = new EventSource("{{ mercure('notif/new-on-stock', { subscribe:'notif/out-of-stock'})|escape('js')}}", {withCredentials: true});
eventSource.onopen = function () {
console.log('Socket connection!');
};
eventSource.onmessage = function (e) {
var data = JSON.parse(e.data);
console.log('A new product is enable for you: '+data.productName+'. Price: $'+data.price);
};
eventSource.onerror = function () {
console.log('Socket error!');
};
});
</script>
您有一些错误。
首先:在你的 mercure.yaml 中,你必须以这种方式建立主题:
publish: ["update/test/{id}"] # your topic must complie with this format
subscribe: ["update/test/{id}"]
在您的环境变量中,您设置了 MERCURE_JWT_SECRET
,以及 mercure.yaml 中声明的主题和订阅者,symfony-mercure-bundle 完成了传递给中心的 JWT,您不需要不需要将其设置到 de Caddy 文件中。
并且,在您的函数中:
#[Route('/update/test/{id}', name: 'test')]
public function test(HubInterface $hub, ?int $id): Response
{
$update = new Update(sprintf("update/test/%s", $id)),
json_encode(
array(
"result" => "success",
"data" => sprintf("User is in Room %s", $id)
)
)
);
$hub->publish($update);
return new Response("Success");
}
考虑到作为Update参数传递的URI段,不包含字符'{}'
我按照文档中的说明使用以下命令安装了 mercure:
composer require mercure
之后,我应该启动 mercure 服务器,问题是:如何?
Symfony 的文档没有说明这一点。
Mercure 的文档也没有说明任何相关内容,尤其是使用在 /config/packages/mercure.yaml
.
我发现我需要下载一个单独的二进制文件(针对我的特定平台),然后我应该使用以下命令从 Powershell 启动服务器:
.\/bin/mercure run
但是,如果我尝试传递 -envfile ".env"
,那么它甚至不会尝试使用其中的任何变量。
最重要的是,它似乎根本没有使用任何环境变量,即使是我在 cmd 中定义的变量。
还有其他事情,比如我如何允许 CORS,因为我的配置文件中没有我可以更改的东西,它不是我可以传递给二进制文件的参数,我不能将它添加为一个环境变量。
如果我尝试订阅该事件(这是在 2019 端口上完成的,导致之前的问题),404 和 CORS 将被返回。
这也是我用 .\/bin/mercure run
:
我的.env
:
现在我想知道我应该如何使用 mercure,我看了几个 symfony 5.4 的视频,它们基本上都在 linux 上并且它以某种方式对他们有用或者它被标记作为配置更改、语法更改和其他的过时原因...
文档在这方面也没有任何帮助,这让我后悔尝试使用 mercure。
编辑:
有人告诉我尝试摆弄 Caddy 配置,但 mercure 似乎也没有尝试使用它们,甚至尝试使用 -config
.
结果:
- 端口未设置为 3000
- 没有allow_corsheader
Caddyfile:
# Learn how to configure the Mercure.rocks Hub on https://mercure.rocks/docs/hub/config
{
{$GLOBAL_OPTIONS}
http_port 3000
https_port 3000
}
localhost:3000
route {
encode zstd gzip
@origin header Origin http://localhost:8000
header @origin Access-Control-Allow-Origin "http://localhost:8000"
header @origin Access-Control-Request-Method GET
header Access-Control-Allow-Credentials "true"
mercure {
# Publisher JWT key
publisher_jwt "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdfX0.iHLdpAEjX4BqCsHJEegxRmO-Y6sMxXwNATrQyRNt3GY"
subscriber_jwt "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyIqIl19fQ.0J4jgLQSHzPMTZ5jiYM8Yv7jmTANRgILG5FKY98LgEU"
publish_origins *
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
respond /healthz 200
respond "Not Found" 404
}
在这一点上,我觉得我正在使用书中的所有技巧,但它仍然不起作用,我可能最终会改用定期获取,可靠且实际工作。
更新 1:
- 服务器在端口 3000 上启动
- 现在允许 CORS
- 401 每当我尝试请求一个主题时
更新 2:
没有 HTTP 错误,事件显然是从 mercure 所说的订阅,但没有收到任何东西,告诉我 mercure 不支持语义
更新 3:
在更新中设置了诸如/update/test/{0}
的主题,事件源和yaml配置,客户端没有收到更新
更新 4:
无论有没有语义,我根本无法让更新工作,这是我的配置和路由 atm:
mercure.yaml :
mercure:
hubs:
default:
url: '%env(MERCURE_URL)%'
public_url: '%env(MERCURE_PUBLIC_URL)%'
jwt:
secret: '%env(MERCURE_JWT_SECRET)%'
publish: '["/update/test/*"]'
subscribe: '["/update/test/*"]'
我的路线(默认控制器):
#[Route('/update/test/{id}', name: 'test')]
public function test(HubInterface $hub, ?int $id): Response
{
$update = new Update("localhost:8000/update/test/{$id}",
son_encode(
array(
"result" => "success",
"data" => "User is in Room {$id}"
)
)
);
$hub->publish($update);
return new Response("Success");
}
我会给你一个 mercure 运行ning over windows 不使用 Docker 的例子,对不起我的英语好吗?!!
我将从使用 SSL 虚拟主机安装 symfony 5.4 开始:https://myshop.local 和 MercureBundle。
目标是当新产品进入商店库存时通知所有经过身份验证的用户。
首先:mercure hub 和您的站点必须 运行 在同一域或子域上,否则无法共享 auth cookie;所以我们的 mercure hub 将 运行 on https://myshop.local:3000(同一个域,但另一个端口,检查你的防火墙)
其次:需要设置合适的环境变量,所以在你的.env.local
:
###> symfony/mercure-bundle ###
# See https://symfony.com/doc/current/mercure.html#configuration
# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
MERCURE_URL=https://myshop.local:3000/.well-known/mercure
# The public URL of the Mercure hub, used by the browser to connect
MERCURE_PUBLIC_URL=https://myshop.local:3000/.well-known/mercure
# The secret used to sign the JWTs
MERCURE_JWT_SECRET=m3rcu353cr37pa55pra53DEV
###< symfony/mercure-bundle ###
第三:Mercure 它基于主题概念(如频道),因此您的 mercure.yaml
食谱:
mercure:
hubs:
default:
url: '%env(MERCURE_URL)%'
public_url: '%env(MERCURE_PUBLIC_URL)%'
jwt:
secret: '%env(MERCURE_JWT_SECRET)%'
publish: ['notif/new-on-stock'] # the topic or topics where the notifications will be published coming from the mercure hub.
subscribe: ['notif/new-on-stock'] # the topic or topics to which users will subscribe to receive notifications.
第四:需要下载mercure的Windows二进制文件,并在Caddy文件中设置一些配置:
# Learn how to configure the Mercure.rocks Hub on https://mercure.rocks/docs/hub/config
{
{$GLOBAL_OPTIONS}
}
{$SERVER_NAME:myshop.local:3000}
log
tls C:\wamp64\bin\apache\apache2.4.41\conf\ssl\myshop.local.crt C:\wamp64\bin\apache\apache2.4.41\conf\ssl\myshop.local.key
route {
encode zstd gzip
mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt://mercure.db}
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
cors_origins https://myshop.local
publish_origins https://myshop.local
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
respond /healthz 200
respond "Not Found" 404
}
这里有三个重要方面:
- $SERVER_NAME
- tls 指令:您必须设置 .crt 和 .key 的路径 您的虚拟主机的 SSL 证书文件。
- cors_origins 和 publish_origins 必须将您的 webapp 域设置为 避免 CORS 错误
第五:你必须 运行 你的 mercure 服务器 shell;从你的 mercure 二进制目录 运行: $env:MERCURE_PUBLISHER_JWT_KEY='m3rcu353cr37pa55pra53DEV';$env:MERCURE_SUBSCRIBER_JWT_KEY='m3rcu353cr37pa55pra53DEV';.\mercure.exe run -config .\Caddyfile
重要!!: 该密钥与环境变量 MERCURE_JWT_SECRET
现在,您必须从控制器发布关于主题的通知:
public function publishNewProductAction(Symfony\Component\Mercure\HubInterface $mercureHub):Response{
/** insert new product to a database **/
...
$em->persist($newProduct);
$em->flush();
$data=['productName'=>$newProduct->getName(), 'productPrice'=>$newProduct->getPrice()];
$update = new Symfony\Component\Mercure\Update();
$hubUpdate = new Symfony\Component\Mercure\Update(
'notif/new-on-stock', # the topic where you go to publish
\json_encode($data), # the data that you want to publish on the mercure hub
true # indicate that need auth
);
return new Response('A new product has been registered!!'); # its the normal response to user that insert a product (admin user for exmple)
}
重要:symfony 创建 real-time 通知系统的真正力量在于将 Messenger 组件和异步队列与 Mercure 相结合。你可以调查一下。
因此,例如在客户端:
<script type="text/javascript">
$(document).ready(function () {
const eventSource = new EventSource("{{ mercure('notif/new-on-stock', { subscribe:'notif/out-of-stock'})|escape('js')}}", {withCredentials: true});
eventSource.onopen = function () {
console.log('Socket connection!');
};
eventSource.onmessage = function (e) {
var data = JSON.parse(e.data);
console.log('A new product is enable for you: '+data.productName+'. Price: $'+data.price);
};
eventSource.onerror = function () {
console.log('Socket error!');
};
});
</script>
您有一些错误。 首先:在你的 mercure.yaml 中,你必须以这种方式建立主题:
publish: ["update/test/{id}"] # your topic must complie with this format
subscribe: ["update/test/{id}"]
在您的环境变量中,您设置了 MERCURE_JWT_SECRET
,以及 mercure.yaml 中声明的主题和订阅者,symfony-mercure-bundle 完成了传递给中心的 JWT,您不需要不需要将其设置到 de Caddy 文件中。
并且,在您的函数中:
#[Route('/update/test/{id}', name: 'test')]
public function test(HubInterface $hub, ?int $id): Response
{
$update = new Update(sprintf("update/test/%s", $id)),
json_encode(
array(
"result" => "success",
"data" => sprintf("User is in Room %s", $id)
)
)
);
$hub->publish($update);
return new Response("Success");
}
考虑到作为Update参数传递的URI段,不包含字符'{}'