private function createBody(
        IHttpRequestMessage $request,
        $rawBody,
        ContentNegotiationResult &$contentNegotiationResult = null
    ): ?IHttpBody {
        if ($rawBody === null || $rawBody instanceof IHttpBody) {
            return $rawBody;
        }

        if ($rawBody instanceof IStream) {
            return new StreamBody($rawBody);
        }

        if (is_scalar($rawBody)) {
            return new StringBody((string)$rawBody);
        }

        if ((!is_object($rawBody) && !is_array($rawBody)) || is_callable($rawBody)) {
            throw new InvalidArgumentException('Unsupported body type ' . gettype($rawBody));
        }

        $type = TypeResolver::resolveType($rawBody);
        $contentNegotiationResult = $this->contentNegotiator->negotiateResponseContent($type, $request);
        $mediaTypeFormatter = $contentNegotiationResult->getFormatter();

        if ($mediaTypeFormatter === null) {
            throw $this->createNotAcceptableException($type);
        }

        $bodyStream = new Stream(fopen('php://temp', 'r+b'));

        try {
            $mediaTypeFormatter->writeToStream(
                $rawBody,
                $bodyStream,
                $contentNegotiationResult->getEncoding()
            );
        } catch (SerializationException $ex) {
            throw new HttpException(
                HttpStatusCodes::HTTP_INTERNAL_SERVER_ERROR,
                'Failed to serialize response body',
                0,
                $ex
            );
        }

        return new StreamBody($bodyStream);
    }