anchor.diff:  <%@page session="false"%>
   <%@page import=
  -"java.net.HttpURLConnection,
  +                "java.net.HttpURLConnection,
   java.net.URL,
   java.net.URLEncoder,
   java.net.URLDecoder,
  
positive.code: java.text.SimpleDateFormat" %>
  
  <!-- ----------------------------------------------------------
   *
   * JSP proxy client
   *
   * Version 1.1 beta
   * See https://github.com/Esri/resource-proxy for more information.
   *
  ----------------------------------------------------------- -->
  
  <%! final String version = "1.1 Beta";   %>
  
  <%!
  public static class RateMeter {
      double _rate; //internal rate is stored in requests per second
      int _countCap;
      double _count = 0;
  
negative.code:     output.write(message.getBytes());
  
      output.flush();
    }
  
    private static void _sendURLMismatchError(HttpServletResponse response, String attemptedUri) throws IOException{
      sendErrorResponse(response, "Proxy has not been set up for this URL. Make sure there is a serverUrl in the configuration file that matches: " + attemptedUri,
              "Proxy has not been set up for this URL.", HttpServletResponse.SC_FORBIDDEN);
    }
  
    private static void _sendPingMessage(HttpServletResponse response, String version, String config, String log) throws IOException{
      response.setStatus(HttpServletResponse.SC_OK);
      response.setHeader("Content-Type", "application/json");
      String message = "{ " +
              "\"Proxy Version\": \"" + version + "\"" +
              //", \"Java Version\": \"" + System.getProperty("java.version") + "\"" +
              ", \"Configuration File\": \"" + config + "\""  +
              ", \"Log File\": \"" + log + "\"" +
              "}";
      OutputStream output = response.getOutputStream();
      output.write(message.getBytes());
      output.flush();
    }
  %><%
    String uri = request.getQueryString();
    _log(Level.INFO, "Creating request for: " + uri);
    ServerUrl serverUrl;
    boolean passThrough = false;
    try {
      try {
  
        out.clear();
        out = pageContext.pushBody();
  
        if (uri == null || uri.isEmpty()){
          String errorMessage = "This proxy does not support empty parameters.";
          _log(Level.WARNING, errorMessage);
          sendErrorResponse(response, errorMessage, "400 - " + errorMessage, HttpServletResponse.SC_BAD_REQUEST);
          return;
        }
  
        if (uri.equalsIgnoreCase("ping")){
          String checkConfig = (getConfig().canReadProxyConfig() == true) ? "OK": "Not Readable";
          String checkLog = (okToLog() == true) ? "OK": "Not Exist/Readable";
          _sendPingMessage(response, version, checkConfig, checkLog);
          return;
        }
  
        //check if the uri is encoded then decode it
        if (uri.toLowerCase().startsWith("http%3a%2f%2f") || uri.toLowerCase().startsWith("https%3a%2f%2f")) uri= URLDecoder.decode(uri, "UTF-8");
  
        String[] allowedReferers = getConfig().getAllowedReferers();
        if (allowedReferers != null && allowedReferers.length > 0 && request.getHeader("referer") != null){
          setReferer(request.getHeader("referer")); //replace PROXY_REFERER with real proxy
          String hostReferer = request.getHeader("referer");
          try{
            //only use the hostname of the referer url
            hostReferer = new URL(request.getHeader("referer")).getHost();
          }catch(Exception e){
            _log(Level.WARNING, "Proxy is being used from an invalid referer: " + request.getHeader("referer"));
            sendErrorResponse(response, "Error verifying referer. ", "403 - Forbidden: Access is denied.", HttpServletResponse.SC_FORBIDDEN);
            return;
          }
          if (!checkReferer(allowedReferers, hostReferer)){
            _log(Level.WARNING, "Proxy is being used from an unknown referer: " + request.getHeader("referer"));
            sendErrorResponse(response, "Unsupported referer. ", "403 - Forbidden: Access is denied.", HttpServletResponse.SC_FORBIDDEN);
            return;
          }
        }
  
        //Check to see if allowed referer list is specified and reject if referer is null
        if (request.getHeader("referer") == null && allowedReferers != null && !allowedReferers[0].equals("*")){
          _log(Level.WARNING, "Proxy is being called by a null referer.  Access denied.");
          sendErrorResponse(response, "Current proxy configuration settings do not allow requests which do not include a referer header.", "403 - Forbidden: Access is denied.", HttpServletResponse.SC_FORBIDDEN);
          return;
        }
  
        serverUrl = getConfig().getConfigServerUrl(uri);
        if (serverUrl == null) {
          //if no serverUrl found, send error message and get out.
          _sendURLMismatchError(response, uri);
          return;
        }
        passThrough = serverUrl == null;
      } catch (IllegalStateException e) {
        _log(Level.WARNING, "Proxy is being used for an unsupported service: " + uri);
  
        _sendURLMismatchError(response, uri);
  
        return;
      }
  
      //Throttling: checking the rate limit coming from particular referrer
      if (!passThrough && serverUrl.getRateLimit() > -1) {
        synchronized(_rateMapLock){
          ConcurrentHashMap<String, RateMeter> ratemap = (ConcurrentHashMap<String, RateMeter>)application.getAttribute("rateMap");
          if (ratemap == null){
            ratemap = new ConcurrentHashMap<String, RateMeter>();
            application.setAttribute("rateMap", ratemap);
            application.setAttribute("rateMap_cleanup_counter", 0);
          }
  
  
          String key = "[" + serverUrl.getUrl() + "]x[" + request.getRemoteAddr() + "]";
          RateMeter rate = ratemap.get(key);
          if (rate == null) {
            rate = new RateMeter(serverUrl.getRateLimit(), serverUrl.getRateLimitPeriod());
            RateMeter rateCheck = ratemap.putIfAbsent(key, rate);
            if (rateCheck != null){
              rate = rateCheck;
            }
          }
          if (!rate.click()) {
            _log(Level.WARNING, "Pair " + key + " is throttled to " + serverUrl.getRateLimit() + " requests per " + serverUrl.getRateLimitPeriod() + " minute(s). Come back later.");
  
            sendErrorResponse(response, "This is a metered resource, number of requests have exceeded the rate limit interval.",
                    "Error 429 - Too Many Requests", 429);
  
            return;
          }
  
          //making sure the rateMap gets periodically cleaned up so it does not grow uncontrollably
          int cnt = ((Integer)application.getAttribute("rateMap_cleanup_counter")).intValue();
          cnt++;
          if (cnt >= CLEAN_RATEMAP_AFTER) {
            cnt = 0;
            cleanUpRatemap(ratemap);
          }
          application.setAttribute("rateMap_cleanup_counter", new Integer(cnt));
        };
      }
  
      //readying body (if any) of POST request
  