v5 - Fix process state in long-lived runtimes - #3469
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Small correctness fixes for leftover process state and empty JSON error bodies. These show up hardest under persistent workers (FrankenPHP, RoadRunner, Swoole) because the PHP process is reused.
Slim 5 already avoids storing the last request on
App. This PR only fixes real leftover-state bugs and one encoding hole. It does not lock routes, close response streams, or change logging.Fixed
Output buffering leaks across requests
OutputBufferingMiddlewareusedob_get_clean()/ob_end_clean(), which pop only the innermost buffer.If a view, PDF lib, or
echopath started a nested buffer and did not close it (or threw), Slim popped the nested one and left its own buffer installed. In a worker that buffer — and any string still in it — lived until the process was killed.It now records
ob_get_level()and pops back to that level on both success and exception.Error handler left installed after the first request
ErrorExceptionMiddlewareonly calledrestore_error_handler()whenset_error_handler()returned a previous handler.On the first request that value is
null, so restore was skipped. Slim’s “turn PHP errors intoErrorException” handler stayed installed for the rest of the process, including between requests.It now always restores.
Empty JSON error body on invalid UTF-8
json_encode()returnsfalsewhen any string contains invalid UTF-8. An exception message with raw bytes (common when user input is echoed into the exception) produced a zero-length body withContent-Type: application/json. Clients then failed to parse the error.JSON_PARTIAL_OUTPUT_ON_ERRORdoes not coverJSON_ERROR_UTF8. AddedJSON_INVALID_UTF8_SUBSTITUTEso invalid sequences become U+FFFD and the payload stays valid JSON.Same fix as #3465 on 4.x (
JsonErrorRenderer); v5’s equivalent isJsonExceptionMiddleware.Changed (breaking)
Route arguments no longer live on
RouteRemoved
RouteInterface::getArgument(),getArguments(), andsetArguments().Slim 5 already puts match args on a per-request
RouteMatch. TheRouteinstance is the FastRoute handler and lives for the process lifetime.setArguments()wrote request-shaped data onto that shared object, so one request’s args could be read on the next. The framework never called these methods.Get args from:
$argsarray$request->getAttribute(RouteMatch::class)RoutingArgumentsMiddleware