docs: protected long proxyPlainTextRequest(final URL url, String pathInContext, String pathParams, HttpRequest request, final HttpResponse response) throws IOException {
          try {
              String urlStr = url.toString();
  
              if (urlStr.toLowerCase().startsWith(Constants.ODO_INTERNAL_WEBAPP_URL)) {
                  urlStr = "http://localhost:" + com.groupon.odo.proxylib.Utils.getSystemPort(Constants.SYS_HTTP_PORT) + "/odo";
              }
  
              // setup okhttp to ignore ssl issues
              OkHttpClient okHttpClient = getUnsafeOkHttpClient();
              okHttpClient.setFollowRedirects(false);
              okHttpClient.setFollowSslRedirects(false);
              okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
              okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
              okHttpClient.setWriteTimeout(60, TimeUnit.SECONDS);
  
              Request.Builder okRequestBuilder = new Request.Builder();
  
              /*
               * urlStr.indexOf(":") == urlStr.lastIndexOf(":") verifies that the url does not have a port
               * by checking it only has a : as part of http://
               */
              if (urlStr.startsWith("http://") && urlStr.indexOf(":") == urlStr.lastIndexOf(":")) {
                  int httpPort = com.groupon.odo.proxylib.Utils.getSystemPort(Constants.SYS_HTTP_PORT);
                  urlStr = urlStr.replace(getHostNameFromURL(urlStr), localIP + ":" + httpPort);
              }
  
              okRequestBuilder = okRequestBuilder.url(urlStr);
  
              // copy request headers
              Enumeration<?> enm = request.getFieldNames();
              boolean isGet = "GET".equals(request.getMethod());
              boolean hasContent = false;
              boolean usedContentLength = false;
              long contentLength = 0;
              while (enm.hasMoreElements()) {
                  String hdr = (String) enm.nextElement();
  
                  if (!isGet && HttpFields.__ContentType.equals(hdr)) {
                      hasContent = true;
                  }
                  if (!isGet && HttpFields.__ContentLength.equals(hdr)) {
                      contentLength = Long.parseLong(request.getField(hdr));
                      usedContentLength = true;
                  }
  
                  Enumeration<?> vals = request.getFieldValues(hdr);
                  while (vals.hasMoreElements()) {
                      String val = (String) vals.nextElement();
                      if (val != null) {
                          if (!isGet && HttpFields.__ContentLength.equals(hdr) && Integer.parseInt(val) > 0) {
                              hasContent = true;
                          }
  
                          if (!_DontProxyHeaders.containsKey(hdr)) {
                              okRequestBuilder = okRequestBuilder.addHeader(hdr, val);
                              //httpReq.addRequestHeader(hdr, val);
                          }
                      }
                  }
              }
  
              if ("GET".equals(request.getMethod())) {
                  // don't need to do anything else
              } else if ("POST".equals(request.getMethod()) ||
                         "PUT".equals(request.getMethod()) ||
                         "DELETE".equals(request.getMethod())) {
                  RequestBody okRequestBody = null;
                  if (hasContent) {
                      final String contentType = request.getContentType();
                      final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
  
                      okRequestBody = new RequestBody() {
                          @Override
                          public MediaType contentType() {
                              MediaType.parse(contentType);
                              return null;
                          }
  
                          @Override
                          public void writeTo(BufferedSink bufferedSink) throws IOException {
                              bufferedSink.write(bytes);
                          }
                      };
  
                      // we need to add some ODO specific headers to give ODO a hint for content-length vs transfer-encoding
                      // since okHTTP will automatically chunk even if the request was not chunked
                      // this allows Odo to set the appropriate headers when the server request is made
                      if (usedContentLength) {
                          okRequestBuilder = okRequestBuilder.addHeader("ODO-POST-TYPE", "content-length:" + contentLength);
                      }
                  } else {
                      okRequestBody = RequestBody.create(null, new byte[0]);
                  }
  
                  if ("POST".equals(request.getMethod())) {
                      okRequestBuilder = okRequestBuilder.post(okRequestBody);
                  } else if ("PUT".equals(request.getMethod())) {
                      okRequestBuilder = okRequestBuilder.put(okRequestBody);
                  } else if ("DELETE".equals(request.getMethod())) {
                      okRequestBuilder = okRequestBuilder.delete(okRequestBody);
                  }
              } else if ("OPTIONS".equals(request.getMethod())) {
                  // NOT SUPPORTED
              } else if ("HEAD".equals(request.getMethod())) {
                  okRequestBuilder = okRequestBuilder.head();
              } else {
                  LOG.warn("Unexpected request method %s, giving up", request.getMethod());
                  request.setHandled(true);
                  return -1;
              }
  
              Request okRequest = okRequestBuilder.build();
              Response okResponse = okHttpClient.newCall(okRequest).execute();
  
              // Set status and response message
              response.setStatus(okResponse.code());
              response.setReason(okResponse.message());
  
              // copy response headers
              for (int headerNum = 0; headerNum < okResponse.headers().size(); headerNum++) {
                  String headerName = okResponse.headers().name(headerNum);
                  if (!_DontProxyHeaders.containsKey(headerName) && !_ProxyAuthHeaders.containsKey(headerName)) {
                      response.addField(headerName, okResponse.headers().value(headerNum));
                  }
              }
  
              // write output to response output stream
              try {
                  IOUtils.copy(okResponse.body().byteStream(), response.getOutputStream());
              } catch (Exception e) {
                  // ignoring this until we refactor the proxy
                  // The copy occasionally fails due to an issue where okResponse has more data in the body than it's supposed to
                  // The client still gets all of the data it was expecting
              }
  
              request.setHandled(true);
              return okResponse.body().contentLength();
          } catch (Exception e) {
              LOG.warn("Caught exception proxying: ", e);
              reportError(e, url, response);
              request.setHandled(true);
              return -1;
          }
      }