| // Copyright 2006 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| /** |
| * @fileoverview Definition of the ChannelDebug class. ChannelDebug provides |
| * a utility for tracing and debugging the BrowserChannel requests. |
| * |
| */ |
| |
| |
| /** |
| * Namespace for BrowserChannel |
| */ |
| goog.provide('goog.net.ChannelDebug'); |
| |
| goog.require('goog.json'); |
| goog.require('goog.log'); |
| |
| |
| |
| /** |
| * Logs and keeps a buffer of debugging info for the Channel. |
| * |
| * @constructor |
| */ |
| goog.net.ChannelDebug = function() { |
| /** |
| * The logger instance. |
| * @const |
| * @private |
| */ |
| this.logger_ = goog.log.getLogger('goog.net.BrowserChannel'); |
| }; |
| |
| |
| /** |
| * Gets the logger used by this ChannelDebug. |
| * @return {goog.debug.Logger} The logger used by this ChannelDebug. |
| */ |
| goog.net.ChannelDebug.prototype.getLogger = function() { |
| return this.logger_; |
| }; |
| |
| |
| /** |
| * Logs that the browser went offline during the lifetime of a request. |
| * @param {goog.Uri} url The URL being requested. |
| */ |
| goog.net.ChannelDebug.prototype.browserOfflineResponse = function(url) { |
| this.info('BROWSER_OFFLINE: ' + url); |
| }; |
| |
| |
| /** |
| * Logs an XmlHttp request.. |
| * @param {string} verb The request type (GET/POST). |
| * @param {goog.Uri} uri The request destination. |
| * @param {string|number|undefined} id The request id. |
| * @param {number} attempt Which attempt # the request was. |
| * @param {?string} postData The data posted in the request. |
| */ |
| goog.net.ChannelDebug.prototype.xmlHttpChannelRequest = |
| function(verb, uri, id, attempt, postData) { |
| this.info( |
| 'XMLHTTP REQ (' + id + ') [attempt ' + attempt + ']: ' + |
| verb + '\n' + uri + '\n' + |
| this.maybeRedactPostData_(postData)); |
| }; |
| |
| |
| /** |
| * Logs the meta data received from an XmlHttp request. |
| * @param {string} verb The request type (GET/POST). |
| * @param {goog.Uri} uri The request destination. |
| * @param {string|number|undefined} id The request id. |
| * @param {number} attempt Which attempt # the request was. |
| * @param {goog.net.XmlHttp.ReadyState} readyState The ready state. |
| * @param {number} statusCode The HTTP status code. |
| */ |
| goog.net.ChannelDebug.prototype.xmlHttpChannelResponseMetaData = |
| function(verb, uri, id, attempt, readyState, statusCode) { |
| this.info( |
| 'XMLHTTP RESP (' + id + ') [ attempt ' + attempt + ']: ' + |
| verb + '\n' + uri + '\n' + readyState + ' ' + statusCode); |
| }; |
| |
| |
| /** |
| * Logs the response data received from an XmlHttp request. |
| * @param {string|number|undefined} id The request id. |
| * @param {?string} responseText The response text. |
| * @param {?string=} opt_desc Optional request description. |
| */ |
| goog.net.ChannelDebug.prototype.xmlHttpChannelResponseText = |
| function(id, responseText, opt_desc) { |
| this.info( |
| 'XMLHTTP TEXT (' + id + '): ' + |
| this.redactResponse_(responseText) + |
| (opt_desc ? ' ' + opt_desc : '')); |
| }; |
| |
| |
| /** |
| * Logs a Trident ActiveX request. |
| * @param {string} verb The request type (GET/POST). |
| * @param {goog.Uri} uri The request destination. |
| * @param {string|number|undefined} id The request id. |
| * @param {number} attempt Which attempt # the request was. |
| */ |
| goog.net.ChannelDebug.prototype.tridentChannelRequest = |
| function(verb, uri, id, attempt) { |
| this.info( |
| 'TRIDENT REQ (' + id + ') [ attempt ' + attempt + ']: ' + |
| verb + '\n' + uri); |
| }; |
| |
| |
| /** |
| * Logs the response text received from a Trident ActiveX request. |
| * @param {string|number|undefined} id The request id. |
| * @param {string} responseText The response text. |
| */ |
| goog.net.ChannelDebug.prototype.tridentChannelResponseText = |
| function(id, responseText) { |
| this.info( |
| 'TRIDENT TEXT (' + id + '): ' + |
| this.redactResponse_(responseText)); |
| }; |
| |
| |
| /** |
| * Logs the done response received from a Trident ActiveX request. |
| * @param {string|number|undefined} id The request id. |
| * @param {boolean} successful Whether the request was successful. |
| */ |
| goog.net.ChannelDebug.prototype.tridentChannelResponseDone = |
| function(id, successful) { |
| this.info( |
| 'TRIDENT TEXT (' + id + '): ' + successful ? 'success' : 'failure'); |
| }; |
| |
| |
| /** |
| * Logs a request timeout. |
| * @param {goog.Uri} uri The uri that timed out. |
| */ |
| goog.net.ChannelDebug.prototype.timeoutResponse = function(uri) { |
| this.info('TIMEOUT: ' + uri); |
| }; |
| |
| |
| /** |
| * Logs a debug message. |
| * @param {string} text The message. |
| */ |
| goog.net.ChannelDebug.prototype.debug = function(text) { |
| this.info(text); |
| }; |
| |
| |
| /** |
| * Logs an exception |
| * @param {Error} e The error or error event. |
| * @param {string=} opt_msg The optional message, defaults to 'Exception'. |
| */ |
| goog.net.ChannelDebug.prototype.dumpException = function(e, opt_msg) { |
| this.severe((opt_msg || 'Exception') + e); |
| }; |
| |
| |
| /** |
| * Logs an info message. |
| * @param {string} text The message. |
| */ |
| goog.net.ChannelDebug.prototype.info = function(text) { |
| goog.log.info(this.logger_, text); |
| }; |
| |
| |
| /** |
| * Logs a warning message. |
| * @param {string} text The message. |
| */ |
| goog.net.ChannelDebug.prototype.warning = function(text) { |
| goog.log.warning(this.logger_, text); |
| }; |
| |
| |
| /** |
| * Logs a severe message. |
| * @param {string} text The message. |
| */ |
| goog.net.ChannelDebug.prototype.severe = function(text) { |
| goog.log.error(this.logger_, text); |
| }; |
| |
| |
| /** |
| * Removes potentially private data from a response so that we don't |
| * accidentally save private and personal data to the server logs. |
| * @param {?string} responseText A JSON response to clean. |
| * @return {?string} The cleaned response. |
| * @private |
| */ |
| goog.net.ChannelDebug.prototype.redactResponse_ = function(responseText) { |
| // first check if it's not JS - the only non-JS should be the magic cookie |
| if (!responseText || |
| /** @suppress {missingRequire}. The require creates a circular |
| * dependency. |
| */ |
| responseText == goog.net.BrowserChannel.MAGIC_RESPONSE_COOKIE) { |
| return responseText; |
| } |
| /** @preserveTry */ |
| try { |
| var responseArray = goog.json.unsafeParse(responseText); |
| if (responseArray) { |
| for (var i = 0; i < responseArray.length; i++) { |
| if (goog.isArray(responseArray[i])) { |
| this.maybeRedactArray_(responseArray[i]); |
| } |
| } |
| } |
| |
| return goog.json.serialize(responseArray); |
| } catch (e) { |
| this.debug('Exception parsing expected JS array - probably was not JS'); |
| return responseText; |
| } |
| }; |
| |
| |
| /** |
| * Removes data from a response array that may be sensitive. |
| * @param {Array<?>} array The array to clean. |
| * @private |
| */ |
| goog.net.ChannelDebug.prototype.maybeRedactArray_ = function(array) { |
| if (array.length < 2) { |
| return; |
| } |
| var dataPart = array[1]; |
| if (!goog.isArray(dataPart)) { |
| return; |
| } |
| if (dataPart.length < 1) { |
| return; |
| } |
| |
| var type = dataPart[0]; |
| if (type != 'noop' && type != 'stop') { |
| // redact all fields in the array |
| for (var i = 1; i < dataPart.length; i++) { |
| dataPart[i] = ''; |
| } |
| } |
| }; |
| |
| |
| /** |
| * Removes potentially private data from a request POST body so that we don't |
| * accidentally save private and personal data to the server logs. |
| * @param {?string} data The data string to clean. |
| * @return {?string} The data string with sensitive data replaced by 'redacted'. |
| * @private |
| */ |
| goog.net.ChannelDebug.prototype.maybeRedactPostData_ = function(data) { |
| if (!data) { |
| return null; |
| } |
| var out = ''; |
| var params = data.split('&'); |
| for (var i = 0; i < params.length; i++) { |
| var param = params[i]; |
| var keyValue = param.split('='); |
| if (keyValue.length > 1) { |
| var key = keyValue[0]; |
| var value = keyValue[1]; |
| |
| var keyParts = key.split('_'); |
| if (keyParts.length >= 2 && keyParts[1] == 'type') { |
| out += key + '=' + value + '&'; |
| } else { |
| out += key + '=' + 'redacted' + '&'; |
| } |
| } |
| } |
| return out; |
| }; |