docs: public HttpConnection execute(HttpConnection connection) {
  
          //set our HttpUrlFactory on the connection
          connection.connectionFactory = factory;
  
          // all CouchClient requests want to receive application/json responses
          connection.requestProperties.put("Accept", "application/json");
          connection.responseInterceptors.addAll(this.responseInterceptors);
          connection.requestInterceptors.addAll(this.requestInterceptors);
          InputStream es = null; // error stream - response from server for a 500 etc
  
          // first try to execute our request and get the input stream with the server's response
          // we want to catch IOException because HttpUrlConnection throws these for non-success
          // responses (eg 404 throws a FileNotFoundException) but we need to map to our own
          // specific exceptions
          try {
              try {
                  connection = connection.execute();
              } catch (HttpConnectionInterceptorException e) {
                  CouchDbException exception = new CouchDbException(connection.getConnection()
                          .getResponseMessage(), connection.getConnection().getResponseCode());
                  if (e.deserialize) {
                      try {
                          JsonObject errorResponse = new Gson().fromJson(e.error, JsonObject
                                  .class);
                          exception.error = getAsString(errorResponse, "error");
                          exception.reason = getAsString(errorResponse, "reason");
                      } catch (JsonParseException jpe) {
                          exception.error = e.error;
                      }
                  } else {
                      exception.error = e.error;
                      exception.reason = e.reason;
                  }
                  throw exception;
              }
              int code = connection.getConnection().getResponseCode();
              String response = connection.getConnection().getResponseMessage();
              // everything ok? return the stream
              if (code / 100 == 2) { // success [200,299]
                  return connection;
              } else {
                  final CouchDbException ex;
                  switch (code) {
                      case HttpURLConnection.HTTP_NOT_FOUND: //404
                          ex = new NoDocumentException(response);
                          break;
                      case HttpURLConnection.HTTP_CONFLICT: //409
                          ex = new DocumentConflictException(response);
                          break;
                      case HttpURLConnection.HTTP_PRECON_FAILED: //412
                          ex = new PreconditionFailedException(response);
                          break;
                      case 429:
                          // If a Replay429Interceptor is present it will check for 429 and retry at
                          // intervals. If the retries do not succeed or no 429 replay was configured
                          // we end up here and throw a TooManyRequestsException.
                          ex = new TooManyRequestsException(response);
                          break;
                      default:
                          ex = new CouchDbException(response, code);
                          break;
                  }
                  es = connection.getConnection().getErrorStream();
                  //if there is an error stream try to deserialize into the typed exception
                  if (es != null) {
                      try {
                          //read the error stream into memory
                          byte[] errorResponse = IOUtils.toByteArray(es);
  
                          Class<? extends CouchDbException> exceptionClass = ex.getClass();
                          //treat the error as JSON and try to deserialize
                          try {
                              // Register an InstanceCreator that returns the existing exception so
                              // we can just populate the fields, but not ignore the constructor.
                              // Uses a new Gson so we don't accidentally recycle an exception.
                              Gson g = new GsonBuilder().registerTypeAdapter(exceptionClass, new
                                      CouchDbExceptionInstanceCreator(ex)).create();
                              // Now populate the exception with the error/reason other info from JSON
                              g.fromJson(new InputStreamReader(new ByteArrayInputStream
                                      (errorResponse),
                                      "UTF-8"), exceptionClass);
                          } catch (JsonParseException e) {
                              // The error stream was not JSON so just set the string content as the
                              // error field on ex before we throw it
                              ex.error = new String(errorResponse, "UTF-8");
                          }
                      } finally {
                          close(es);
                      }
                  }
                  ex.setUrl(connection.url.toString());
                  throw ex;
              }
          } catch (IOException ioe) {
              CouchDbException ex = new CouchDbException("Error retrieving server response", ioe);
              ex.setUrl(connection.url.toString());
              throw ex;
          }
      }