1
0
Fork 0

Merge pull request #672 from rqlite/fix_http_redirect

Fix and Test LeaderAPIAddr and LeaderAPIProto
master
Philip O'Toole 4 years ago committed by GitHub
commit 4923ab5bb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -326,8 +326,8 @@ func (s *Service) handleJoin(w http.ResponseWriter, r *http.Request) {
if err := s.store.Join(remoteID.(string), remoteAddr.(string), voter.(bool), m); err != nil {
if err == store.ErrNotLeader {
leaderAPIAddr := s.leaderAPIAddr()
leaderProto := s.leaderAPIProto()
leaderAPIAddr := s.LeaderAPIAddr()
leaderProto := s.LeaderAPIProto()
if leaderAPIAddr == "" {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
@ -381,8 +381,8 @@ func (s *Service) handleRemove(w http.ResponseWriter, r *http.Request) {
if err := s.store.Remove(remoteID); err != nil {
if err == store.ErrNotLeader {
leaderAPIAddr := s.leaderAPIAddr()
leaderProto := s.leaderAPIProto()
leaderAPIAddr := s.LeaderAPIAddr()
leaderProto := s.LeaderAPIProto()
if leaderAPIAddr == "" {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
@ -462,8 +462,8 @@ func (s *Service) handleLoad(w http.ResponseWriter, r *http.Request) {
results, err := s.store.ExecuteOrAbort(&store.ExecuteRequest{queries, timings, false})
if err != nil {
if err == store.ErrNotLeader {
leaderAPIAddr := s.leaderAPIAddr()
leaderProto := s.leaderAPIProto()
leaderAPIAddr := s.LeaderAPIAddr()
leaderProto := s.LeaderAPIProto()
if leaderAPIAddr == "" {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
@ -513,7 +513,7 @@ func (s *Service) handleStatus(w http.ResponseWriter, r *http.Request) {
httpStatus := map[string]interface{}{
"addr": s.Addr().String(),
"auth": prettyEnabled(s.credentialStore != nil),
"redirect": s.leaderAPIAddr(),
"redirect": s.LeaderAPIAddr(),
}
nodeStatus := map[string]interface{}{
@ -610,8 +610,8 @@ func (s *Service) handleExecute(w http.ResponseWriter, r *http.Request) {
results, err := s.store.Execute(&store.ExecuteRequest{queries, timings, isTx})
if err != nil {
if err == store.ErrNotLeader {
leaderAPIAddr := s.leaderAPIAddr()
leaderProto := s.leaderAPIProto()
leaderAPIAddr := s.LeaderAPIAddr()
leaderProto := s.LeaderAPIProto()
if leaderAPIAddr == "" {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
@ -679,8 +679,8 @@ func (s *Service) handleQuery(w http.ResponseWriter, r *http.Request) {
results, err := s.store.Query(&store.QueryRequest{queries, timings, isTx, lvl, frsh})
if err != nil {
if err == store.ErrNotLeader {
leaderAPIAddr := s.leaderAPIAddr()
leaderProto := s.leaderAPIProto()
leaderAPIAddr := s.LeaderAPIAddr()
leaderProto := s.LeaderAPIProto()
if leaderAPIAddr == "" {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
@ -765,7 +765,8 @@ func (s *Service) CheckRequestPerm(r *http.Request, perm string) bool {
return s.credentialStore.HasAnyPerm(username, perm, PermAll)
}
func (s *Service) leaderAPIAddr() string {
// LeaderAPIAddr returns the API address of the leader, as known by this node.
func (s *Service) LeaderAPIAddr() string {
id, err := s.store.LeaderID()
if err != nil {
return ""
@ -773,7 +774,8 @@ func (s *Service) leaderAPIAddr() string {
return s.store.Metadata(id, "api_addr")
}
func (s *Service) leaderAPIProto() string {
// LeaderAPIProto returns the protocol used by the leader, as known by this node.
func (s *Service) LeaderAPIProto() string {
id, err := s.store.LeaderID()
if err != nil {
return "http"
@ -783,7 +785,7 @@ func (s *Service) leaderAPIProto() string {
if p == "" {
return "http"
}
return "https"
return p
}
// addBuildVersion adds the build version to the HTTP response.

@ -443,6 +443,43 @@ func Test_RegisterStatus(t *testing.T) {
}
}
func Test_LeaderAPIAddrProto(t *testing.T) {
m := &MockStore{}
s := New("127.0.0.1:0", m, nil)
m.metadata = map[string]string{
"api_addr": "1.2.3.4:999",
"api_proto": "http",
}
if addr := s.LeaderAPIAddr(); addr != "1.2.3.4:999" {
t.Fatalf("incorrect Leader API addresss, got %s", addr)
}
if proto := s.LeaderAPIProto(); proto != "http" {
t.Fatalf("incorrect Leader API proto, got %s", proto)
}
m.metadata = map[string]string{
"api_addr": "1.2.3.4:999",
}
if addr := s.LeaderAPIAddr(); addr != "1.2.3.4:999" {
t.Fatalf("incorrect Leader API addresss, got %s", addr)
}
if proto := s.LeaderAPIProto(); proto != "http" {
t.Fatalf("incorrect Leader API proto, got %s", proto)
}
m.metadata = map[string]string{
"api_addr": "1.2.3.4:999",
"api_proto": "https",
}
if addr := s.LeaderAPIAddr(); addr != "1.2.3.4:999" {
t.Fatalf("incorrect Leader API addresss, got %s", addr)
}
if proto := s.LeaderAPIProto(); proto != "https" {
t.Fatalf("incorrect Leader API proto, got %s", proto)
}
}
func Test_FormRedirect(t *testing.T) {
m := &MockStore{}
s := New("127.0.0.1:0", m, nil)
@ -485,6 +522,8 @@ func Test_FormRedirectHTTPS(t *testing.T) {
type MockStore struct {
executeFn func(queries []string, tx bool) ([]*sql.Result, error)
queryFn func(queries []string, tx, leader, verify bool) ([]*sql.Rows, error)
leaderID string
metadata map[string]string
}
func (m *MockStore) Execute(er *store.ExecuteRequest) ([]*sql.Result, error) {
@ -514,11 +553,15 @@ func (m *MockStore) Remove(id string) error {
}
func (m *MockStore) LeaderID() (string, error) {
return "", nil
return m.leaderID, nil
}
func (m *MockStore) Metadata(id, key string) string {
return ""
// If the preset leaderID is not used in the call, return nothing.
if id != m.leaderID {
return ""
}
return m.metadata[key]
}
func (m *MockStore) Stats() (map[string]interface{}, error) {

@ -55,6 +55,9 @@ class Node(object):
return self.api_adv
return self.api_addr
def APIProtoAddr(self):
return "http://%s" % self.APIAddr()
def scramble_network(self):
if self.api_adv == self.api_addr:
self.api_adv = None
@ -201,7 +204,7 @@ class Node(object):
def redirect_addr(self):
r = requests.post(self._execute_url(), data=json.dumps(['nonsense']), allow_redirects=False)
if r.status_code == 301:
return urlparse(r.headers['Location']).netloc
return "%s://%s" % (urlparse(r.headers['Location']).scheme, urlparse(r.headers['Location']).netloc)
def _status_url(self):
return 'http://' + self.APIAddr() + '/status'
@ -347,12 +350,12 @@ class TestEndToEnd(unittest.TestCase):
fs = self.cluster.followers()
self.assertEqual(len(fs), 2)
for n in fs:
self.assertEqual(l.APIAddr(), n.redirect_addr())
self.assertEqual(l.APIProtoAddr(), n.redirect_addr())
l.stop()
n = self.cluster.wait_for_leader(node_exc=l)
for f in self.cluster.followers():
self.assertEqual(n.APIAddr(), f.redirect_addr())
self.assertEqual(n.APIProtoAddr(), f.redirect_addr())
class TestEndToEndAdvAddr(TestEndToEnd):
def setUp(self):

Loading…
Cancel
Save