Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

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