1

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.

1 Answer 1

3

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.

3
  • I think that is a great idea. I suppose I can add a plugin, and implement payload save when a particular service is called.
    – BAF
    May 17, 2017 at 12:58
  • Update - did some testing and found that $request->getContent() does return the request in JSON format - so that I can store it. Thanks again Giel.
    – BAF
    May 17, 2017 at 14:15
  • just one more question. Where is getContent() method defined? I checked in \Magento\Framework\App\RequestInterface and it wasn't defined in there.
    – BAF
    May 17, 2017 at 15:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.