Completed
Pull Request — master (#1867)
by
unknown
02:27
created

MessageFormatter   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 146
rs 9.44
c 0
b 0
f 0
wmc 37
lcom 1
cbo 3

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 2
F format() 0 104 33
A headers() 0 9 2
1
<?php
2
namespace GuzzleHttp;
3
4
use Psr\Http\Message\MessageInterface;
5
use Psr\Http\Message\RequestInterface;
6
use Psr\Http\Message\ResponseInterface;
7
8
/**
9
 * Formats log messages using variable substitutions for requests, responses,
10
 * and other transactional data.
11
 *
12
 * The following variable substitutions are supported:
13
 *
14
 * - {request}:        Full HTTP request message
15
 * - {response}:       Full HTTP response message
16
 * - {ts}:             ISO 8601 date in GMT
17
 * - {date_iso_8601}   ISO 8601 date in GMT
18
 * - {date_common_log} Apache common log date using the configured timezone.
19
 * - {host}:           Host of the request
20
 * - {method}:         Method of the request
21
 * - {uri}:            URI of the request
22
 * - {version}:        Protocol version
23
 * - {target}:         Request target of the request (path + query + fragment)
24
 * - {hostname}:       Hostname of the machine that sent the request
25
 * - {code}:           Status code of the response (if available)
26
 * - {phrase}:         Reason phrase of the response  (if available)
27
 * - {error}:          Any error messages (if available)
28
 * - {req_header_*}:   Replace `*` with the lowercased name of a request header to add to the message
29
 * - {res_header_*}:   Replace `*` with the lowercased name of a response header to add to the message
30
 * - {req_headers}:    Request headers
31
 * - {res_headers}:    Response headers
32
 * - {req_body}:       Request body
33
 * - {res_body}:       Response body
34
 */
35
class MessageFormatter
36
{
37
    /**
38
     * Apache Common Log Format.
39
     * @link http://httpd.apache.org/docs/2.4/logs.html#common
40
     * @var string
41
     */
42
    const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
43
    const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
44
    const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
45
46
    /** @var string Template used to format log messages */
47
    private $template;
48
49
    /**
50
     * @param string $template Log message template
51
     */
52
    public function __construct($template = self::CLF)
53
    {
54
        $this->template = $template ?: self::CLF;
55
    }
56
57
    /**
58
     * Returns a formatted message string.
59
     *
60
     * @param RequestInterface  $request  Request that was sent
61
     * @param ResponseInterface $response Response that was received
62
     * @param \Exception        $error    Exception that was received
63
     *
64
     * @return string
65
     */
66
    public function format(
67
        RequestInterface $request,
68
        ResponseInterface $response = null,
69
        \Exception $error = null
70
    ) {
71
        $cache = [];
72
73
        return preg_replace_callback(
74
            '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
75
            function (array $matches) use ($request, $response, $error, &$cache) {
76
                if (isset($cache[$matches[1]])) {
77
                    return $cache[$matches[1]];
78
                }
79
80
                $result = '';
81
                switch ($matches[1]) {
82
                    case 'request':
83
                        $result = Psr7\str($request);
84
                        break;
85
                    case 'response':
86
                        $result = $response ? Psr7\str($response) : '';
87
                        break;
88
                    case 'req_headers':
89
                        $result = trim($request->getMethod()
90
                                . ' ' . $request->getRequestTarget())
91
                            . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
92
                            . $this->headers($request);
93
                        break;
94
                    case 'res_headers':
95
                        $result = $response ?
96
                            sprintf(
97
                                'HTTP/%s %d %s',
98
                                $response->getProtocolVersion(),
99
                                $response->getStatusCode(),
100
                                $response->getReasonPhrase()
101
                            ) . "\r\n" . $this->headers($response)
102
                            : 'NULL';
103
                        break;
104
                    case 'req_body':
105
                        $result = $request->getBody();
106
                        break;
107
                    case 'res_body':
108
                        $result = $response ? $response->getBody() : 'NULL';
109
                        break;
110
                    case 'ts':
111
                    case 'date_iso_8601':
112
                        $result = gmdate('c');
113
                        break;
114
                    case 'date_common_log':
115
                        $result = date('d/M/Y:H:i:s O');
116
                        break;
117
                    case 'method':
118
                        $result = $request->getMethod();
119
                        break;
120
                    case 'version':
121
                        $result = $request->getProtocolVersion();
122
                        break;
123
                    case 'uri':
124
                    case 'url':
125
                        $result = $request->getUri();
126
                        break;
127
                    case 'target':
128
                        $result = $request->getRequestTarget();
129
                        break;
130
                    case 'req_version':
131
                        $result = $request->getProtocolVersion();
132
                        break;
133
                    case 'res_version':
134
                        $result = $response
135
                            ? $response->getProtocolVersion()
136
                            : 'NULL';
137
                        break;
138
                    case 'host':
139
                        $result = $request->getHeaderLine('Host');
140
                        break;
141
                    case 'hostname':
142
                        $result = gethostname();
143
                        break;
144
                    case 'code':
145
                        $result = $response ? $response->getStatusCode() : 'NULL';
146
                        break;
147
                    case 'phrase':
148
                        $result = $response ? $response->getReasonPhrase() : 'NULL';
149
                        break;
150
                    case 'error':
151
                        $result = $error ? $error->getMessage() : 'NULL';
152
                        break;
153
                    default:
154
                        // handle prefixed dynamic headers
155
                        if (strpos($matches[1], 'req_header_') === 0) {
156
                            $result = $request->getHeaderLine(substr($matches[1], 11));
157
                        } elseif (strpos($matches[1], 'res_header_') === 0) {
158
                            $result = $response
159
                                ? $response->getHeaderLine(substr($matches[1], 11))
160
                                : 'NULL';
161
                        }
162
                }
163
164
                $cache[$matches[1]] = $result;
165
                return $result;
166
            },
167
            $this->template
168
        );
169
    }
170
171
    private function headers(MessageInterface $message)
172
    {
173
        $result = '';
174
        foreach ($message->getHeaders() as $name => $values) {
175
            $result .= $name . ': ' . implode(', ', $values) . "\r\n";
176
        }
177
178
        return trim($result);
179
    }
180
}
181