$response->getBody()->write(json_encode($res));
// also set content type if you are not doing so elsewhere
$response = $response->withHeader('Content-Type', 'application/json;charset=utf-8')
return $response; // important to return the response object
// or Slim specific:
return $response->withJson($res);

Ohw I see, that is what's happening. It seems subRequest uses the request from the container, which is the same one the app itself uses (conainer returns the same instance of response if pulled twice). This architecture is something that bugged Slim before and there are plans to remove the request and response object from the container as they do not belong there.

I think passing a new response instance into the subRequest will also do the job.

My reason for asking on this is same as acidvertigo's, when I do $response->withJson($data), the JSON is displayed since I'm returning the response from the front-end. I need the response from the /api/v1/login endpoint to be a different response than the /login front-end route's.

We are removing subRequest as it does not fit well with proper code design.

In instances where one might need a "sub" request, it is almost always the wrong design choice to resend an HTTP Request through Slim again. Typically we remove features that are not considered good practice with every Major release [ Slim 2 => 3 we removed service location ... as an example ].