Write to the access log (in Apache/NCSA Combined Log format). See the `apache documentation `_ for format details. CherryPy calls this automatically for you. Note there are no arguments; it col
(self)
| 221 | return self.error(*args, **kwargs) |
| 222 | |
| 223 | def access(self): |
| 224 | """Write to the access log (in Apache/NCSA Combined Log format). |
| 225 | |
| 226 | See the |
| 227 | `apache documentation |
| 228 | <http://httpd.apache.org/docs/current/logs.html#combined>`_ |
| 229 | for format details. |
| 230 | |
| 231 | CherryPy calls this automatically for you. Note there are no arguments; |
| 232 | it collects the data itself from |
| 233 | :class:`cherrypy.request<cherrypy._cprequest.Request>`. |
| 234 | |
| 235 | Like Apache started doing in 2.0.46, non-printable and other special |
| 236 | characters in %r (and we expand that to all parts) are escaped using |
| 237 | \\xhh sequences, where hh stands for the hexadecimal representation |
| 238 | of the raw byte. Exceptions from this rule are " and \\, which are |
| 239 | escaped by prepending a backslash, and all whitespace characters, |
| 240 | which are written in their C-style notation (\\n, \\t, etc). |
| 241 | """ |
| 242 | request = cherrypy.serving.request |
| 243 | remote = request.remote |
| 244 | response = cherrypy.serving.response |
| 245 | outheaders = response.headers |
| 246 | inheaders = request.headers |
| 247 | if response.output_status is None: |
| 248 | status = '-' |
| 249 | else: |
| 250 | status = response.output_status.split(b' ', 1)[0] |
| 251 | status = status.decode('ISO-8859-1') |
| 252 | |
| 253 | atoms = {'h': remote.name or remote.ip, |
| 254 | 'l': '-', |
| 255 | 'u': getattr(request, 'login', None) or '-', |
| 256 | 't': self.time(), |
| 257 | 'r': request.request_line, |
| 258 | 's': status, |
| 259 | 'b': dict.get(outheaders, 'Content-Length', '') or '-', |
| 260 | 'f': dict.get(inheaders, 'Referer', ''), |
| 261 | 'a': dict.get(inheaders, 'User-Agent', ''), |
| 262 | 'o': dict.get(inheaders, 'Host', '-'), |
| 263 | 'i': request.unique_id, |
| 264 | 'z': LazyRfc3339UtcTime(), |
| 265 | } |
| 266 | for k, v in atoms.items(): |
| 267 | if not isinstance(v, str): |
| 268 | v = str(v) |
| 269 | v = v.replace('"', '\\"').encode('utf8') |
| 270 | # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc |
| 271 | # and backslash for us. All we have to do is strip the quotes. |
| 272 | v = repr(v)[2:-1] |
| 273 | |
| 274 | # in python 3.0 the repr of bytes (as returned by encode) |
| 275 | # uses double \'s. But then the logger escapes them yet, again |
| 276 | # resulting in quadruple slashes. Remove the extra one here. |
| 277 | v = v.replace('\\\\', '\\') |
| 278 | |
| 279 | # Escape double-quote. |
| 280 | atoms[k] = v |