From df57685d572109657c2f5095c845e7ce3c7235eb Mon Sep 17 00:00:00 2001 From: Sean Huo Date: Sat, 21 Oct 2023 01:22:59 +0000 Subject: [PATCH] #185690008 : update dependencies, support for governance rules, some performnace improvement. (#113) * update dependency * little bit safer to use unmasked event instead * governance rule blocking, remove AppConfigManager * add governance rule blocking * Add governance rule blocking * Add BlockedResponse * Add governance rule route --- README.md | 8 +- .../pom.xml | 2 +- .../moesif/servlet/spring/ApiController.java | 30 +++++ .../com/moesif/servlet/spring/MyConfig.java | 14 +- jersey-servlet-example/pom.xml | 2 +- moesif-servlet-jakarta/README.md | 2 +- moesif-servlet-jakarta/pom.xml | 4 +- .../com/moesif/servlet/AppConfigManager.java | 119 ----------------- .../com/moesif/servlet/BatchProcessor.java | 10 +- .../java/com/moesif/servlet/MoesifFilter.java | 81 ++++++++--- .../moesif/servlet/MoesifServletTests.java | 6 +- moesif-servlet/pom.xml | 10 +- .../com/moesif/servlet/AppConfigManager.java | 119 ----------------- .../com/moesif/servlet/BatchProcessor.java | 9 -- .../java/com/moesif/servlet/MoesifFilter.java | 126 ++++++++++-------- .../moesif/servlet/MoesifServletTests.java | 6 +- moesif-springrequest/pom.xml | 10 +- .../MoesifBlockedClientHttpResponse.java | 60 +++++++++ .../MoesifSpringRequestInterceptor.java | 51 ++++++- servlet-example/pom.xml | 2 +- spark-servlet-example/pom.xml | 2 +- spring-boot-servlet-example/pom.xml | 2 +- spring-boot-starter-example/pom.xml | 2 +- 23 files changed, 301 insertions(+), 376 deletions(-) delete mode 100644 moesif-servlet-jakarta/src/main/java/com/moesif/servlet/AppConfigManager.java delete mode 100644 moesif-servlet/src/main/java/com/moesif/servlet/AppConfigManager.java create mode 100644 moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifBlockedClientHttpResponse.java diff --git a/README.md b/README.md index fa9fdae..75ed7d6 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,14 @@ Add the Moesif dependency to your project's pom.xml file: com.moesif.servlet moesif-servlet - 1.7.8 + 1.7.9 com.moesif.servlet moesif-servlet-jakarta - 2.0.2 + 2.0.3 ``` @@ -44,12 +44,12 @@ Add the Moesif dependency to your project's build.gradle file: ```gradle dependencies { - compile 'com.moesif.servlet:moesif-servlet:1.7.8' + compile 'com.moesif.servlet:moesif-servlet:1.7.9' } // OR for newer Jakarta dependencies { - compile 'com.moesif.servlet:moesif-servlet-jakarta:2.0.2' + compile 'com.moesif.servlet:moesif-servlet-jakarta:2.0.3' } ``` diff --git a/examples/spring-boot-starter-example-jakarta/pom.xml b/examples/spring-boot-starter-example-jakarta/pom.xml index f36ae97..26e1408 100644 --- a/examples/spring-boot-starter-example-jakarta/pom.xml +++ b/examples/spring-boot-starter-example-jakarta/pom.xml @@ -33,7 +33,7 @@ com.moesif.servlet moesif-servlet-jakarta - 2.0.2 + 2.1.0 diff --git a/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/ApiController.java b/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/ApiController.java index 41be5f6..4cfcef7 100644 --- a/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/ApiController.java +++ b/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/ApiController.java @@ -27,6 +27,36 @@ public Greeting greeting(@RequestParam(value="name", defaultValue="") String nam return new Greeting(counter.incrementAndGet(), "Hello There!"); } + @GetMapping("gov/no_italy") + public String noItaly() { + return "{\"success\" : true}"; + } + + @GetMapping("gov/company1") + public String company1() { + return "{\"success\" : true}"; + } + + @GetMapping("gov/canada") + public String canada() { + return "{\"success\" : true}"; + } + + @GetMapping("gov/cairo") + public String cairo() { + return "{\"success\" : true}"; + } + + @GetMapping("gov/for_companies_in_japan_only") + public String forCompaniesInJapanOnly() { + return "{\"success\" : true}"; + } + + @GetMapping("gov/random") + public String random() { + return "{\"success\" : true}"; + } + @RequestMapping("/api/text") @ResponseBody public String simpleString() { diff --git a/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/MyConfig.java b/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/MyConfig.java index 7aa3ef2..1f31a94 100644 --- a/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/MyConfig.java +++ b/examples/spring-boot-starter-example-jakarta/src/main/java/com/moesif/servlet/spring/MyConfig.java @@ -23,10 +23,11 @@ public Filter moesifFilter() { @Override public String identifyUser(HttpServletRequest request, HttpServletResponse response) { - if (request.getUserPrincipal() == null) { - return null; - } - return request.getUserPrincipal().getName(); + return request.getHeader("X-User-Id"); +// if (request.getUserPrincipal() == null) { +// return null; +// } +// return request.getUserPrincipal().getName(); } @Override @@ -34,6 +35,11 @@ public String getSessionToken(HttpServletRequest request, HttpServletResponse re return request.getHeader("Authorization"); } + @Override + public String identifyCompany(HttpServletRequest request, HttpServletResponse response) { + return request.getHeader("X-Company-Id"); + } + @Override public String getApiVersion(HttpServletRequest request, HttpServletResponse response) { return request.getHeader("X-Api-Version"); diff --git a/jersey-servlet-example/pom.xml b/jersey-servlet-example/pom.xml index 7dcb305..1e1ae22 100644 --- a/jersey-servlet-example/pom.xml +++ b/jersey-servlet-example/pom.xml @@ -96,7 +96,7 @@ com.moesif.servlet moesif-servlet - 1.7.8 + 1.7.9 diff --git a/moesif-servlet-jakarta/README.md b/moesif-servlet-jakarta/README.md index b6be687..52f067b 100644 --- a/moesif-servlet-jakarta/README.md +++ b/moesif-servlet-jakarta/README.md @@ -24,7 +24,7 @@ Add the Moesif dependency to your project's pom.xml file: com.moesif.servlet moesif-servlet-jakarta - 2.0.2 + 2.0.3 ``` diff --git a/moesif-servlet-jakarta/pom.xml b/moesif-servlet-jakarta/pom.xml index 3bfb82d..2236887 100644 --- a/moesif-servlet-jakarta/pom.xml +++ b/moesif-servlet-jakarta/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.moesif.servlet moesif-servlet-jakarta - 2.0.2 + 2.1.0 jar moesif-servlet-jakarta Moesif SDK for Java Servlet to log and analyze API calls using Jakarta @@ -52,7 +52,7 @@ com.moesif.api moesifapi - 1.7.0 + 1.7.4 org.apache.commons diff --git a/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/AppConfigManager.java b/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/AppConfigManager.java deleted file mode 100644 index 05282bf..0000000 --- a/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/AppConfigManager.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.moesif.servlet; - -import com.moesif.api.MoesifAPIClient; -import com.moesif.api.controllers.APIController; -import com.moesif.api.http.response.HttpResponse; -import com.moesif.api.models.AppConfigModel; - -import java.io.InputStream; -import java.util.Date; -import java.util.TimerTask; -import java.util.logging.Logger; - -/*** - * TimerTask to manage the appConfig and get it from moesif periodically - * to update local cache. - */ -public class AppConfigManager extends TimerTask { - - private static final Logger logger = Logger.getLogger(AppConfigManager.class.toString()); - private static AppConfigManager instance = null; - - private MoesifAPIClient moesifApi = null; - private AppConfigModel appConfigModel = new AppConfigModel(); - private String cachedConfigEtag; - private Date lastUpdatedTime = new Date(0); - private boolean jobRunning = false; // to avoid running multiple job - private boolean debug = false; - - public boolean isJobRunning() { - return jobRunning; - } - - public static synchronized AppConfigManager getInstance() { - if (instance == null) { - instance = new AppConfigManager(); - } - - return instance; - } - - public void setMoesifApiClient(MoesifAPIClient moesifApi, boolean debug) { - this.moesifApi = moesifApi; - this.debug = debug; - } - - private AppConfigManager() { - } - - public int getSampleRate(String userId, String companyId) { - int sampleRate = appConfigModel.getSampleRate(); - if (userId != null && appConfigModel.getUserSampleRate().containsKey(userId)) { - sampleRate = appConfigModel.getUserSampleRate().get(userId); - } else if (companyId != null && appConfigModel.getCompanySampleRate().containsKey(companyId)) { - sampleRate = appConfigModel.getCompanySampleRate().get(companyId); - } - return sampleRate; - } - - /*** - * Method to update the appConfigModel based on Etag - * if cached copy is stale. - * @param responseConfigEtag: String - */ - public void updateIfStale(String responseConfigEtag) { - // Ignore, if job is already in-progress. - if (this.isJobRunning()) { - return; - } - - // Check if needed to call the getConfig api to update app config - if (responseConfigEtag != null - && !(responseConfigEtag.equals(this.cachedConfigEtag)) - && new Date().after(new Date(this.lastUpdatedTime.getTime() + 5 * 60 * 1000)) - ) { - if (this.debug) { - logger.info("Calling API to update appConfig based on Etag."); - } - // Call api to update samplingPercentage - this.run(); - } - } - - /*** - * TaskRunner to update the local cache of ppConfig from the server. - * It also keeps track of a flag to show if job is in-progress. - */ - @Override - public void run() { - // Skip, if job is already in-progress. - if (this.isJobRunning()) { - return; - } - - try { - this.jobRunning = true; - - // Calling the api - HttpResponse configApiResponse = moesifApi.getAPI().getAppConfig(); - // Fetch the response ETag - String responseConfigEtag = configApiResponse.getHeaders().get("x-moesif-config-etag"); - - // Read the response body - InputStream respBodyIs = configApiResponse.getRawBody(); - AppConfigModel newConfig = APIController.parseAppConfigModel(respBodyIs); - respBodyIs.close(); - - this.appConfigModel = newConfig; - this.cachedConfigEtag = responseConfigEtag; - } catch(Throwable e) { - logger.warning("Fetched configuration failed; using default configuration " + e.toString()); - this.appConfigModel = new AppConfigModel(); - this.appConfigModel.setSampleRate(100); - } finally { - jobRunning = false; - } - this.lastUpdatedTime = new Date(); - } - -} diff --git a/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/BatchProcessor.java b/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/BatchProcessor.java index 19d7cca..ce0a47c 100644 --- a/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/BatchProcessor.java +++ b/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/BatchProcessor.java @@ -101,15 +101,7 @@ public void onSuccess(HttpContext httpContext, HttpResponse httpResponse) { final int status = httpContext.getResponse().getStatusCode(); // No need to retry. Mark call done. done[0] = true; - if (status == 201) { - // Fetch the response ETag to check if we need to update appConfig. - String responseConfigEtag = httpResponse.getHeaders().get("x-moesif-config-etag"); - if (responseConfigEtag != null) { - AppConfigManager.getInstance().updateIfStale(responseConfigEtag); - } - } else if (debug) { - logger.warning("Status is " + status); - } + } public void onFailure(HttpContext httpContext, Throwable error) { diff --git a/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/MoesifFilter.java b/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/MoesifFilter.java index c18ca0c..a3c5c7e 100644 --- a/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/MoesifFilter.java +++ b/moesif-servlet-jakarta/src/main/java/com/moesif/servlet/MoesifFilter.java @@ -34,7 +34,7 @@ public class MoesifFilter implements Filter { private int sendBatchJobAliveCounter = 0; // counter to check scheduled job is alive or not. // Timer for various tasks - Timer updateConfigTimer = null; +// Timer updateConfigTimer = null; Timer sendBatchEventTimer = null; /** @@ -167,9 +167,6 @@ public void init(FilterConfig filterConfig) { } } - // Setup app config manager and run it immediately to load app config. - AppConfigManager.getInstance().setMoesifApiClient(this.moesifApi, this.debug); - AppConfigManager.getInstance().run(); // Initialize the batch event processor and timer tasks. this.initBatchProcessorAndStartJobs(); @@ -335,6 +332,35 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha EventRequestModel eventRequestModel = getEventRequestModel(requestWrapper, startDate, config.getApiVersion(httpRequest, httpResponse), transactionId); + EventModel event = createEvent(eventRequestModel, + config.identifyUser(httpRequest, null), + config.identifyCompany(httpRequest, null), + config.getSessionToken(httpRequest, null), + config.getTags(httpRequest, null), + config.getMetadata(httpRequest, null) + ); + + if(moesifApi.getAPI().isBlockedByGovernanceRules(event)) { + logger.warning("Blocked by governance rules" + event.getBlockedBy()); + EventResponseModel responseModel = event.getResponse(); + if (transactionId != null) { + responseModel.getHeaders().put("X-Moesif-Transaction-Id", transactionId); + } + + EventModel maskedEvent = config.maskContent(event); + this.addEventToQueue(maskedEvent); + + //short circuit the filter chain + Map headers = responseModel.getHeaders(); + headers.forEach((key, value) -> { + httpResponse.setHeader(key, value); + }); + httpResponse.setStatus(responseModel.getStatus()); + httpResponse.setContentType(responseModel.getTransferEncoding()); + httpResponse.getWriter().write(responseModel.getBody().toString()); + return; + } + // pass to next step in the chain. try { filterChain.doFilter(requestWrapper, responseWrapper); @@ -421,7 +447,6 @@ private void initBatchProcessorAndStartJobs() { this.batchProcessor = new BatchProcessor(this.moesifApi, this.config, this.debug); // Initialize the timer tasks - Create scheduled jobs - this.scheduleAppConfigJob(); this.scheduleBatchEventsJob(); } @@ -440,27 +465,13 @@ public void drainQueueAndStopJobs() { if (debug) { logger.info("Stopping scheduled jobs."); } - this.resetJobTimer(this.updateConfigTimer); +// this.resetJobTimer(this.updateConfigTimer); this.resetJobTimer(this.sendBatchEventTimer); } catch (Exception e) { // ignore the error. } } - /** - * Method to create scheduled job for updating config periodically. - */ - private void scheduleAppConfigJob() { - // Make sure there is none before creating the timer - this.resetJobTimer(this.updateConfigTimer); - - this.updateConfigTimer = new Timer("moesif_update_config_job"); - updateConfigTimer.schedule( - AppConfigManager.getInstance(), - (long) this.batchProcessor.getUpdateConfigTime() * 1000, // Trigger this job every X seconds since we're already fetching the app config on init. - (long) this.batchProcessor.getUpdateConfigTime() * 1000 - ); - } /** * Method to create scheduled job for sending batch events periodically. @@ -604,7 +615,7 @@ public void onFailure(HttpContext context, Throwable error) { // Generate random number double randomPercentage = Math.random() * 100; - int samplingPercentage = AppConfigManager.getInstance().getSampleRate(userId, companyId); + int samplingPercentage = moesifApi.getAPI().getSampleRateToUse(event); // Compare percentage to send event if (samplingPercentage >= randomPercentage) { @@ -641,4 +652,32 @@ static String getFullURL(HttpServletRequest request) { return requestURL.append('?').append(queryString).toString(); } } + + private EventModel createEvent(EventRequestModel eventRequestModel, + String userId, + String companyId, + String sessionToken, + String tags, + Object metadata) { + + EventBuilder eb = new EventBuilder(); + eb.request(eventRequestModel); + eb.direction("Incoming"); + if (userId != null) { + eb.userId(userId); + } + if (companyId != null) { + eb.companyId(companyId); + } + if (sessionToken != null) { + eb.sessionToken(sessionToken); + } + if (tags != null) { + eb.tags(tags); + } + if (metadata != null) { + eb.metadata(metadata); + } + return eb.build(); + } } \ No newline at end of file diff --git a/moesif-servlet-jakarta/src/test/java/com/moesif/servlet/MoesifServletTests.java b/moesif-servlet-jakarta/src/test/java/com/moesif/servlet/MoesifServletTests.java index 11f4fca..9de48ee 100644 --- a/moesif-servlet-jakarta/src/test/java/com/moesif/servlet/MoesifServletTests.java +++ b/moesif-servlet-jakarta/src/test/java/com/moesif/servlet/MoesifServletTests.java @@ -241,9 +241,5 @@ public void testUpdateCompaniesBatch() throws Throwable { filter.updateCompaniesBatch(companies); } - public void testGetAppConfig() throws Throwable{ -// filter.init(filterConfig); - int sampleRate = AppConfigManager.getInstance().getSampleRate(null, null); - assertTrue("Sample Rate should be less than equal to 100", 100 >= sampleRate); - } + } diff --git a/moesif-servlet/pom.xml b/moesif-servlet/pom.xml index 3ef48a0..4d41844 100644 --- a/moesif-servlet/pom.xml +++ b/moesif-servlet/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.moesif.servlet moesif-servlet - 1.7.8 + 1.7.9 jar moesif-servlet Moesif SDK for Java Servlet to log and analyze API calls @@ -39,12 +39,12 @@ UTF-8 - 1.7 - 1.7 + 1.8 + 1.8 2.7 3.4 1.1.3 - 1.7 + 1.8 @@ -57,7 +57,7 @@ com.moesif.api moesifapi - 1.7.0 + 1.7.4 org.apache.commons diff --git a/moesif-servlet/src/main/java/com/moesif/servlet/AppConfigManager.java b/moesif-servlet/src/main/java/com/moesif/servlet/AppConfigManager.java deleted file mode 100644 index 05282bf..0000000 --- a/moesif-servlet/src/main/java/com/moesif/servlet/AppConfigManager.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.moesif.servlet; - -import com.moesif.api.MoesifAPIClient; -import com.moesif.api.controllers.APIController; -import com.moesif.api.http.response.HttpResponse; -import com.moesif.api.models.AppConfigModel; - -import java.io.InputStream; -import java.util.Date; -import java.util.TimerTask; -import java.util.logging.Logger; - -/*** - * TimerTask to manage the appConfig and get it from moesif periodically - * to update local cache. - */ -public class AppConfigManager extends TimerTask { - - private static final Logger logger = Logger.getLogger(AppConfigManager.class.toString()); - private static AppConfigManager instance = null; - - private MoesifAPIClient moesifApi = null; - private AppConfigModel appConfigModel = new AppConfigModel(); - private String cachedConfigEtag; - private Date lastUpdatedTime = new Date(0); - private boolean jobRunning = false; // to avoid running multiple job - private boolean debug = false; - - public boolean isJobRunning() { - return jobRunning; - } - - public static synchronized AppConfigManager getInstance() { - if (instance == null) { - instance = new AppConfigManager(); - } - - return instance; - } - - public void setMoesifApiClient(MoesifAPIClient moesifApi, boolean debug) { - this.moesifApi = moesifApi; - this.debug = debug; - } - - private AppConfigManager() { - } - - public int getSampleRate(String userId, String companyId) { - int sampleRate = appConfigModel.getSampleRate(); - if (userId != null && appConfigModel.getUserSampleRate().containsKey(userId)) { - sampleRate = appConfigModel.getUserSampleRate().get(userId); - } else if (companyId != null && appConfigModel.getCompanySampleRate().containsKey(companyId)) { - sampleRate = appConfigModel.getCompanySampleRate().get(companyId); - } - return sampleRate; - } - - /*** - * Method to update the appConfigModel based on Etag - * if cached copy is stale. - * @param responseConfigEtag: String - */ - public void updateIfStale(String responseConfigEtag) { - // Ignore, if job is already in-progress. - if (this.isJobRunning()) { - return; - } - - // Check if needed to call the getConfig api to update app config - if (responseConfigEtag != null - && !(responseConfigEtag.equals(this.cachedConfigEtag)) - && new Date().after(new Date(this.lastUpdatedTime.getTime() + 5 * 60 * 1000)) - ) { - if (this.debug) { - logger.info("Calling API to update appConfig based on Etag."); - } - // Call api to update samplingPercentage - this.run(); - } - } - - /*** - * TaskRunner to update the local cache of ppConfig from the server. - * It also keeps track of a flag to show if job is in-progress. - */ - @Override - public void run() { - // Skip, if job is already in-progress. - if (this.isJobRunning()) { - return; - } - - try { - this.jobRunning = true; - - // Calling the api - HttpResponse configApiResponse = moesifApi.getAPI().getAppConfig(); - // Fetch the response ETag - String responseConfigEtag = configApiResponse.getHeaders().get("x-moesif-config-etag"); - - // Read the response body - InputStream respBodyIs = configApiResponse.getRawBody(); - AppConfigModel newConfig = APIController.parseAppConfigModel(respBodyIs); - respBodyIs.close(); - - this.appConfigModel = newConfig; - this.cachedConfigEtag = responseConfigEtag; - } catch(Throwable e) { - logger.warning("Fetched configuration failed; using default configuration " + e.toString()); - this.appConfigModel = new AppConfigModel(); - this.appConfigModel.setSampleRate(100); - } finally { - jobRunning = false; - } - this.lastUpdatedTime = new Date(); - } - -} diff --git a/moesif-servlet/src/main/java/com/moesif/servlet/BatchProcessor.java b/moesif-servlet/src/main/java/com/moesif/servlet/BatchProcessor.java index 19d7cca..6587cb3 100644 --- a/moesif-servlet/src/main/java/com/moesif/servlet/BatchProcessor.java +++ b/moesif-servlet/src/main/java/com/moesif/servlet/BatchProcessor.java @@ -101,15 +101,6 @@ public void onSuccess(HttpContext httpContext, HttpResponse httpResponse) { final int status = httpContext.getResponse().getStatusCode(); // No need to retry. Mark call done. done[0] = true; - if (status == 201) { - // Fetch the response ETag to check if we need to update appConfig. - String responseConfigEtag = httpResponse.getHeaders().get("x-moesif-config-etag"); - if (responseConfigEtag != null) { - AppConfigManager.getInstance().updateIfStale(responseConfigEtag); - } - } else if (debug) { - logger.warning("Status is " + status); - } } public void onFailure(HttpContext httpContext, Throwable error) { diff --git a/moesif-servlet/src/main/java/com/moesif/servlet/MoesifFilter.java b/moesif-servlet/src/main/java/com/moesif/servlet/MoesifFilter.java index 0ca3a76..2060eb1 100644 --- a/moesif-servlet/src/main/java/com/moesif/servlet/MoesifFilter.java +++ b/moesif-servlet/src/main/java/com/moesif/servlet/MoesifFilter.java @@ -1,34 +1,22 @@ package com.moesif.servlet; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; -import java.lang.*; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.moesif.api.models.*; - +import com.moesif.api.BodyParser; +import com.moesif.api.IpAddress; import com.moesif.api.MoesifAPIClient; -import com.moesif.api.http.client.APICallBack; -import com.moesif.api.http.client.HttpContext; import com.moesif.api.controllers.APIController; -import com.moesif.api.IpAddress; -import com.moesif.api.BodyParser; - +import com.moesif.api.models.*; import com.moesif.servlet.wrappers.LoggingHttpServletRequestWrapper; import com.moesif.servlet.wrappers.LoggingHttpServletResponseWrapper; import org.apache.commons.lang3.StringUtils; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + public class MoesifFilter implements Filter { private static final Logger logger = Logger.getLogger(MoesifFilter.class.toString()); @@ -175,10 +163,6 @@ public void init(FilterConfig filterConfig) throws ServletException { } } - // Setup app config manager and run it immediately to load app config. - AppConfigManager.getInstance().setMoesifApiClient(this.moesifApi, this.debug); - AppConfigManager.getInstance().run(); - // Initialize the batch event processor and timer tasks. this.initBatchProcessorAndStartJobs(); } @@ -343,6 +327,33 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha EventRequestModel eventRequestModel = getEventRequestModel(requestWrapper, startDate, config.getApiVersion(httpRequest, httpResponse), transactionId); + EventModel event = createEvent(eventRequestModel, + config.identifyUser(httpRequest, null), + config.identifyCompany(httpRequest, null), + config.getSessionToken(httpRequest, null), + config.getTags(httpRequest, null), + config.getMetadata(httpRequest, null) + ); + + if(moesifApi.getAPI().isBlockedByGovernanceRules(event)) { + EventResponseModel responseModel = event.getResponse(); + if (transactionId != null) { + responseModel.getHeaders().put("X-Moesif-Transaction-Id", transactionId); + } + + EventModel maskedEvent = config.maskContent(event); + this.addEventToQueue(maskedEvent); + Map headers = responseModel.getHeaders(); + headers.forEach((key, value) -> { + httpResponse.setHeader(key, value); + }); + httpResponse.setStatus(responseModel.getStatus()); + httpResponse.setContentType(responseModel.getTransferEncoding()); + httpResponse.getWriter().write(responseModel.getBody().toString()); + return; + } + + // pass to next step in the chain. try { filterChain.doFilter(requestWrapper, responseWrapper); @@ -429,7 +440,7 @@ private void initBatchProcessorAndStartJobs() { this.batchProcessor = new BatchProcessor(this.moesifApi, this.config, this.debug); // Initialize the timer tasks - Create scheduled jobs - this.scheduleAppConfigJob(); +// this.scheduleAppConfigJob(); this.scheduleBatchEventsJob(); } @@ -455,20 +466,6 @@ public void drainQueueAndStopJobs() { } } - /** - * Method to create scheduled job for updating config periodically. - */ - private void scheduleAppConfigJob() { - // Make sure there is none before creating the timer - this.resetJobTimer(this.updateConfigTimer); - - this.updateConfigTimer = new Timer("moesif_update_config_job"); - updateConfigTimer.schedule( - AppConfigManager.getInstance(), - (long) this.batchProcessor.getUpdateConfigTime() * 1000, // Trigger this job every X seconds since we're already fetching the app config on init. - (long) this.batchProcessor.getUpdateConfigTime() * 1000 - ); - } /** * Method to create scheduled job for sending batch events periodically. @@ -555,6 +552,34 @@ private void addEventToQueue(EventModel maskedEvent) { } } + private EventModel createEvent(EventRequestModel eventRequestModel, + String userId, + String companyId, + String sessionToken, + String tags, + Object metadata) { + + EventBuilder eb = new EventBuilder(); + eb.request(eventRequestModel); + eb.direction("Incoming"); + if (userId != null) { + eb.userId(userId); + } + if (companyId != null) { + eb.companyId(companyId); + } + if (sessionToken != null) { + eb.sessionToken(sessionToken); + } + if (tags != null) { + eb.tags(tags); + } + if (metadata != null) { + eb.metadata(metadata); + } + return eb.build(); + } + private void sendEvent(EventRequestModel eventRequestModel, EventResponseModel eventResponseModel, String userId, @@ -585,22 +610,7 @@ private void sendEvent(EventRequestModel eventRequestModel, EventModel event = eb.build(); if (this.moesifApi != null) { - // actually send the event here. - APICallBack callBack = new APICallBack() { - public void onSuccess(HttpContext context, Object response) { - if (debug) { - logger.info("send to Moesif success"); - } - } - - public void onFailure(HttpContext context, Throwable error) { - if (debug) { - logger.info("send to Moesif error "); - logger.info( error.toString()); - } - } - }; try { @@ -612,7 +622,7 @@ public void onFailure(HttpContext context, Throwable error) { // Generate random number double randomPercentage = Math.random() * 100; - int samplingPercentage = AppConfigManager.getInstance().getSampleRate(userId, companyId); + int samplingPercentage = moesifApi.getAPI().getSampleRateToUse(event); // Compare percentage to send event if (samplingPercentage >= randomPercentage) { diff --git a/moesif-servlet/src/test/java/com/moesif/servlet/MoesifServletTests.java b/moesif-servlet/src/test/java/com/moesif/servlet/MoesifServletTests.java index 4422104..e9c112e 100644 --- a/moesif-servlet/src/test/java/com/moesif/servlet/MoesifServletTests.java +++ b/moesif-servlet/src/test/java/com/moesif/servlet/MoesifServletTests.java @@ -241,9 +241,5 @@ public void testUpdateCompaniesBatch() throws Throwable { filter.updateCompaniesBatch(companies); } - public void testGetAppConfig() throws Throwable{ -// filter.init(filterConfig); - int sampleRate = AppConfigManager.getInstance().getSampleRate(null, null); - assertTrue("Sample Rate should be less than equal to 100", 100 >= sampleRate); - } + } diff --git a/moesif-springrequest/pom.xml b/moesif-springrequest/pom.xml index 06a3fc6..78a0b40 100644 --- a/moesif-springrequest/pom.xml +++ b/moesif-springrequest/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.moesif.springrequest moesif-springrequest - 1.0.18 + 1.1.0 jar moesif-springrequest Moesif SDK for Java to log and analyze outgoing API calls @@ -39,15 +39,15 @@ UTF-8 - 1.7 - 1.7 + 1.8 + 1.8 3.1.0 2.4 3.4 4.13.2 1.1.3 1.10.19 - 1.7 + 1.8 @@ -55,7 +55,7 @@ com.moesif.api moesifapi - 1.7.0 + 1.7.4 org.springframework diff --git a/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifBlockedClientHttpResponse.java b/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifBlockedClientHttpResponse.java new file mode 100644 index 0000000..6a9e2ba --- /dev/null +++ b/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifBlockedClientHttpResponse.java @@ -0,0 +1,60 @@ +package com.moesif.springrequest; + +import com.moesif.api.models.EventResponseModel; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.MultiValueMap; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + + +public class MoesifBlockedClientHttpResponse implements ClientHttpResponse { + private EventResponseModel response; + + + + MoesifBlockedClientHttpResponse(EventResponseModel response) { + this.response = response; + } + + + @Override + public InputStream getBody() throws IOException { + return new ByteArrayInputStream(response.getBody().toString().getBytes()); + } + + // wrap all methods required by ClientHttpResponse + @Override + public int getRawStatusCode() throws IOException { + return response.getStatus(); + } + + @Override + public HttpStatus getStatusCode() throws IOException { + return HttpStatus.valueOf(getRawStatusCode()); + } + + @Override + public void close() { + + } + + @Override + public HttpHeaders getHeaders() { + HttpHeaders headers = new HttpHeaders(); + for (String key : response.getHeaders().keySet()) { + headers.put(key, Arrays.asList(response.getHeaders().get(key))); + } + return headers; + } + + @Override + public String getStatusText() throws IOException { + return getStatusCode().getReasonPhrase(); + } +} \ No newline at end of file diff --git a/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifSpringRequestInterceptor.java b/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifSpringRequestInterceptor.java index 1401ab9..5371042 100644 --- a/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifSpringRequestInterceptor.java +++ b/moesif-springrequest/src/main/java/com/moesif/springrequest/MoesifSpringRequestInterceptor.java @@ -45,8 +45,6 @@ public class MoesifSpringRequestInterceptor implements ClientHttpRequestIntercep public MoesifSpringRequestInterceptor(MoesifAPIClient moesifApi) { this.moesifApi = moesifApi; this.config = new MoesifRequestConfiguration(); - - this.moesifApi.getAPI().setShouldSyncAppConfig(true); } /** @@ -56,8 +54,6 @@ public MoesifSpringRequestInterceptor(MoesifAPIClient moesifApi) { public MoesifSpringRequestInterceptor(String applicationId) { this.moesifApi = new MoesifAPIClient(applicationId); this.config = new MoesifRequestConfiguration(); - - this.moesifApi.getAPI().setShouldSyncAppConfig(true); } /** @@ -185,6 +181,28 @@ private EventResponseModel buildEventResponseModel(Exception e) { public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { IOException queryException = null; EventRequestModel eventRequestModel = buildEventRequestModel(request, body); + + EventModel event = createEvent(eventRequestModel, + config.identifyUser(request, null), + config.identifyCompany(request, null), + config.getSessionToken(request, null), + config.getMetadata(request, null) + ); + + if (moesifApi.getAPI().isBlockedByGovernanceRules(event)) { + EventResponseModel responseModel = event.getResponse(); + if (!config.skip(request, null)) { + EventModel maskedEvent = config.maskContent(event); + try { + moesifApi.getAPI().createEvent(maskedEvent); + } catch (Throwable e) { + warn(e); + } + } + MoesifBlockedClientHttpResponse response = new MoesifBlockedClientHttpResponse(responseModel); + return response; + } + EventResponseModel eventResponseModel = null; MoesifClientHttpResponse response = null; @@ -253,5 +271,30 @@ private void warn(Throwable e) { logger.warning("Warning:\n" + e.toString()); } } + + private EventModel createEvent(EventRequestModel eventRequestModel, + String userId, + String companyId, + String sessionToken, + Object metadata) { + + EventBuilder eb = new EventBuilder(); + eb.request(eventRequestModel); + eb.direction("Incoming"); + if (userId != null) { + eb.userId(userId); + } + if (companyId != null) { + eb.companyId(companyId); + } + if (sessionToken != null) { + eb.sessionToken(sessionToken); + } + + if (metadata != null) { + eb.metadata(metadata); + } + return eb.build(); + } } diff --git a/servlet-example/pom.xml b/servlet-example/pom.xml index 4d63b02..43e2bd8 100644 --- a/servlet-example/pom.xml +++ b/servlet-example/pom.xml @@ -28,7 +28,7 @@ com.moesif.servlet moesif-servlet - 1.7.8 + 1.7.9 diff --git a/spark-servlet-example/pom.xml b/spark-servlet-example/pom.xml index 53dcd9b..ea10b91 100644 --- a/spark-servlet-example/pom.xml +++ b/spark-servlet-example/pom.xml @@ -76,7 +76,7 @@ com.moesif.servlet moesif-servlet - 1.7.8 + 1.7.9