1<?php 2 3namespace Guzzle\Log; 4 5use Guzzle\Http\Curl\CurlHandle; 6use Guzzle\Http\Message\RequestInterface; 7use Guzzle\Http\Message\EntityEnclosingRequestInterface; 8use Guzzle\Http\Message\Response; 9 10/** 11 * Message formatter used in various places in the framework 12 * 13 * Format messages using a template that can contain the the following variables: 14 * 15 * - {request}: Full HTTP request message 16 * - {response}: Full HTTP response message 17 * - {ts}: Timestamp 18 * - {host}: Host of the request 19 * - {method}: Method of the request 20 * - {url}: URL of the request 21 * - {host}: Host of the request 22 * - {protocol}: Request protocol 23 * - {version}: Protocol version 24 * - {resource}: Resource of the request (path + query + fragment) 25 * - {port}: Port of the request 26 * - {hostname}: Hostname of the machine that sent the request 27 * - {code}: Status code of the response (if available) 28 * - {phrase}: Reason phrase of the response (if available) 29 * - {curl_error}: Curl error message (if available) 30 * - {curl_code}: Curl error code (if available) 31 * - {curl_stderr}: Curl standard error (if available) 32 * - {connect_time}: Time in seconds it took to establish the connection (if available) 33 * - {total_time}: Total transaction time in seconds for last transfer (if available) 34 * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message 35 * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message 36 * - {req_body}: Request body 37 * - {res_body}: Response body 38 */ 39class MessageFormatter 40{ 41 const DEFAULT_FORMAT = "{hostname} {req_header_User-Agent} - [{ts}] \"{method} {resource} {protocol}/{version}\" {code} {res_header_Content-Length}"; 42 const DEBUG_FORMAT = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{curl_stderr}"; 43 const SHORT_FORMAT = '[{ts}] "{method} {resource} {protocol}/{version}" {code}'; 44 45 /** 46 * @var string Template used to format log messages 47 */ 48 protected $template; 49 50 /** 51 * @param string $template Log message template 52 */ 53 public function __construct($template = self::DEFAULT_FORMAT) 54 { 55 $this->template = $template ?: self::DEFAULT_FORMAT; 56 } 57 58 /** 59 * Set the template to use for logging 60 * 61 * @param string $template Log message template 62 * 63 * @return self 64 */ 65 public function setTemplate($template) 66 { 67 $this->template = $template; 68 69 return $this; 70 } 71 72 /** 73 * Returns a formatted message 74 * 75 * @param RequestInterface $request Request that was sent 76 * @param Response $response Response that was received 77 * @param CurlHandle $handle Curl handle associated with the message 78 * @param array $customData Associative array of custom template data 79 * 80 * @return string 81 */ 82 public function format( 83 RequestInterface $request, 84 Response $response = null, 85 CurlHandle $handle = null, 86 array $customData = array() 87 ) { 88 $cache = $customData; 89 90 return preg_replace_callback( 91 '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', 92 function (array $matches) use ($request, $response, $handle, &$cache) { 93 94 if (array_key_exists($matches[1], $cache)) { 95 return $cache[$matches[1]]; 96 } 97 98 $result = ''; 99 switch ($matches[1]) { 100 case 'request': 101 $result = (string) $request; 102 break; 103 case 'response': 104 $result = (string) $response; 105 break; 106 case 'req_body': 107 $result = $request instanceof EntityEnclosingRequestInterface 108 ? (string) $request->getBody() : ''; 109 break; 110 case 'res_body': 111 $result = $response ? $response->getBody(true) : ''; 112 break; 113 case 'ts': 114 $result = gmdate('c'); 115 break; 116 case 'method': 117 $result = $request->getMethod(); 118 break; 119 case 'url': 120 $result = (string) $request->getUrl(); 121 break; 122 case 'resource': 123 $result = $request->getResource(); 124 break; 125 case 'protocol': 126 $result = 'HTTP'; 127 break; 128 case 'version': 129 $result = $request->getProtocolVersion(); 130 break; 131 case 'host': 132 $result = $request->getHost(); 133 break; 134 case 'hostname': 135 $result = gethostname(); 136 break; 137 case 'port': 138 $result = $request->getPort(); 139 break; 140 case 'code': 141 $result = $response ? $response->getStatusCode() : ''; 142 break; 143 case 'phrase': 144 $result = $response ? $response->getReasonPhrase() : ''; 145 break; 146 case 'connect_time': 147 $result = $handle && $handle->getInfo(CURLINFO_CONNECT_TIME) 148 ? $handle->getInfo(CURLINFO_CONNECT_TIME) 149 : ($response ? $response->getInfo('connect_time') : ''); 150 break; 151 case 'total_time': 152 $result = $handle && $handle->getInfo(CURLINFO_TOTAL_TIME) 153 ? $handle->getInfo(CURLINFO_TOTAL_TIME) 154 : ($response ? $response->getInfo('total_time') : ''); 155 break; 156 case 'curl_error': 157 $result = $handle ? $handle->getError() : ''; 158 break; 159 case 'curl_code': 160 $result = $handle ? $handle->getErrorNo() : ''; 161 break; 162 case 'curl_stderr': 163 $result = $handle ? $handle->getStderr() : ''; 164 break; 165 default: 166 if (strpos($matches[1], 'req_header_') === 0) { 167 $result = $request->getHeader(substr($matches[1], 11)); 168 } elseif ($response && strpos($matches[1], 'res_header_') === 0) { 169 $result = $response->getHeader(substr($matches[1], 11)); 170 } 171 } 172 173 $cache[$matches[1]] = $result; 174 return $result; 175 }, 176 $this->template 177 ); 178 } 179} 180