public function parseResponse(HttpResponse $response)
    {
        $httpCode = $response->getHttpCode();

        if ($httpCode < 200 || $httpCode >= 400) {
            // failure on server
            $body = $response->getBody();
            if ($body !== '') {
                // check if we can find details in the response body
                $details = json_decode($body, true);

                // handle failover
                if (is_array($details) && isset($details['errorNum'])) {
                    if ($details['errorNum'] === 1495) { 
                        // 1495 = leadership challenge is ongoing
                        $exception = new FailoverException(@$details['errorMessage'], @$details['code']);
                        throw $exception;
                    }

                    if ($details['errorNum'] === 1496) { 
                        // 1496 = not a leader
                        // not a leader. now try to find new leader
                        $leader = $response->getLeaderEndpointHeader();
                        if ($leader) {
                            // have a different leader
                            $leader = Endpoint::normalize($leader);
                            $this->_options->addEndpoint($leader);
                            
                        } else {
                            $leader = $this->_options->nextEndpoint();
                        }
                            
                        // close existing connection
                        $this->closeHandle();
                        $this->updateHttpHeader();

                        $exception = new FailoverException(@$details['errorMessage'], @$details['code']);
                        $exception->setLeader($leader);
                        throw $exception;
                    }
                }

                if (is_array($details) && isset($details['errorMessage'])) {
                    // yes, we got details
                    $exception = new ServerException($details['errorMessage'], $details['code']);
                    $exception->setDetails($details);
                    throw $exception;
                }
            }
            
            // check if server has responded with any other 503 response not handled above
            if ($httpCode === 503) {
                // generic service unavailable response
                $exception = new FailoverException('service unavailable', 503);
                throw $exception;
            }

            // no details found, throw normal exception
            throw new ServerException($response->getResult(), $httpCode);
        }

        return $response;
    }