[Python3] Webdav connectie werkt niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • +1 Henk 'm!

  • mjpeters
  • Registratie: Augustus 2010
  • Laatst online: 05-09 20:28
Allereerst zal ik alvast melden dat ik deze vraag ook in het TransIP Stack Storage topic heb gezet, maar omdat het ook gerelateerd is aan Python programmeren dacht ik hem ook maar hier neer te zetten:

Heeft er iemand ervaring met het maken van een verbinding naar een webdav storage (in dit geval specifiek van TransIP Stack Storage)?

Ik heb één of twee posts hier op tweakers gevonden wat betreft het maken van een verbinding, maar tot nog toe heeft niks echt gewerkt. Bij deze even een lijst linkjes die ik al heb geprobeerd te gebruiken:
  1. Post op tweakers over Python en easywebdav package: https://gathering.tweakers.net/forum/list_message/46628599#46628599
  2. Github repo specifiek voor de TransIP API: https://github.com/Paradoxis/TransIP-STACK-API
  3. Andere github repo, lijkt op tweakers post: https://github.com/hslatman/python-snippets/blob/master/transip-stack-webdav.py
  4. Ander Python package waar ik tot nog toe geen succes mee heb gehad: https://pypi.python.org/pypi/webdavclient/1.0.8
En als laatste mijn eigen post in het stack topic: https://gathering.tweakers.net/forum/list_message/53575569#53575569

Mijn beste ervaring tot nog toe is met puntje 1 en 3, maar ik loop tegen 302 foutcode aan in de get request. Ik heb webdav van Stack wel gewoon werkend op Windows door de storage als netwerkschijf te koppelen, dus er is geen issue aan de server kant.

Ik ben van origine geen professioneel Python programmeur, maar ik probeer mezelf wat nieuwe dingen te leren door te experimenteren, dus vergeef me als ik niet alle ins en outs ken. ;)

Het uiteindelijke doel van dit geexperimenteer is dat ik mijn stack storage als centrale data opslag wil gebruiken voor data analyse (bijv. persoonlijke financieen/Google fit data, etc.).

Is er iemand die me hiermee kan helpen? Alvast dank!

Acties:
  • +1 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Een HTTP/302 is geen foutcode maar een redirect. Vermoedelijk heb je dus de verkeerde URL te pakken, maar daar kom je pas achter als je de redirect daadwerkelijk volgt.

Wat gebeurt er als je met je browser op https://redsandro.stackstorage.com/remote.php/webdav inlogt? De kans is aanwezig dat dat evengoed een redirect oplevert. Vervolgens kan je die nieuwe URL in je Python-tooltje hangen.

Het alternatief is om je library zo te configureren dat 'ie redirects volgt. Maar hoe je dat doet zul je toch echt zelf even in de relevante documentatie op moeten zoeken :-)

[ Voor 18% gewijzigd door ValHallASW op 18-12-2017 21:16 ]


Acties:
  • +1 Henk 'm!

  • mjpeters
  • Registratie: Augustus 2010
  • Laatst online: 05-09 20:28
Hi ValHallASW! De url en alle credentials lijken goed te zijn (ik heb ze al een aantal keer geprobeerd). De URL die ik gaf was een voorbeeld van een oude post van een andere Tweaker, maar dit is de werkelijke call die ik doe (credentials e.d. even verwijderd):

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import easywebdav
>>> webdav = easywebdav.connect(host='****.stackstorage.com', path='/remote.php/webdav', port=443, protocol='https', verify_ssl=True, username='****', password='****')
>>> webdav.ls()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\M63C984\PortableApps\WinPython\python-3.6.2.amd64\lib\site-packages\easywebdav\client.py", line 176, in ls
    response = self._send('PROPFIND', remote_path, (207, 301), headers=headers)
  File "C:\Users\M63C984\PortableApps\WinPython\python-3.6.2.amd64\lib\site-packages\easywebdav\client.py", line 100, in _send
    raise OperationFailed(method, path, expected_code, response.status_code)
easywebdav.client.OperationFailed: Failed to list directory ".".
  Operation     :  PROPFIND .
  Expected code :  207 Multi-Status, 301 Moved Permanently
  Actual code   :  302 Found


Ik heb hiervoor nog met de requests library een random chuck norris grap opgehaald, om te kijken of er proxy settings fout zijn in mijn geval, maar ook dat is geen probleem.

Als ik naar dezelfde webdav URL navigeer in Google Chrome krijg ik gewoon netjes een alert om credentials in te voeren en krijg ik daarna een "OK" terug. Dus ik snap niet echt waar ik de mist in ga... :?

Acties:
  • +2 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Tsja, dan zal je toch moeten debuggen.

- Je kunt proberen easywebdav aan te passen zodat 'ie ook 302 redirects snapt (apart dat 'ie 301's wel snapt). Zie https://github.com/amnong...easywebdav/client.py#L179.
- Je kunt proberen _send meer informatie te laten uitprinten (https://github.com/amnong.../easywebdav/client.py#L98) en daarmee te kijken waar de redirect heen gaat
- Ik vermoed nog steeds dat je ook in Chrome een redirect krijgt. Kijk even in de network-tab van je developer console, of kijk gewoon of je URL verandert ;-)

Acties:
  • +1 Henk 'm!

  • mjpeters
  • Registratie: Augustus 2010
  • Laatst online: 05-09 20:28
