Skip to content

SendApiProblemResponseListener modifies content #2

@weierophinney

Description

@weierophinney

I have noticed, that SendApiProblemResponseListener is modifying the response content AFTER sending headers (if display_exceptions is enabled).

I have a Content-Length header based on response content but this header is now responding a wrong length as it doesn't know if the content gets modified afterwords.

On the same time I'm automatically pretty printing the response if the request contains header X-Pretty: 1 but this will also be ignored as the content gets rewritten in this case.

What is the reason to overwrite HttpResponseSender instead of listening on EVENT_FINISH?

This is my broken code:

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $eventManager  = $e->getApplication()->getEventManager();
        $eventManager->attach(MvcEvent::EVENT_FINISH, [$this, 'onFinish'], -1000);
    }

    public function onFinish(MvcEvent $event)
    {
        $response = $event->getResponse();
        $request  = $event->getRequest();

        if ($request instanceof HttpRequest && $response instanceof HttpResponse && !($response instanceof HttpStreamResponse)) {
            $rqHeaders = $request->getHeaders();
            $rsHeaders = $response->getHeaders();
            $rsContent = $response->getContent();

            // pretty print JSON response
            if ($rqHeaders->has('X-Pretty')
                && $rqHeaders->get('X-Pretty')->getFieldValue() === '1'
                && is_string($rsContent) && $rsContent
                && $rsHeaders->has('Content-Type')
                && preg_match('/^application\\/(.*\\-)?json/', $rsHeaders->get('Content-Type')->getFieldValue())
            ) {
                $rsContentDecode = json_decode($rsContent);
                if ($rsContentDecode !== null) {
                    $prettyOptions = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
                    $rsContent     = json_encode($rsContentDecode, $prettyOptions);
                    $response->setContent($rsContent);

                    if ($rsHeaders->has('Content-Length')) {
                        $rsHeaders->removeHeader($rsHeaders->get('Content-Length'));
                    }
                    $rsHeaders->addHeaderLine('Content-Length', strlen($rsContent));
                }
            }

            // Send Content-Length header if possible
            if (is_string($rsContent) && !$rsHeaders->has('Content-Length')) {
                $rsHeaders->addHeaderLine('Content-Length', strlen($rsContent));
            }
        }
    }
}

Originally posted by @marc-mabe at zfcampus/zf-api-problem#54

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions