@Post
  public Reply<?> newProxy(Request<String> request) {
    String systemProxyHost = System.getProperty("http.proxyHost");
    String systemProxyPort = System.getProperty("http.proxyPort");
    String httpProxy = request.param("httpProxy");
    Hashtable<String, String> options = new Hashtable<String, String>();

    // If the upstream proxy is specified via query params that should override any default system
    // level proxy.
    if (httpProxy != null) {
      options.put("httpProxy", httpProxy);
    } else if ((systemProxyHost != null) && (systemProxyPort != null)) {
      options.put("httpProxy", String.format("%s:%s", systemProxyHost, systemProxyPort));
    }

    String paramBindAddr = request.param("bindAddress");
    Integer paramPort =
        request.param("port") == null ? null : Integer.parseInt(request.param("port"));
    String useEccString = request.param("useEcc");
    boolean useEcc = Boolean.parseBoolean(useEccString);
    LOG.debug("POST proxy instance on bindAddress `{}` & port `{}`", paramBindAddr, paramPort);
    LegacyProxyServer proxy;
    try {
      proxy = proxyManager.create(options, paramPort, paramBindAddr, useEcc);
    } catch (ProxyExistsException ex) {
      return Reply.with(new ProxyDescriptor(ex.getPort())).status(455).as(Json.class);
    } catch (ProxyPortsExhaustedException ex) {
      return Reply.saying().status(456);
    } catch (Exception ex) {
      StringWriter s = new StringWriter();
      ex.printStackTrace(new PrintWriter(s));
      return Reply.with(s).as(Text.class).status(550);
    }
    return Reply.with(new ProxyDescriptor(proxy.getPort())).as(Json.class);
  }
  @Put
  @At("/:port/har")
  public Reply<?> newHar(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String initialPageRef = request.param("initialPageRef");
    String initialPageTitle = request.param("initialPageTitle");
    Har oldHar = proxy.newHar(initialPageRef, initialPageTitle);

    String captureHeaders = request.param("captureHeaders");
    String captureContent = request.param("captureContent");
    String captureBinaryContent = request.param("captureBinaryContent");
    proxy.setCaptureHeaders(Boolean.parseBoolean(captureHeaders));
    proxy.setCaptureContent(Boolean.parseBoolean(captureContent));
    proxy.setCaptureBinaryContent(Boolean.parseBoolean(captureBinaryContent));

    if (oldHar != null) {
      return Reply.with(oldHar).as(Json.class);
    } else {
      return Reply.saying().noContent();
    }
  }
 @Get
 @At("/:port/limit")
 public Reply<?> getLimits(@Named("port") int port, Request<String> request) {
   LegacyProxyServer proxy = proxyManager.get(port);
   if (proxy == null) {
     return Reply.saying().notFound();
   }
   return Reply.with(new BandwidthLimitDescriptor(proxy.getStreamManager())).as(Json.class);
 }
  @Get
  @At("/:port/whitelist")
  public Reply<?> getWhitelist(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    return Reply.with(proxy.getWhitelistUrls()).as(Json.class);
  }
  @Delete
  @At("/:port/dns/cache")
  public Reply<?> clearDnsCache(@Named("port") int port) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    proxy.clearDNSCache();
    return Reply.saying().ok();
  }
  @Delete
  @At("/:port/rewrite")
  public Reply<?> clearRewriteRules(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    proxy.clearRewriteRules();
    return Reply.saying().ok();
  }
  @Delete
  @At("/:port")
  public Reply<?> delete(@Named("port") int port) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    proxyManager.delete(port);
    return Reply.saying().ok();
  }
  @Get
  @At("/:port/har")
  public Reply<?> getHar(@Named("port") int port) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    Har har = proxy.getHar();

    return Reply.with(har).as(Json.class);
  }
  @Put
  @At("/:port/retry")
  public Reply<?> retryCount(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String count = request.param("retrycount");
    proxy.setRetryCount(Integer.parseInt(count));
    return Reply.saying().ok();
  }
  @Put
  @At("/:port/rewrite")
  public Reply<?> rewriteUrl(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String match = request.param("matchRegex");
    String replace = request.param("replace");
    proxy.rewriteUrl(match, replace);
    return Reply.saying().ok();
  }
  @Post
  @At("/:port/auth/basic/:domain")
  public Reply<?> autoBasicAuth(
      @Named("port") int port, @Named("domain") String domain, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    Map<String, String> credentials = request.read(HashMap.class).as(Json.class);
    proxy.autoBasicAuthorization(domain, credentials.get("username"), credentials.get("password"));

    return Reply.saying().ok();
  }
  @Put
  @At("/:port/whitelist")
  public Reply<?> whitelist(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String regex = request.param("regex");
    int responseCode = parseResponseCode(request.param("status"));
    proxy.whitelistRequests(regex.split(","), responseCode);

    return Reply.saying().ok();
  }
  @Put
  @At("/:port/har/pageRef")
  public Reply<?> setPage(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String pageRef = request.param("pageRef");
    String pageTitle = request.param("pageTitle");
    proxy.newPage(pageRef, pageTitle);

    return Reply.saying().ok();
  }
  @Post
  @RequiresLogin
  public Reply<?> postStatus() {
    newStatus.setAuthor(userSession.get());
    newStatus.setPostTime(clock.now());

    if (newStatus.getText().length() > 140) {
      return Reply.saying().redirect("/"); // TODO: Error message
    }

    statusService.postStatus(newStatus);

    return Reply.saying().redirect("/");
  }
  @Put
  @At("/:port/wait")
  public Reply<?> wait(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String quietPeriodInMs = request.param("quietPeriodInMs");
    String timeoutInMs = request.param("timeoutInMs");
    proxy.waitForNetworkTrafficToStop(
        Integer.parseInt(quietPeriodInMs), Integer.parseInt(timeoutInMs));
    return Reply.saying().ok();
  }
  @Put
  @At("/:port/blacklist")
  public Reply<?> blacklist(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String blacklist = request.param("regex");
    int responseCode = parseResponseCode(request.param("status"));
    String method = request.param("method");
    proxy.blacklistRequests(blacklist, responseCode, method);

    return Reply.saying().ok();
  }
  @Post
  @At("/:port/headers")
  public Reply<?> updateHeaders(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    Map<String, String> headers = request.read(Map.class).as(Json.class);
    for (Map.Entry<String, String> entry : headers.entrySet()) {
      String key = entry.getKey();
      String value = entry.getValue();
      proxy.addHeader(key, value);
    }
    return Reply.saying().ok();
  }
 @Get
 public Reply<?> getProxies() {
   Collection<ProxyDescriptor> proxyList = new ArrayList<ProxyDescriptor>();
   for (LegacyProxyServer proxy : proxyManager.get()) {
     proxyList.add(new ProxyDescriptor(proxy.getPort()));
   }
   return Reply.with(new ProxyListDescriptor(proxyList)).as(Json.class);
 }
  @Post
  @At("/:port/hosts")
  public Reply<?> remapHosts(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    @SuppressWarnings("unchecked")
    Map<String, String> headers = request.read(Map.class).as(Json.class);

    for (Map.Entry<String, String> entry : headers.entrySet()) {
      String key = entry.getKey();
      String value = entry.getValue();
      proxy.remapHost(key, value);
      proxy.setDNSCacheTimeout(0);
      proxy.clearDNSCache();
    }

    return Reply.saying().ok();
  }
  @Post
  @At("/:port/interceptor/request")
  public Reply<?> addRequestInterceptor(@Named("port") int port, Request<String> request)
      throws IOException, ScriptException {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    if (!(proxy instanceof ProxyServer)) {
      return Reply.saying().badRequest();
    }

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    request.readTo(baos);

    ScriptEngineManager mgr = new ScriptEngineManager();
    final ScriptEngine engine = mgr.getEngineByName("JavaScript");
    Compilable compilable = (Compilable) engine;
    final CompiledScript script = compilable.compile(baos.toString());

    proxy.addRequestInterceptor(
        new RequestInterceptor() {
          @Override
          public void process(BrowserMobHttpRequest request, Har har) {
            Bindings bindings = engine.createBindings();
            bindings.put("request", request);
            bindings.put("har", har);
            bindings.put("log", LOG);
            try {
              script.eval(bindings);
            } catch (ScriptException e) {
              LOG.error("Could not execute JS-based response interceptor", e);
            }
          }
        });

    return Reply.saying().ok();
  }
  @Put
  @At("/:port/timeout")
  public Reply<?> timeout(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    String requestTimeout = request.param("requestTimeout");
    if (requestTimeout != null) {
      try {
        proxy.setRequestTimeout(Integer.parseInt(requestTimeout));
      } catch (NumberFormatException e) {
      }
    }
    String readTimeout = request.param("readTimeout");
    if (readTimeout != null) {
      try {
        proxy.setSocketOperationTimeout(Integer.parseInt(readTimeout));
      } catch (NumberFormatException e) {
      }
    }
    String connectionTimeout = request.param("connectionTimeout");
    if (connectionTimeout != null) {
      try {
        proxy.setConnectionTimeout(Integer.parseInt(connectionTimeout));
      } catch (NumberFormatException e) {
      }
    }
    String dnsCacheTimeout = request.param("dnsCacheTimeout");
    if (dnsCacheTimeout != null) {
      try {
        proxy.setDNSCacheTimeout(Integer.parseInt(dnsCacheTimeout));
      } catch (NumberFormatException e) {
      }
    }
    return Reply.saying().ok();
  }
  @Get
  public Reply<String> get() {
    String runId = request.getParameter("runId");
    if (StringUtils.isBlank(runId)) {
      return Reply.with(StringUtils.EMPTY);
    }

    LogBus logBus = LogBus.get(runId);
    synchronized (logBus.getLock()) {
      if (logBus.size() > 0) {
        log.debug("Found logs from cache, size={}", logBus.size());
        StringBuffer logs = new StringBuffer();
        for (String log : logBus) {
          logs.append(log).append("\n");
        }

        // Clean log cache after get all logs
        logBus.clear();
        return Reply.with(logs.toString());
      }
    }
    return Reply.with(StringUtils.EMPTY);
  }
  @Post
  @At("/:port/filter/response")
  public Reply<?> addResponseFilter(@Named("port") int port, Request<String> request)
      throws IOException, ScriptException {
    LegacyProxyServer legacyProxy = proxyManager.get(port);
    if (legacyProxy == null) {
      return Reply.saying().notFound();
    }

    if (!(legacyProxy instanceof BrowserMobProxyServer)) {
      return Reply.saying().badRequest();
    }

    BrowserMobProxy proxy = (BrowserMobProxy) legacyProxy;

    JavascriptRequestResponseFilter requestResponseFilter = new JavascriptRequestResponseFilter();

    String script = getEntityBodyFromRequest(request);
    requestResponseFilter.setResponseFilterScript(script);

    proxy.addResponseFilter(requestResponseFilter);

    return Reply.saying().ok();
  }
 public Reply<?> reply() {
   FormResponse response = get();
   return Reply.with(response).as(Json.class);
 }
  @Put
  @At("/:port/limit")
  public Reply<?> limit(@Named("port") int port, Request<String> request) {
    LegacyProxyServer proxy = proxyManager.get(port);
    if (proxy == null) {
      return Reply.saying().notFound();
    }

    StreamManager streamManager = proxy.getStreamManager();
    String upstreamKbps = request.param("upstreamKbps");
    if (upstreamKbps != null) {
      try {
        streamManager.setUpstreamKbps(Integer.parseInt(upstreamKbps));
        streamManager.enable();
      } catch (NumberFormatException e) {
      }
    }

    String upstreamBps = request.param("upstreamBps");
    if (upstreamBps != null) {
      try {
        ((BrowserMobProxy) proxy).setWriteBandwidthLimit(Integer.parseInt(upstreamBps));
      } catch (NumberFormatException e) {
      }
    }

    String downstreamKbps = request.param("downstreamKbps");
    if (downstreamKbps != null) {
      try {
        streamManager.setDownstreamKbps(Integer.parseInt(downstreamKbps));
        streamManager.enable();
      } catch (NumberFormatException e) {
      }
    }

    String downstreamBps = request.param("downstreamBps");
    if (downstreamBps != null) {
      try {
        ((BrowserMobProxy) proxy).setReadBandwidthLimit(Integer.parseInt(downstreamBps));
      } catch (NumberFormatException e) {
      }
    }

    String upstreamMaxKB = request.param("upstreamMaxKB");
    if (upstreamMaxKB != null) {
      try {
        streamManager.setUpstreamMaxKB(Integer.parseInt(upstreamMaxKB));
        streamManager.enable();
      } catch (NumberFormatException e) {
      }
    }
    String downstreamMaxKB = request.param("downstreamMaxKB");
    if (downstreamMaxKB != null) {
      try {
        streamManager.setDownstreamMaxKB(Integer.parseInt(downstreamMaxKB));
        streamManager.enable();
      } catch (NumberFormatException e) {
      }
    }
    String latency = request.param("latency");
    if (latency != null) {
      try {
        streamManager.setLatency(Integer.parseInt(latency));
        streamManager.enable();
      } catch (NumberFormatException e) {
      }
    }
    String payloadPercentage = request.param("payloadPercentage");
    if (payloadPercentage != null) {
      try {
        streamManager.setPayloadPercentage(Integer.parseInt(payloadPercentage));
      } catch (NumberFormatException e) {
      }
    }
    String maxBitsPerSecond = request.param("maxBitsPerSecond");
    if (maxBitsPerSecond != null) {
      try {
        streamManager.setMaxBitsPerSecondThreshold(Integer.parseInt(maxBitsPerSecond));
      } catch (NumberFormatException e) {
      }
    }
    String enable = request.param("enable");
    if (enable != null) {
      if (Boolean.parseBoolean(enable)) {
        streamManager.enable();
      } else {
        streamManager.disable();
      }
    }
    return Reply.saying().ok();
  }