Nou ik heb je raad onbewust opgevolgd (had hetzelfde al gedaan zonder je post te hebben gezien), maar ik heb het eindelijk werkend! Redenem waarom het niet werkte of niet leek te werken waren de volgende:

- Stom genoeg moet ik bij de path de eerste slash weglaten ondanks dat ik dat in andere scripts wel voorbij zag komen. Daardoor kreeg ik een redirect, omdat de url die naar de requests library werd doorgestuurd al slash bevatte.
- Verder testte ik de connectiestring telkens met de ls() methode zonder een directory op te geven, maar de default is '.', terwijl STACK dit niet ziet als een geldige directory. Daardoor kreeg ik een 404 foutcode, terwijl ik in werkelijkheid gewoon een andere directory had op moeten geven of een lege string.

Dank voor de hulp!! _/-\o_

Acties:
  • +2 Henk 'm!

  • mjpeters
  • Registratie: Augustus 2010
  • Laatst online: 05-09 20:28
En als laatste reactie nog, mijn versie van een backupscript voor de TransIP STACK Storage. Het script werkt in de commandline en kan lokale directories en bestanden uploaden naar STACK met behoud van de originele directories op basis van een target directory. Klein gemis is dat ik het nog niet heb getest met een enkel bestand en het slaat directories over die geen inhoud hebben.

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/python

import getopt
import sys
import os
import easywebdav as ew
import urllib.parse

def main(argv):
    username = ''
    password = ''
    inputfiles = ''
    outputfiles = ''
    usage = 'main.py -u <username> -p <password> -i <input> -o <output>'
    try:
        opts, args = getopt.getopt(argv, "h:u:p:i:o:", ["user=", "password=", "input=", "output="])
    except getopt.GetoptError:
        print(usage)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(usage)
            sys.exit()
        elif opt in ("-u", "--users"):
            username = arg
        elif opt in ("-p", "--password"):
            password = arg
        elif opt in ("-i", "--input"):
            inputfiles = arg
        elif opt in ("-o", "--output"):
            outputfiles = arg
    return username, password, inputfiles, outputfiles


def list_local_objects(location):
    files = []
    try:
        if os.path.isfile(location):
            files.append(location)
        elif os.path.isdir(location):
            for root, dirnames, filenames in os.walk(location):
                for f in filenames:
                    files.append(os.path.join(root, f))
    except FileNotFoundError:
        print("Input directory or file was not found: ", location)
        sys.exit(2)
    return [f.replace('\\','/') for f in files]


def webdav_connect(u, pw):
    try:
        webdav = ew.connect(
            host=u + '.stackstorage.com',
            path='remote.php/webdav',
            username=u,
            password=pw,
            protocol='https',
            port=443,
            verify_ssl=True
        )
        webdav.exists('')
        return webdav
    except Exception as e:
        print('Webdav connection could not be created!')
        print(u + '.stackstorage.com', 'remote.php/webdav', u, pw, 'https', 443, True)
        print(e)
        sys.exit(2)


def files_to_dirs(files):
    return list(set(['/'.join(str(f).split('/')[:-1]) for f in files]))


if __name__ == "__main__":
    username, password, inputfiles, outputfiles = main(sys.argv[1:])
    try:
        # Collect files that exist in webdav location
        wd = webdav_connect(username, password)
        # remote_files = [urllib.parse.unquote(obj.name.strip('/')) for obj in wd.ls(outputfiles)]

        # Collect Local Files to upload
        local_files = list_local_objects(inputfiles)

        # Create dirs based on local
        # Strip root from local files
        print("\n------------------------\nCreating new directories\n------------------------\n")
        dirs = [d.replace(inputfiles, '').strip('/') for d in files_to_dirs(local_files)]
        no_of_new_dirs = 0
        for d in dirs:
            new_dir = outputfiles + "/" + d
            print("Creating directory: " + new_dir)
            if not wd.exists(new_dir):
                wd.mkdirs(new_dir)
                no_of_new_dirs += 1

        # Uploading to destination files
        print("Start uploading")
        files = [(f, f.replace(inputfiles, '').strip('/')) for f in local_files]
        no_of_files = 0
        no_of_mbs = 0
        no_of_fails = 0
        for f in files:
            u_file = f[0]
            u_file_size = os.stat(u_file).st_size / 10 ** 6
            d_file = outputfiles + "/" + f[1]
            print("Uploading file: " + u_file + ", Destination file: " + d_file + ", Filesize: " + str(round(u_file_size)) + "MB")
            try:
                wd.upload(u_file, d_file)
            except Exception as e:
                print("Failed: " + u_file)
                no_of_fails += 1
                continue
            no_of_files += 1
            no_of_mbs += u_file_size

        # Final report
        print("\n------------------\nUpload completed!!\n------------------\n")
        print("Number of directories created: " + str(no_of_new_dirs))
        print("Number of files uploaded: " + str(no_of_files))
        print("Number of files failed: " + str(no_of_fails))
        print("MB's uploaded: " + str(round(no_of_mbs)))
    except Exception as e:
        print("Something went wrong, oops!")
        print(e)
        sys.exit(2)
    print("Program executed succesfully")
    sys.exit(0)


Doe ermee wat je wilt! ;)
Pagina: 1