Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

FinalHandler should return new responses #12

Conversation

weierophinney
Copy link
Member

If no error is present, and the response passed on invocation is different than the response at initialization, the FinalHandler should return that response intact.

This allows middleware to create a response, but pass it on to $next() for post-processing further up the chain. In particular, this is useful for things like routing middleware, so as to allow for application-wide concerns such as logging, finalizing sessions, etc., without requiring onion-style middleware for these behaviors.

This change requires loosening the typehinting to allow any PSR-7 response on invocation. In most cases, PSR-7 requests and responses are adequate, and having the decorated versions present in Stratigility simply provides some convenience. As such, this patch also loosens most typehints to hint on the PSR-7 interfaces; this does not present a BC break, however, as the original instances also pass this hint.

Essentially, this change allows something like the following:

$app->pipe(function ($req, $res, $next) {
    $response = new StringResponse('Hello!');
    return $next($req, $response);
});
$app->pipe(function ($req, $res, $next) {
    /* maybe log the request and response */
    return $next($req, $res);
});

Prior to this patch, while you could do the above, you would end up returning a 404 response at the end. The reason is that the middleware stack would become exhausted, leading to invocation of the FinalHandler; in the absence of an error, the FinalHandler returns a 404. With the patch, because the response passed to FinalHandler will be the response created and passed from the first middleware, FinalHandler will return that response instead.

@@ -23,33 +25,54 @@ class FinalHandler
private $options;

/**
* Original response provided to the middleware.
*
* @var null|Http\Response
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be null | ResponseInterface

@weierophinney weierophinney added this to the 1.1.0 milestone Jun 23, 2015
@weierophinney
Copy link
Member Author

Ping @ezimuel — this is the feature we discussed.

If no error is present, and the response passed on invocation is
different than the response at initialization, the `FinalHandler` should
return that response intact.

This allows middleware to create a response, but pass it on to `$next()`
for post-processing further up the chain. In particular, this is useful
for things like routing middleware, so as to allow for application-wide
concerns such as logging, finalizing sessions, etc., without requiring
onion-style middleware for these behaviors.
@weierophinney weierophinney force-pushed the feature/next-response-behavior branch from f147390 to e13dd06 Compare June 24, 2015 21:35
@ezimuel
Copy link

ezimuel commented Jun 25, 2015

@weierophinney I just tested this PR with this gist but it's not working. It seems that the condition here is not satisfied. Changing the body of the original response, using write(), doesn't affect the equal operator (===).

- Per @ezimuel, when the original response body has been written to,
  `FinalHandler` was still returning the 404 response. This patch
  ensures that if the body size changes, the response will still be
  returned.
@weierophinney
Copy link
Member Author

@ezimuel I've just pushed a change that checks to see if the response body size has changed; if it has, then FinalHandler will return the response.

@ezimuel
Copy link

ezimuel commented Jun 25, 2015

@weierophinney I'm not sure that checking the response body size will solve the issue, imagine that you change another value of the response, like the HTTP status, without changing the body, I think we should return the response as well.

@weierophinney
Copy link
Member Author

@ezimuel You cannot change the HTTP status without creating a new instance; the response object itself is immutable. The body is the only aspect of the response that is not immutable, and this is due to the fact that we cannot enforce immutability on what the Stream instance wraps (usually a PHP stream resource). So, in this case, our options are:

  • check for a different Response instance (which will be the case if any with*() operation is called on the original instance, or if a new instance is created).
  • check if the body size has changed (which indicates writing to the message body stream).

The only other condition that could indicate a change might be changes to stream metadata; however, I would consider that an edge case.

@ezimuel
Copy link

ezimuel commented Jun 25, 2015

@weierophinney ok, it sound reasonable. I don't know if we can find a better way to check against different PHP stream. Anyway, I checked your last commit with my gist example and it works fine!

@weierophinney weierophinney merged commit 69057f1 into zendframework:develop Jun 25, 2015
weierophinney added a commit that referenced this pull request Jun 25, 2015
@weierophinney weierophinney deleted the feature/next-response-behavior branch June 25, 2015 15:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants