2009-08-15 3 views
1

J'ai une classe qui hérite de httplib.HTTPSConnection.Gestion des connexions SSL et non SSL lors de l'héritage de httplib.HTTP (s) Connexion

class MyConnection(httplib.HTTPSConnection): 
    def __init__(self, *args, **kw): 
    httplib.HTTPSConnection.__init__(self,*args, **kw) 
    ... 

Est-il possible de désactiver la couche SSL lorsque la classe est instantiatied donc je peux aussi l'utiliser pour communiquer avec les serveurs non sécurisés?

Je mon cas, il est connu avant l'initialisation si SSL doit être utilisé si une autre solution serait d'essayer de changer l'héritage de httplib.HTTPSConnection-httplib.HTTPConnection, mais je suis pas sûr de savoir comment faire ceci d'une manière sensible?

Répondre

1

Selon mon commentaire sur la réponse de @ Mark, j'aime l'approche d'usine qu'il préconise. Cependant, je ne le ferais pas exactement comme il le veut, parce qu'il refait une nouvelle classe à chaque fois. , Cela est plutôt un beau cas d'utilisation pour mixin MI et super, comme suit:

class MyConnectionPlugin(object): 
    def __init__(self, *args, **kw): 
    super(MyConnectionPlugin, self).__init__(*args, **kw) 
    # etc etc -- rest of initiatizations, other methods 

class SecureConnection(MyConnectionPlugin, 
         httplib.HTTPSConnection, object): 
    pass 

class PlainConnection(MyConnectionPlugin, 
         httplib.HTTPConnection, object): 
    pass 

def ConnectionClass(secure): 
    if secure: 
    return SecureConnection 
    else: 
    return PlainConnection 

conn = ConnectionClass(whatever_expression())() 

etc.

Maintenant, les alternatives sont possibles, comme un objet Python peut changer son propre __class__, et ainsi de suite. Cependant, comme tirer des mouches avec un fusil de rhinocéros, en utilisant une force excessive (extrêmement puissant, profond, et des fonctions linguistiques quasi-magiques) pour résoudre des problèmes qui peuvent être résolus avec une retenue raisonnable (l'équivalent d'un flyswatter), n'est PAS recommandé;).

Modifier: l'injection supplémentaire de object dans les bases est nécessaire que pour compenser le fait que triste en Python 2. * la classe HTTPConnection est ancienne et ne joue donc pas bien avec les autres - témoin ...:

>>> import httplib 
>>> class Z(object): pass 
... 
>>> class Y(Z, httplib.HTTPConnection): pass 
... 
>>> Y.mro() 
[<class '__main__.Y'>, <class '__main__.Z'>, <type 'object'>, <class httplib.HTTPConnection at 0x264ae0>] 
>>> class X(Z, httplib.HTTPConnection, object): pass 
... 
>>> X.mro() 
[<class '__main__.X'>, <class '__main__.Z'>, <class httplib.HTTPConnection at 0x264ae0>, <type 'object'>] 
>>> 

l'ordre méthode résolution (alias MRO) dans la classe Y (sans injection supplémentaire d'une base object) a objet avant la classe de httplib (si super ne fait pas la bonne chose), mais l'injection supplémentaire perturbe le MRO pour compenser. Hélas, un tel soin est nécessaire dans Python 2. * lorsqu'il s'agit de mauvaises vieilles classes de style hérité; heureusement, en Python 3, le style hérité a disparu et chaque classe "joue bien avec les autres" comme il se doit! -)

+0

Merci. Encore quelque chose que je ne connaissais pas "super". Cela m'évite d'indenter tout mon fichier pour l'inclure dans le code de l'usine. Utilisera ceci. – pkit

+1

@pkit, toujours heureux de vous aider! «super» doit toujours être utilisé avec précaution, mais pour ce cas inhabituel de mixins nécessitant des «initiés» spécialisés, c'est vraiment un bon choix. –

+0

Lorsque j'utilise ceci, il semble que la connexion HTTP (S) .__ init__ ne soit pas appelée. Se pourrait-il que je manque quelque chose dans cette configuration de classe? – pkit

2

par votre dernier paragraphe, en Python, vous pouvez utiliser quelque chose comme un modèle d'usine:

class Foo: 
    def doit(self): 
     print "I'm a foo" 
class Bar: 
    def doit(self): 
     print "I'm a bar" 

def MakeClass(isSecure): 
    if isSecure: 
     base = Foo 
    else: 
     base = Bar 

    class Quux(base): 
     def __init__(self): 
      print "I am derived from", base 

    return Quux() 

MakeClass(True).doit() 
MakeClass(False).doit() 

sorties:

I am derived from __main__.Foo 
I'm a foo 
I am derived from __main__.Bar 
I'm a bar 
+0

Merci pour cette idée. Je me demande encore si c'est le seul moyen de gérer les deux cas lors de l'héritage de HTTPSConnection? – pkit

+1

@pkit, une approche d'usine n'est pas la seule façon - c'est juste de loin la meilleure façon - simple, propre, direct, sans faille. Je ne le ferais pas exactement comme Mark l'a fait, en détail (cela génère beaucoup de classes séparées mais identiques) mais je suis toujours +1 pour des raisons générales. –

+0

@Alex, merci pour votre réponse. En regardant le code httplib, il semble que seule la méthode connect est ré-implémentée. Monkey corrigeant l'instance HTTPSConnection avec HTTPConnection.connecter la méthode a un sens? Ou est-ce simplement laid? – pkit

0

, vous voulez Apparemment utiliser MyConnection pour de multiples connexions ultérieures à différents hôtes . Si c'est le cas, vous ne devriez pas du tout hériter de la connexion HTTP (S) - cette classe n'est pas vraiment destinée à être utilisée pour plusieurs connexions. Au lieu de cela, faites simplement MyConnection avoir une connexion HTTP (S).

+0

Dans mon cas, je l'utilise réellement pour une connexion à un hôte. C'est pourquoi je sais avant l'instatiation si cela devrait être avec SLL ou wihtout. – pkit

Questions connexes