Question

I need to store my REST request within the file system - I have tried serializing the request object, but obviously the file size is quite a lot larger than the original.

I have run a test that allows me to store the payload as an object, then retrieve the data and un-serialize it. But as mentioned, not happy with the 10MB+ file size for a small payload of a few KB.

Is there any way I can get the original payload without extending the core? The only ways I can think to do it is either to BASE64 encode the original JSON data and pass it as a string - seems like a hack - perhaps enclose JSON in an XML field - but then it'd be an XML only REST method, which wouldn't be ideal.

Any ideas would be appreciated.

Was it helpful?

Solution

Serializing the object will most likely serialize the entire PHP Object. That's the reason why you end up with a massive file. You only want to log the payload from that request.

I've wrote a module once that would log all API requests to the database for debugging purposes. The way I did it was with a plugin around the dispatch()-method of \Magento\Webapi\Controller\Rest. This is the code:

class Rest
{
    /**
     * @var Auto
     */
    protected $autoLogger;

    /**
     * @var ConfigHelper
     */
    protected $configHelper;

    /**
     * Rest constructor.
     * @param Auto $autoLogger
     */
    public function __construct(
        Auto $autoLogger,
        ConfigHelper $configHelper
    )
    {
        $this->autoLogger = $autoLogger;
        $this->configHelper = $configHelper;
    }

    /**
     * @param \Magento\Webapi\Controller\Rest $subject
     * @param callable $proceed
     * @param \Magento\Framework\App\RequestInterface|\Magento\Framework\Webapi\Rest\Request $request
     * @return mixed
     */
    public function aroundDispatch(
        \Magento\Webapi\Controller\Rest $subject,
        callable $proceed,
        \Magento\Framework\App\RequestInterface $request
    ) {
        if ($this->configHelper->isEnableApiDebugging()) {
            $this->autoLogger->setTitle('API: ' . $request->getPathInfo());
            $this->autoLogger->setType('API Debugger');
            try {
                $this->autoLogger->add('Request: ' . $request->getPathInfo());

                $params = [];
                foreach ($request->getParams() as $key => $value) {
                    $params[] = $key . ': ' . $value;
                }
                $this->autoLogger->add("Params:\n  " . implode("\n  ", $params));

                $headers = [];
                try {
                    foreach ($request->getHeaders() as $header) {
                        $headers[] = $header->toString();
                    }
                } catch (\Exception $exception) {
                    // Fail silently ...
                }

                $this->autoLogger->add("Headers:\n  " . implode("\n  ", $headers));
                if ($this->isAuthorizationRequest($request->getPathInfo())) {
                    $this->autoLogger
                        ->add("Body:\n  (Authorization request body is not logged because it contains the password)");
                } else {
                    $this->autoLogger->add('Body: ' . $request->getContent());
                }
            } catch (\Exception $exception) {
                $this->autoLogger->add(
                    'Exception before logging API request: ' . $exception->getMessage() . ' (' .
                        $exception->getFile() . '::' . $exception->getLine() . ')',
                    Log::LEVEL_ERROR
                );
            }
        }

        /** @var \Magento\Framework\Webapi\Rest\Response $returnValue */
        $returnValue = $proceed($request);

        if ($this->configHelper->isEnableApiDebugging()) {
            try {
                if ($this->isAuthorizationRequest($request->getPathInfo())) {
                    $this->autoLogger
                        ->add("Response:\n  (Response is not logged because it contains the authorization key)");
                } else {
                    $this->autoLogger->add('Response: ' . $returnValue->getBody());
                }
            } catch(\Exception $exception) {
                $this->autoLogger->add(
                    'Exception after logging API request: ' . $exception->getMessage(),
                    Log::LEVEL_ERROR
                );
            }
        }

        return $returnValue;
    }

    /**
     * @param string $pathInfo
     * @return bool
     */
    protected function isAuthorizationRequest(string $pathInfo) : bool
    {
        return preg_match('/integration\/(admin|customer)\/token/', $pathInfo) !== 0;
    }
}

The $autoLogger in this example is a class that would simply write data to the database. You could do something similar by writing it to a file or something.

Perhaps this can be of some help for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top