terrasync.py: add support for the HTTPS protocol
- Instantiate an HTTPSConnection object when the URL scheme is 'https'. - Clarify and simplify the initialization of HTTPSocketRequest and HTTPDownloadRequest: + clarify initialization of their 'callback' attribute (it's the method of the same name; make it clear that the base class constructor, namely HTTPGetCallback.__init__(), doesn't modify the 'callback' attribute when an object of class HTTPSocketRequest or HTTPDownloadRequest is initialized); + HTTPDownloadRequest doesn't need access to the TerraSync object -> remove the corresponding instance attribute and constructor argument. - Don't use super() when initializing HTTPDownloadRequest objects (see [1]). [1] https://fuhm.net/super-harmful/
This commit is contained in:
parent
62cdd30810
commit
e342a0f41e
2 changed files with 24 additions and 13 deletions
|
@ -65,6 +65,10 @@ class NetworkError(TerraSyncPyException):
|
||||||
"""Exception raised when getting a network error even after retrying."""
|
"""Exception raised when getting a network error even after retrying."""
|
||||||
ExceptionShortDescription = "Network error"
|
ExceptionShortDescription = "Network error"
|
||||||
|
|
||||||
|
class UnsupportedURLScheme(TerraSyncPyException):
|
||||||
|
"""Exception raised when asked to handle an unsupported URL scheme."""
|
||||||
|
ExceptionShortDescription = "Unsupported URL scheme"
|
||||||
|
|
||||||
class RepoDataError(TerraSyncPyException):
|
class RepoDataError(TerraSyncPyException):
|
||||||
"""
|
"""
|
||||||
Exception raised when getting invalid data from the TerraSync repository."""
|
Exception raised when getting invalid data from the TerraSync repository."""
|
||||||
|
|
|
@ -25,18 +25,19 @@ import hashlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from urllib.parse import urlparse, urljoin
|
from urllib.parse import urlparse, urljoin
|
||||||
from http.client import HTTPConnection, _CS_IDLE, HTTPException
|
from http.client import HTTPConnection, HTTPSConnection, HTTPException
|
||||||
from os import listdir
|
from os import listdir
|
||||||
from os.path import isfile, isdir, join
|
from os.path import isfile, isdir, join
|
||||||
|
|
||||||
from . import dirindex
|
from . import dirindex
|
||||||
from .exceptions import UserError, NetworkError, RepoDataError, \
|
from .exceptions import UserError, NetworkError, RepoDataError, \
|
||||||
InvalidDirIndexFile
|
InvalidDirIndexFile, UnsupportedURLScheme
|
||||||
from .virtual_path import VirtualPath
|
from .virtual_path import VirtualPath
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,6 +121,7 @@ class HTTPGetCallback:
|
||||||
by HTTPGetter.get().
|
by HTTPGetter.get().
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if callback is not None:
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.src = src
|
self.src = src
|
||||||
|
|
||||||
|
@ -130,7 +132,16 @@ class HTTPGetter:
|
||||||
self.maxPending = maxPending
|
self.maxPending = maxPending
|
||||||
self.requests = []
|
self.requests = []
|
||||||
self.pendingRequests = []
|
self.pendingRequests = []
|
||||||
|
|
||||||
|
if self.parsedBaseUrl.scheme == "http":
|
||||||
self.httpConnection = HTTPConnection(self.parsedBaseUrl.netloc)
|
self.httpConnection = HTTPConnection(self.parsedBaseUrl.netloc)
|
||||||
|
elif self.parsedBaseUrl.scheme == "https":
|
||||||
|
context = ssl.create_default_context()
|
||||||
|
self.httpConnection = HTTPSConnection(self.parsedBaseUrl.netloc,
|
||||||
|
context=context)
|
||||||
|
else:
|
||||||
|
raise UnsupportedURLScheme(self.parsedBaseUrl.scheme)
|
||||||
|
|
||||||
self.httpRequestHeaders = headers = {'Host':self.parsedBaseUrl.netloc,'Content-Length':0,'Connection':'Keep-Alive','User-Agent':'FlightGear terrasync.py'}
|
self.httpRequestHeaders = headers = {'Host':self.parsedBaseUrl.netloc,'Content-Length':0,'Connection':'Keep-Alive','User-Agent':'FlightGear terrasync.py'}
|
||||||
|
|
||||||
def assemblePath(self, httpGetCallback):
|
def assemblePath(self, httpGetCallback):
|
||||||
|
@ -151,7 +162,6 @@ class HTTPGetter:
|
||||||
return urljoin(baseUrl + '/', httpGetCallback.src.asRelative())
|
return urljoin(baseUrl + '/', httpGetCallback.src.asRelative())
|
||||||
|
|
||||||
def doGet(self, httpGetCallback):
|
def doGet(self, httpGetCallback):
|
||||||
conn = self.httpConnection
|
|
||||||
pathOnServer = self.assemblePath(httpGetCallback)
|
pathOnServer = self.assemblePath(httpGetCallback)
|
||||||
self.httpConnection.request("GET", pathOnServer, None,
|
self.httpConnection.request("GET", pathOnServer, None,
|
||||||
self.httpRequestHeaders)
|
self.httpRequestHeaders)
|
||||||
|
@ -183,10 +193,9 @@ class HTTPGetter:
|
||||||
|
|
||||||
|
|
||||||
class HTTPDownloadRequest(HTTPGetCallback):
|
class HTTPDownloadRequest(HTTPGetCallback):
|
||||||
def __init__(self, terrasync, src, dst, callback = None ):
|
def __init__(self, src, dst, callback=None):
|
||||||
"""Initialize an HTTPDownloadRequest instance.
|
"""Initialize an HTTPDownloadRequest instance.
|
||||||
|
|
||||||
terrasync -- a TerraSync instance
|
|
||||||
src -- a VirtualPath instance (corresponding to the path
|
src -- a VirtualPath instance (corresponding to the path
|
||||||
on the server for which a GET request is to be
|
on the server for which a GET request is to be
|
||||||
issued)
|
issued)
|
||||||
|
@ -199,8 +208,7 @@ class HTTPDownloadRequest(HTTPGetCallback):
|
||||||
instance. Its return value is ignored.
|
instance. Its return value is ignored.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
super().__init__(src, self.callback)
|
HTTPGetCallback.__init__(self, src, None)
|
||||||
self.terrasync = terrasync
|
|
||||||
self.dst = dst
|
self.dst = dst
|
||||||
self.mycallback = callback
|
self.mycallback = callback
|
||||||
|
|
||||||
|
@ -241,7 +249,7 @@ class HTTPSocketRequest(HTTPGetCallback):
|
||||||
(presumably a file)
|
(presumably a file)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
HTTPGetCallback.__init__(self, src, self.callback)
|
HTTPGetCallback.__init__(self, src, None)
|
||||||
|
|
||||||
def callback(self, url, httpResponse):
|
def callback(self, url, httpResponse):
|
||||||
# Same comment as for HTTPDownloadRequest.callback()
|
# Same comment as for HTTPDownloadRequest.callback()
|
||||||
|
@ -511,7 +519,7 @@ class TerraSync:
|
||||||
removeDirectoryTree(self.target, localFullPath)
|
removeDirectoryTree(self.target, localFullPath)
|
||||||
|
|
||||||
print("Downloading '{}'".format(virtualPath))
|
print("Downloading '{}'".format(virtualPath))
|
||||||
request = HTTPDownloadRequest(self, virtualPath, localFullPath)
|
request = HTTPDownloadRequest(virtualPath, localFullPath)
|
||||||
self.httpGetter.get(request)
|
self.httpGetter.get(request)
|
||||||
else:
|
else:
|
||||||
self.abortCheckMode(failedCheckReason, virtualPath)
|
self.abortCheckMode(failedCheckReason, virtualPath)
|
||||||
|
@ -548,8 +556,7 @@ class TerraSync:
|
||||||
if not os.path.exists(localFullPath):
|
if not os.path.exists(localFullPath):
|
||||||
os.makedirs(localFullPath)
|
os.makedirs(localFullPath)
|
||||||
|
|
||||||
request = HTTPDownloadRequest(self,
|
request = HTTPDownloadRequest(virtualPath / ".dirindex",
|
||||||
virtualPath / ".dirindex",
|
|
||||||
localDirIndex,
|
localDirIndex,
|
||||||
self.handleDirindexRequest)
|
self.handleDirindexRequest)
|
||||||
self.httpGetter.get(request)
|
self.httpGetter.get(request)
|
||||||
|
|
Loading…
Reference in a new issue