Conversation
6cacc6a to
2aacd4c
Compare
alexandre-daubois
left a comment
There was a problem hiding this comment.
I know it's a draft so feel free close anything that was already planned to be fixed 馃檪
Publish-side validation is part of the protocol now: report what Update.Validate() rejects (reserved topics and event types, forbidden event IDs, invalid UTF-8 data) as a ValueError carrying the reason, and the dispatch failures as a RuntimeException. The subscribe query parameter becomes "match", so hot reloading advertises its topic with it. The publisher_jwt and subscriber_jwt directives now require the compatibility mode, which drops the audience, expiration and issuer checks: bind the keys to a trusted issuer instead.
The publisher_jwt and subscriber_jwt directives only work in the compatibility mode of the hub, which FrankenPHP is built without. Octane writes every entry of the mercure array as a Caddyfile line, so the issuer block is passed as a multi-line value.
Like the official Mercure binaries and images, ship the deprecated_topic and deprecated_claim build tags so protocol_version_compatibility 8 can accept 0.x tokens and topic selectors during a migration. The hub stays in modern mode unless the directive is set. Static builds go through static-php-cli, which sets the tags itself and needs a matching change.
MERCURE_TRUSTED_ISSUERS is a list separated by commas or whitespace, each identifier bound to the same publisher and subscriber keys.
2aacd4c to
7fb6208
Compare
The caddy module only takes what Mercure 1.0.0 requires: a broader bump outruns the versions Caddy 2.11.4 compiles against (automemlimit, cel-go).
The hub validates the update in Publish(), so the extra Validate() call is dropped and its error is classified with errors.Is against the exported sentinels, then raised through zend_argument_value_error() with the position of the argument at fault. Non-string topics are rejected in C with the standard TypeError wording instead of a Go type name. Tests cover the missing hub, a failing transport, the invalid id and the non-string topic cases.
symfony/mercure 0.8 requires the sub and client_id claims of RFC 9068 and the Hub must be told the protocol version to write the 1.0 cookie.
7fb6208 to
6c8e74e
Compare
The protocol requires the hub to assign an ID to every update, so an empty one is a transport bug rather than a case to handle.
alexandre-daubois
left a comment
There was a problem hiding this comment.
Congrats on the 1.0 release! 馃帀
|
|
||
| if (Z_TYPE_P(topics) == IS_ARRAY) { | ||
| zval *topic; | ||
| ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(topics), topic) { |
There was a problem hiding this comment.
This tests Z_TYPE_P(topic) without a deref, so an array holding a reference such as ['a', &$b] is rejected, and because zend_zval_type_name() does deref the message reads must only contain strings, string given. You can ZVAL_DEREF(topic) before the check and handle IS_REFERENCE in goValue(), which GoPackedArray() needs to read the element.
| Key: mercureSubscriberJwtKey, | ||
| }, | ||
| }, | ||
| mercureCaddy.Mercure{Issuers: issuers}, |
There was a problem hiding this comment.
Neither PublicURLs nor ResourceIdentifier is set, so the aud the hub now requires comes from r.Host, and php-server builds a catch-all site whenever --domain is empty. It may be worth deriving public_urls from --domain, or pinning resource_identifier, so a client cannot pick the audience its own token is checked against.
|
|
||
| /** | ||
| * @param string|string[] $topics | ||
| * @param string|string[] $topics The first topic is the canonical one, the others are alternate topics |
There was a problem hiding this comment.
The stub hash recorded in frankenphp_arginfo.h is still 60f0d27c04f94d7b24c052e91ef294595a2bc421, while this file now hashes to 85fabd314ab885307e0032b9f7635fa13cc0c4b5, so the generated header is stale. Running gen_stub.php again would resync it before the next contributor regenerates and gets an unrelated diff.
| # # MERCURE_TRUSTED_ISSUERS to the stable identifier of your token issuer | ||
| # # (your app's URL for self-issued tokens). Add more issuer blocks through | ||
| # # MERCURE_EXTRA_DIRECTIVES. | ||
| # issuer {$MERCURE_TRUSTED_ISSUERS:https://localhost} { |
There was a problem hiding this comment.
This takes a single identifier, so MERCURE_TRUSTED_ISSUERS="https://a https://b" expands to a stray token ahead of the block, while docs/mercure.md:59 documents the same variable as a comma or space separated list. Scoping that sentence to php-server, the one path that splits the value, would keep the two contracts apart.
| Subscribers matching the canonical topic or any of the alternate topics receive the update. | ||
| The returned string is the ID of the update, to be used as `Last-Event-ID` to resume a stream. | ||
|
|
||
| `mercure_publish()` throws a `ValueError` when the update violates the protocol, notably when: |
There was a problem hiding this comment.
The list leaves out the two checks this change adds in C, a ValueError on a negative $retry and a TypeError on a $topics array holding a non-string, both pinned in mercure_test.go. Adding them would cover every rejection the function can raise.
golang.org/x/net v0.59.0 deprecates http2.Transport in favor of http.Transport with Protocols, which staticcheck now flags.
Upgrades
github.com/dunglas/mercureandgithub.com/dunglas/mercure/caddyfromv0.24.2tov1.0.0, and adapts the integration to the protocol changes of draft-dunglas-mercure-08.mercure_publish()The hub validates updates before dispatching them, so the function now distinguishes the caller's mistakes from a failed publication:
ValueErrorcarrying the reason for a topic addressing the reserved/.well-known/mercurenamespace or equal to*, an$idstarting with#or equal toearliest, a$typeequal tomercure, control characters, invalid UTF-8$data, or no topic at all;RuntimeExceptionwith the message of the hub when the dispatch fails.The negative values of
$retryare also rejected, as the protocol only allows digits in that field.An enum in
frankenphp.hreplaces the status codesgo_mercure_publish()returned as bare integers. On the way, an array of topics that cannot be converted no longer reportsNo Mercure hub configured.Hot reloading
The subscribe query parameter of the protocol is
match, so$_SERVER['FRANKENPHP_HOT_RELOAD']advertises/.well-known/mercure?match=<topic>. Thetopicparameter it replaces is only honored by a hub built with thedeprecated_topictag, which FrankenPHP doesn't set.Hub configuration
Setting
publisher_jwtorsubscriber_jwtwithoutprotocol_version_compatibilityis a configuration error now, because that mode also drops the requiredexp, the audience check, theat+jwtcheck and the issuer check. The keys are bound to a trusted issuer instead:php-server --mercureand the sampleCaddyfilefollow.MERCURE_TRUSTED_ISSUERSaccepts several identifiers separated by commas or whitespace, all bound to the same keys.FrankenPHP is built with the
deprecated_topicanddeprecated_claimtags of the hub, like the official Mercure binaries, soprotocol_version_compatibility 8accepts the 0.x tokens andtopic=selectors during a migration. Static builds get the tags through static-php-cli: crazywhalecc/static-php-cli#1240.Docs
docs/mercure.mdand the Laravel Octane section ofdocs/laravel.mddescribe the 1.0 configuration. Octane writes each entry of itsmercurearray as aCaddyfileline, so theissuerblock is passed as a multi-line value (verified withcaddy adaptand a live hub). The Symfony example targets symfony/mercure 0.8, which shipsProtocolVersion::V1.The translations of
docs/mercure.mdanddocs/laravel.mdstill describe the 0.x configuration.The other Go dependencies are updated on the way.