Esempio n. 1
0
        /// <summary>
        /// Processes the incoming request. This method is not depended on the environment and so can be unit tested.
        /// Note that the incoming request may not be the POST request with log data.
        ///
        /// Effect of this method:
        /// * setting StatusCode on the response parameter
        /// * adding headers to the response parameter
        /// * logging contents of log request
        /// </summary>
        /// <param name="json">
        /// JSON payload in the incoming request
        /// </param>
        /// <param name="logRequestBase">
        /// * Type of browser that sent the request
        /// * IP address that sent the address
        /// * Url that the request was sent to
        /// * Request Id sent as part of the request
        /// * Request data to be given to onLogging event handler
        /// </param>
        /// <param name="serverSideTimeUtc">Current time in UTC</param>
        /// <param name="httpMethod">HTTP method of the request</param>
        /// <param name="origin">Value of the Origin request header</param>
        /// <param name="response">
        /// Empty response object. This method can add headers, etc.
        /// </param>
        internal static void ProcessLogRequest(string json, LogRequestBase logRequestBase,
                                               DateTime serverSideTimeUtc,
                                               string httpMethod, string origin, LogResponse response)
        {
            JsnlogConfiguration jsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration();

            ILoggingAdapter logger = JavascriptLogging.GetLogger();

            if ((httpMethod != "POST") && (httpMethod != "OPTIONS"))
            {
                response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
                return;
            }

            string corsAllowedOriginsRegex = jsnlogConfiguration.corsAllowedOriginsRegex;
            bool   originIsAllowed         = ((!string.IsNullOrEmpty(corsAllowedOriginsRegex)) && (!string.IsNullOrEmpty(origin)) && Regex.IsMatch(origin, corsAllowedOriginsRegex));

            if (originIsAllowed)
            {
                response.AppendHeader("Access-Control-Allow-Origin", origin);
            }

            response.StatusCode = (int)HttpStatusCode.OK;

            if (httpMethod == "OPTIONS")
            {
                // Standard HTTP response (not related to CORS)
                response.AppendHeader("Allow", "POST");

                // Only if the origin is allowed send CORS headers
                if (originIsAllowed)
                {
                    response.AppendHeader("Access-Control-Max-Age", Constants.CorsAccessControlMaxAgeInSeconds.ToString());
                    response.AppendHeader("Access-Control-Allow-Methods", "POST");
                    response.AppendHeader("Access-Control-Allow-Headers", "jsnlog-requestid, content-type");
                }

                return;
            }

            // httpMethod must be POST

            List <FinalLogData> logDatas =
                ProcessLogRequestExec(json, logRequestBase, serverSideTimeUtc, jsnlogConfiguration);

            // ---------------------------------
            // Pass log data to Common Logging

            foreach (FinalLogData logData in logDatas)
            {
                logger.Log(logData);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Processes the incoming request. This method is not depended on the environment and so can be unit tested.
        /// Note that the incoming request may not be the POST request with log data.
        /// 
        /// Effect of this method:
        /// * setting StatusCode on the response parameter
        /// * adding headers to the response parameter
        /// * logging contents of log request
        /// </summary>
        /// <param name="json">
        /// JSON payload in the incoming request
        /// </param>
        /// <param name="logRequestBase">
        /// * Type of browser that sent the request
        /// * IP address that sent the address
        /// * Url that the request was sent to
        /// * Request Id sent as part of the request
        /// * Request data to be given to onLogging event handler
        /// </param>
        /// <param name="serverSideTimeUtc">Current time in UTC</param>
        /// <param name="httpMethod">HTTP method of the request</param>
        /// <param name="origin">Value of the Origin request header</param>
        /// <param name="response">
        /// Empty response object. This method can add headers, etc.
        /// </param>
        internal static void ProcessLogRequest(string json, LogRequestBase logRequestBase,
            DateTime serverSideTimeUtc,
            string httpMethod, string origin, LogResponse response)
        {
            JsnlogConfiguration jsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration();

            ILoggingAdapter logger = JavascriptLogging.GetLogger();

            if ((httpMethod != "POST") && (httpMethod != "OPTIONS"))
            {
                response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
                return;
            }

            string corsAllowedOriginsRegex = jsnlogConfiguration.corsAllowedOriginsRegex;
            bool originIsAllowed = ((!string.IsNullOrEmpty(corsAllowedOriginsRegex)) && (!string.IsNullOrEmpty(origin)) && Regex.IsMatch(origin, corsAllowedOriginsRegex));

            if (originIsAllowed)
            {
                response.AppendHeader("Access-Control-Allow-Origin", origin);
            }

            response.StatusCode = (int)HttpStatusCode.OK;

            if (httpMethod == "OPTIONS")
            {
                // Standard HTTP response (not related to CORS)
                response.AppendHeader("Allow", "POST");

                // Only if the origin is allowed send CORS headers
                if (originIsAllowed)
                {
                    response.AppendHeader("Access-Control-Max-Age", Constants.CorsAccessControlMaxAgeInSeconds.ToString());
                    response.AppendHeader("Access-Control-Allow-Methods", "POST");
                    response.AppendHeader("Access-Control-Allow-Headers", "jsnlog-requestid, content-type");
                }

                return;
            }

            // httpMethod must be POST

            List<FinalLogData> logDatas =
                ProcessLogRequestExec(json, logRequestBase, serverSideTimeUtc, jsnlogConfiguration);

            // ---------------------------------
            // Pass log data to Common Logging

            foreach (FinalLogData logData in logDatas)
            {
                logger.Log(logData);
            }
        }
Esempio n. 3
0
        private static async Task ProcessRequestAsync(HttpContext context)
        {
            var    headers     = context.Request.Headers.ToDictionary();
            string urlReferrer = headers.SafeGet("Referer");
            string url         = context.Request.GetDisplayUrl();

            var logRequestBase = new LogRequestBase(
                userAgent: headers.SafeGet("User-Agent"),
                userHostAddress: context.Wrapper().GetUserIp(),
                requestId: context.Wrapper().GetLogRequestId(),
                url: (urlReferrer ?? url).ToString(),
                queryParameters: context.Request.Query.ToDictionary(),
                cookies: context.Request.Cookies.ToDictionary(),
                headers: headers);

            DateTime serverSideTimeUtc = DateTime.UtcNow;
            string   httpMethod        = context.Request.Method;
            string   origin            = headers.SafeGet("Origin");

            Encoding encoding = HttpHelpers.GetEncoding(headers.SafeGet("Content-Type"));

            string json;

            using (var reader = new StreamReader(context.Request.Body, encoding))
            {
                json = await reader.ReadToEndAsync();
            }

            var response = new LogResponse();

            LoggerProcessor.ProcessLogRequest(json, logRequestBase,
                                              serverSideTimeUtc,
                                              httpMethod, origin, response);

            // Send dummy response. That way, the log request will not remain "pending"
            // in eg. Chrome dev tools.
            //
            // This must be given a MIME type of "text/plain"
            // Otherwise, the browser may try to interpret the empty string as XML.
            // When the user uses Firefox, and right clicks on the page and chooses "Inspect Element",
            // then in that debugger's console it will say "no element found".
            // See
            // http://www.acnenomor.com/307387p1/how-do-i-setup-my-ajax-post-request-to-prevent-no-element-found-on-empty-response
            // http://stackoverflow.com/questions/975929/firefox-error-no-element-found/976200#976200

            ToAspNet5Response(response, context.Response);
            context.Response.ContentType   = "text/plain";
            context.Response.ContentLength = 0;
        }
Esempio n. 4
0
        /// <summary>
        /// Processes a request with logging info. Unit testable.
        ///
        /// Returns log info in easily digestable format.
        /// </summary>
        /// <param name="json">JSON sent from client by AjaxAppender</param>
        /// <param name="serverSideTimeUtc">Current time in UTC</param>
        /// <param name="jsnlogConfiguration">Contains all config info</param>
        internal static List <FinalLogData> ProcessLogRequestExec(string json, LogRequestBase logRequestBase,
                                                                  DateTime serverSideTimeUtc, JsnlogConfiguration jsnlogConfiguration)
        {
            var          logDatas = new List <FinalLogData>();
            FinalLogData logData  = null;

            try
            {
                LogRequestData logRequestData = LogMessageHelpers.DeserializeJson <LogRequestData>(json);

                foreach (var logItem in logRequestData.lg)
                {
                    logData = null; // in case ProcessLogItem throws exception
                    logData = ProcessLogItem(logItem,
                                             logRequestBase, serverSideTimeUtc, jsnlogConfiguration);

                    if (logData != null)
                    {
                        logDatas.Add(logData);
                    }
                }
            }
            catch (Exception e)
            {
                try
                {
                    string message = string.Format("Exception: {0}, json: {1}, FinalLogData: {{{2}}}, logRequestBase: {{{3}}}", e, json, logData, logRequestBase);

                    var internalErrorFinalLogData = new FinalLogData(null)
                    {
                        FinalMessage = message,
                        FinalLogger  = Constants.JSNLogInternalErrorLoggerName,
                        FinalLevel   = Level.ERROR
                    };

                    logDatas.Add(internalErrorFinalLogData);
                }
                catch
                {
                }
            }

            return(logDatas);
        }
Esempio n. 5
0
        private static FinalLogData ProcessLogItem(LogRequestSingleMsg logItem, LogRequestBase logRequestBase,
            DateTime serverSideTimeUtc, JsnlogConfiguration jsnlogConfiguration)
        {
            string serversideLoggerNameOverride = jsnlogConfiguration.serverSideLogger;
            string messageFormat = jsnlogConfiguration.serverSideMessageFormat;
            string levelOverride = jsnlogConfiguration.serverSideLevel;
            string dateFormat = jsnlogConfiguration.dateFormat;

            try
            {
                LevelUtils.ValidateLevel(levelOverride);
            }
            catch (Exception e)
            {
                throw new PropertyException("levelOverride", e);
            }

            // ----------------

            string message = logItem.m;
            string logger = logItem.n;
            string level = logItem.l; // note that level as sent by the javascript is a number

            DateTime utcDate = DateTime.UtcNow;
            string timestampMs = logItem.t;
            try
            {
                double ms = double.Parse(timestampMs);
                utcDate = DateTime.SpecifyKind((new DateTime(1970, 1, 1)).AddMilliseconds(ms), DateTimeKind.Utc);
            }
            catch
            {
            }

            // ----------------

            string jsonmessage = "";
            if (messageFormat.Contains("%jsonmessage"))
            {
                jsonmessage = LogMessageHelpers.EnsureValidJson(message);
            }

            // ----------------

            var logRequest = new LogRequest(message, logger, level, utcDate, jsonmessage, logRequestBase);
            var loggingEventArgs = new LoggingEventArgs(logRequest) 
            {
                Cancel = false,
                ServerSideMessageFormat = messageFormat
            };

            // ----------------

            if (string.IsNullOrWhiteSpace(logger)) { logger = Constants.RootLoggerNameServerSide; }
            loggingEventArgs.FinalLogger = serversideLoggerNameOverride ?? logger;

            string consolidatedLevel = levelOverride ?? level;
            loggingEventArgs.FinalLevel = LevelUtils.ParseLevel(consolidatedLevel).Value;

            // ----------------

            loggingEventArgs.FinalMessage = messageFormat
                .Replace("%message", message)
                .Replace("%jsonmessage", jsonmessage)
                .Replace("%utcDateServer", serverSideTimeUtc.ToString(dateFormat))
                .Replace("%utcDate", utcDate.ToString(dateFormat))
                .Replace("%dateServer", Utils.UtcToLocalDateTime(serverSideTimeUtc).ToString(dateFormat))
                .Replace("%date", Utils.UtcToLocalDateTime(utcDate).ToString(dateFormat))
                .Replace("%level", level)
                .Replace("%newline", System.Environment.NewLine)
                .Replace("%userAgent", logRequestBase.UserAgent)
                .Replace("%userHostAddress", logRequestBase.UserHostAddress)
                .Replace("%requestId", logRequestBase.RequestId ?? "")
                .Replace("%url", logRequestBase.Url)
                .Replace("%logger", logger);

            // ----------------

            JavascriptLogging.RaiseLoggingEvent(loggingEventArgs);

            // If user wrote event handler that decided not to log the message, return null
            if (loggingEventArgs.Cancel) { return null; }

            return loggingEventArgs;
        }
Esempio n. 6
0
        /// <summary>
        /// Processes a request with logging info. Unit testable.
        /// 
        /// Returns log info in easily digestable format.
        /// </summary>
        /// <param name="json">JSON sent from client by AjaxAppender</param>
        /// <param name="serverSideTimeUtc">Current time in UTC</param>
        /// <param name="jsnlogConfiguration">Contains all config info</param>
        internal static List<FinalLogData> ProcessLogRequestExec(string json, LogRequestBase logRequestBase,
            DateTime serverSideTimeUtc, JsnlogConfiguration jsnlogConfiguration)
        {
            var logDatas = new List<FinalLogData>();
            FinalLogData logData = null;

            try
            {
                LogRequestData logRequestData = LogMessageHelpers.DeserializeJson<LogRequestData>(json);

                foreach (var logItem in logRequestData.lg)
                {
                    logData = null; // in case ProcessLogItem throws exception
                    logData = ProcessLogItem(logItem,
                        logRequestBase, serverSideTimeUtc, jsnlogConfiguration);

                    if (logData != null)
                    {
                        logDatas.Add(logData);
                    }
                }
            }
            catch (Exception e)
            {
                try
                {
                    string message = string.Format("Exception: {0}, json: {1}, FinalLogData: {{{2}}}, logRequestBase: {{{3}}}", e, json, logData, logRequestBase);

                    var internalErrorFinalLogData = new FinalLogData(null)
                    {
                        FinalMessage = message,
                        FinalLogger = Constants.JSNLogInternalErrorLoggerName,
                        FinalLevel = Level.ERROR
                    };

                    logDatas.Add(internalErrorFinalLogData);
                }
                catch
                {
                }
            }

            return logDatas;
        }
Esempio n. 7
0
        private static FinalLogData ProcessLogItem(LogRequestSingleMsg logItem, LogRequestBase logRequestBase,
                                                   DateTime serverSideTimeUtc, JsnlogConfiguration jsnlogConfiguration)
        {
            string serversideLoggerNameOverride = jsnlogConfiguration.serverSideLogger;
            string messageFormat = jsnlogConfiguration.serverSideMessageFormat;
            string levelOverride = jsnlogConfiguration.serverSideLevel;
            string dateFormat    = jsnlogConfiguration.dateFormat;

            try
            {
                LevelUtils.ValidateLevel(levelOverride);
            }
            catch (Exception e)
            {
                throw new PropertyException("levelOverride", e);
            }

            // ----------------

            string message = logItem.m;
            string logger  = logItem.n;
            string level   = logItem.l; // note that level as sent by the javascript is a number
            string entryId = logItem.u;

            DateTime utcDate     = DateTime.UtcNow;
            string   timestampMs = logItem.t;

            try
            {
                double ms = double.Parse(timestampMs);
                utcDate = DateTime.SpecifyKind((new DateTime(1970, 1, 1)).AddMilliseconds(ms), DateTimeKind.Utc);
            }
            catch
            {
            }

            // ----------------

            string jsonmessage = "";

            if (messageFormat.Contains("%jsonmessage"))
            {
                jsonmessage = LogMessageHelpers.EnsureValidJson(message);
            }

            // ----------------

            var logRequest       = new LogRequest(message, logger, level, utcDate, entryId, jsonmessage, logRequestBase);
            var loggingEventArgs = new LoggingEventArgs(logRequest)
            {
                Cancel = false,
                ServerSideMessageFormat = messageFormat
            };

            // ----------------

            if (string.IsNullOrWhiteSpace(logger))
            {
                logger = Constants.RootLoggerNameServerSide;
            }
            loggingEventArgs.FinalLogger = serversideLoggerNameOverride ?? logger;

            string consolidatedLevel = levelOverride ?? level;

            loggingEventArgs.FinalLevel = LevelUtils.ParseLevel(consolidatedLevel).Value;

            // ----------------

            loggingEventArgs.FinalMessage = messageFormat
                                            .Replace("%message", message)
                                            .Replace("%entryId", entryId)
                                            .Replace("%jsonmessage", jsonmessage)
                                            .Replace("%utcDateServer", serverSideTimeUtc.ToString(dateFormat))
                                            .Replace("%utcDate", utcDate.ToString(dateFormat))
                                            .Replace("%dateServer", Utils.UtcToLocalDateTime(serverSideTimeUtc).ToString(dateFormat))
                                            .Replace("%date", Utils.UtcToLocalDateTime(utcDate).ToString(dateFormat))
                                            .Replace("%level", level)
                                            .Replace("%newline", System.Environment.NewLine)
                                            .Replace("%userAgent", logRequestBase.UserAgent)
                                            .Replace("%userHostAddress", logRequestBase.UserHostAddress)
                                            .Replace("%requestId", logRequestBase.RequestId ?? "")
                                            .Replace("%url", logRequestBase.Url)
                                            .Replace("%logger", logger);

            // ----------------

            JavascriptLogging.RaiseLoggingEvent(loggingEventArgs);

            // If user wrote event handler that decided not to log the message, return null
            if (loggingEventArgs.Cancel)
            {
                return(null);
            }

            return(loggingEventArgs);
        }