0

I am kind of new in python, trying to develop an user interaction with an API.

In this API I have to authenticate first and then with a token received I can do multiple things,

I have a module authfile.py that returns a cookie which is in a variable

url = "https://172.16.1.77:8089/api"

headers = {
    'Content-Type': 'application/json;charset=UTF-8',
    'Connection': 'close',
}

def auth(self, url, headers):
        
        data = '{"request": {"action":"challenge","user":"apiuser","version":"1.0"}}'

        # First send the challenge.

        response = requests.post(url, headers=headers, data=data, verify=False)

        # Get the challenge into variable.

        a = response.json()
        b = a['response']
        c = b['challenge']

        print("This is the challenge number: " + c)

        # Getting the challenge with the Password with MD5
        e = input("Please enter the Password\n")
        user = c+e
        h = hashlib.md5(user.encode())
        md = h.hexdigest()
        print("This is the Token: " + md)

        datas = '{"request":{"action":"login", "token":"' + str(md) + '", "url":"' + str(url) + '" , "user": "cdrapi"}}'

        #Send the token to get the Cookie

        response2 = requests.post(url, headers=headers, data=datas, verify=False)

        #Getting the cookie into a variable
        global cookie
        f = response2.json()
        g = f['response']
        cookie = g['cookie']

        print("This is the Cookie: " +cookie)

        return cookie

cookie = auth(url, headers)

So I have another file that I use to apply some changes, it will need to be in a different module since the applychanges() functions will be called many times

applychanes.py:

from authfile import url, headers, cookie
import requests

def changes():
    while True:
            q = (input("Are you sure you would like to apply changes?\nPlease enter only Y for Yes and N for No\n").lower())
            if q.lower() not in ("y", "n"):
                print("This is not a valid entry")
            if q == "y":
                postta = '{"request":{"action":"applyChanges", "cookie":"' + str(cookie) + '"}}'
                format_to_json = requests.post(url, headers=headers, data=postta, verify=False)
                jsonresponse = format_to_json.json()
                                        # Get the response in a variable
                presponse = jsonresponse['response']
                                        # Get the status code into a variable
                codestatus = jsonresponse['status']
                                        # Print the reponse
                print(presponse)
                print(codestatus)
                print("The changes has been applied")
                break
                    
            if q == "n":
                print("NO changes has been made")
                break
            else:
                continue
    return q

When I call the Cookie, the auth file is excecuted again changing the Cookie and the changes will not be applied since the new cookie means a new session**

How do I call a variable preventing to run the function?

On the Main program the auth MUST be excecuted before anything else.

2e0byo
  • 5,305
  • 1
  • 6
  • 26
  • [`if __name__ == "__main__":`](https://stackoverflow.com/q/419163/10824407) ? – Olvin Roght Oct 11 '21 at 21:26
  • Hi Olvin, I have been tryng to get this but I am unsure where to put it or how it should be structurated the code, WOuld you give me a hint? – F3RN4ND Oct 15 '21 at 15:14

1 Answers1

0

when I call the cookie, the authfile is executed again

If I read you right here, you mean than when you do import authfile or from authfile import cookie, authfile gets evaluated again, and the cookie changes.

This is impossible, unless you are using reload (or a reload-like trick, like del sys.modules["authfile"]. Python will only ever evaluate an imported module once: after that it just binds a new name to it.* Thus if your debugging is premised on the idea that importing the same file multiple times is causing the file to be evaluated multiple times, it's based on a misconception, and something else is going wrong.

On the other hand, I could easily be misreading you here! Do clarify if I'm wrong; I'll check back on this tomorrow [and delete this sentence either way].

In any case, this is probably an instance of a bigger problem: modules are not really for state: that's more what classes are for. Modules just insulate namespaces, but that can have problems if you rely on module-level variables to hold state. So if you really do have a problem with state changing stored in a module, either make a class, to be the 'single source of truth' with respect to this state:

class Authentication:
    def __init__(self, url, headers):
        # put your auth code here
        self._cookie = ...

    @property
    def cookie(self):
        return self._cookie

With appropriate methods to refresh the cookie when needed, or possibly with a dict of cookies if you have multiple realms.

If you don't want to do that and you still think something else is modifying your cookie, replace all instances of cookie with a get_cookie() function defined as:

_cookie = auth(url, headers)
def get_cookie():
    return _cookie

That will throw an error when somebody tries to write to your cookie.

Note that all this assumes that cookie is an immuteable type. A possible cause of your problem is cookie being e.g. a dict or list, and something else modifying that---which will modify the original object.

Lastly, if your problem is simply that you want to define cookie in authfile but only generate it later, wrap it in a function or method on a class (personally I would do this---classes are for state, modules for namespace), and call the method later. Something like:

class Authentication:
    def __init__(self, url, headers):
        self._url = url
        self._headers = headers

    @staticmethod
    def authenticate(url, headers):
        # your auth fn

    @property
    def cookie(self):
        if not self._cookie:
            self._cookie = self.authenticate(self._url, self._headers)
        return self._cookie

auth = Authentication(url, headers)

This will generate the cookie the first time it's accessed. So import as:

from authfile import auth
...
with auth.cookie as cookie:
   ...

*Alright, I don't actually know what happens in the case of circular imports, whether Python 'evaluates' the same file multiple times before bailing. But it bails, so the question is moot.

2e0byo
  • 5,305
  • 1
  • 6
  • 26
  • I really have to thank you for all your effort answering this, I will try this tomorrow also haha, however I wanted to clear for a better understanding: The cookie is not mutable, Once I get it, I hold this on a variable, use it as I wish and in case the cookie is not valid anymore, it will throw an error which I will be handling later. – F3RN4ND Oct 13 '21 at 01:27