protected HttpResponse sendRequestWithRetry(HttpRequest httpRequest) throws HttpException {
        int retryCounter = 0;
        int maxRetries = httpRequest.getHttpMethod().isIdemponent() ? config.getMaxRetryTimes() : 0;
        if (httpRequest instanceof HttpStreamingRequest) {
            maxRetries = 1; // for streaming, don't retry. the stream cannot be reused.
        }
        do {
            try {
                if (httpRequest instanceof HttpStreamingRequest) {
                    HttpStreamingRequest streamingRequest = (HttpStreamingRequest) httpRequest;
                    return sendRequestOnce(streamingRequest);
                } else {
                    return sendRequestOnce(httpRequest);
                }
            } catch (Exception e) {
                if (++retryCounter >= maxRetries) {
                    e.printStackTrace();
                } else {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ignored) {
                    }
                }
            }
        } while (retryCounter < config.getMaxRetryTimes());
        return new HttpResponse(503, httpRequest.getUrl(), null, null);
    }