Completed
Pull Request — master (#19)
by Stefano
03:43
created

LogTrait::logRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 14
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2018 ChannelWeb Srl, Chialab Srl
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 */
10
11
namespace BEdita\SDK;
12
13
use Monolog\Handler\StreamHandler;
14
use Monolog\Logger;
15
use Psr\Http\Message\RequestInterface;
16
use Psr\Http\Message\ResponseInterface;
17
18
/**
19
 * Basic SDK logging functions
20
 */
21
trait LogTrait
22
{
23
    /**
24
     * internal Logger
25
     *
26
     * @var null|Logger
27
     */
28
    protected $logger = null;
29
30
    /**
31
     * Get configured logger, may be null
32
     *
33
     * @return Logger|null
34
     * @codeCoverageIgnore
35
     */
36
    public function getLogger(): ?Logger
37
    {
38
        return $this->logger;
39
    }
40
41
    /**
42
     * Initialize and configure logger
43
     *
44
     * @param array $options Configuration options, 'log_file' key with log file path is mandatory
45
     * @return bool True on successful initialization, false otherwise
46
     */
47
    public function initLogger(array $options): bool
48
    {
49
        // 'path' to log file is mandatory
50
        if (empty($options['log_file'])) {
51
            return false;
52
        }
53
54
        $this->logger = new Logger('be4-php-sdk');
55
        $this->logger->pushHandler(new StreamHandler($options['log_file'], Logger::DEBUG));
56
57
        return true;
58
    }
59
60
    /**
61
     * Perform request log
62
     *
63
     * @param RequestInterface $request The request to log
64
     * @return void
65
     */
66
    public function logRequest(RequestInterface $request) : void
67
    {
68
        if (!$this->logger) {
69
            return;
70
        }
71
72
        $msg = sprintf(
73
            'Request: %s %s - Headers %s - Body %s',
74
            $request->getMethod(),
75
            $request->getUri(),
76
            $this->requestHeadersCleanup($request),
77
            $this->requestBodyCleanup($request)
78
        );
79
        $this->logger->info($msg);
80
    }
81
82
    /**
83
     * Return request body without sensitive information.
84
     *
85
     * @param RequestInterface $request The request to log
86
     * @return string
87
     */
88
    protected function requestBodyCleanup(RequestInterface $request) : string
89
    {
90
        $body = $request->getBody();
91
        if (empty((string)$body)) {
92
            return '(empty)';
93
        }
94
95
        $data = json_decode($body, true);
96
        foreach (['password', 'old_password', 'confirm-password'] as $p) {
97
            if (!empty($data[$p])) {
98
                $data[$p] = '***************';
99
            }
100
            if (!empty($data['data']['attributes'][$p])) {
101
                $data['data']['attributes'][$p] = '***************';
102
            }
103
        }
104
105
        return json_encode($data);
106
    }
107
108
    /**
109
     * Return request headers as string without sensitive information.
110
     *
111
     * @param RequestInterface $request The request to log
112
     * @return string
113
     */
114
    protected function requestHeadersCleanup(RequestInterface $request) : string
115
    {
116
        $headers = $request->getHeaders();
117
        foreach (['Authorization', 'X-Api-Key'] as $h) {
118
            if (!empty($headers[$h]) && !empty(array_diff($headers[$h], ['']))) {
119
                $headers[$h] = ['***************'];
120
            }
121
        }
122
123
        return json_encode($headers);
124
    }
125
126
    /**
127
     * Perform response log
128
     *
129
     * @param ResponseInterface $response The response to log
130
     * @return void
131
     */
132
    public function logResponse(ResponseInterface $response) : void
133
    {
134
        if (!$this->logger) {
135
            return;
136
        }
137
138
        $msg = sprintf(
139
            'Response: %s %s - Headers %s - Body %s',
140
            $response->getStatusCode(),
141
            $response->getReasonPhrase(),
142
            json_encode($response->getHeaders()),
143
            $this->responseBodyCleanup($response)
144
        );
145
        $this->logger->info($msg);
146
    }
147
148
    /**
149
     * Return response body without sensitive information.
150
     *
151
     * @param ResponseInterface $response The response to log
152
     * @return string
153
     */
154
    protected function responseBodyCleanup(ResponseInterface $response) : string
155
    {
156
        $body = $response->getBody();
157
        if (empty((string)$body)) {
158
            return '(empty)';
159
        }
160
161
        $data = json_decode($body, true);
162
        foreach (['jwt', 'renew'] as $tok) {
163
            if (!empty($data['meta'][$tok])) {
164
                $data['meta'][$tok] = '***************';
165
            }
166
        }
167
168
        return json_encode($data);
169
    }
170
}
171