def request(self, url, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None, blocking=True): """ Make a network request by calling QgsNetworkAccessManager. redirections argument is ignored and is here only for httplib2 compatibility. """ self.http_call_result.url = url self.msg_log(u'http_call request: {0}'.format(url)) self.blocking_mode = blocking req = QNetworkRequest() # Avoid double quoting form QUrl url = urllib.parse.unquote(url) req.setUrl(QUrl(url)) if headers is not None: # This fixes a weird error with compressed content not being correctly # inflated. # If you set the header on the QNetworkRequest you are basically telling # QNetworkAccessManager "I know what I'm doing, please don't do any content # encoding processing". # See: https://bugs.webkit.org/show_bug.cgi?id=63696#c1 try: del headers['Accept-Encoding'] except KeyError: pass for k, v in list(headers.items()): self.msg_log("Setting header %s to %s" % (k, v)) req.setRawHeader(k, v) if self.authid: self.msg_log("Update request w/ authid: {0}".format(self.authid)) QgsAuthManager.instance().updateNetworkRequest(req, self.authid) if self.reply is not None and self.reply.isRunning(): self.reply.close() if method.lower() == 'delete': func = getattr(QgsNetworkAccessManager.instance(), 'deleteResource') else: func = getattr(QgsNetworkAccessManager.instance(), method.lower()) # Calling the server ... # Let's log the whole call for debugging purposes: self.msg_log("Sending %s request to %s" % (method.upper(), req.url().toString())) self.on_abort = False headers = {str(h): str(req.rawHeader(h)) for h in req.rawHeaderList()} for k, v in list(headers.items()): self.msg_log("%s: %s" % (k, v)) if method.lower() in ['post', 'put']: if isinstance(body, file): body = body.read() self.reply = func(req, body) else: self.reply = func(req) if self.authid: self.msg_log("Update reply w/ authid: {0}".format(self.authid)) QgsAuthManager.instance().updateNetworkReply( self.reply, self.authid) # necessary to trap local timeout manage by QgsNetworkAccessManager # calling QgsNetworkAccessManager::abortRequest QgsNetworkAccessManager.instance().requestTimedOut.connect( self.requestTimedOut) self.reply.sslErrors.connect(self.sslErrors) self.reply.finished.connect(self.replyFinished) self.reply.downloadProgress.connect(self.downloadProgress) # block if blocking mode otherwise return immediately # it's up to the caller to manage listeners in case of no blocking mode if not self.blocking_mode: return None, None # Call and block self.el = QEventLoop() self.reply.finished.connect(self.el.quit) # Catch all exceptions (and clean up requests) try: self.el.exec_(QEventLoop.ExcludeUserInputEvents) except Exception as e: raise e if self.reply: self.reply.finished.disconnect(self.el.quit) # emit exception in case of error if not self.http_call_result.ok: if self.http_call_result.exception and not self.exception_class: raise self.http_call_result.exception elif self.exception_class: raise self.exception_class(self.http_call_result.reason) else: raise RequestsException('Unknown reason') return self.http_call_result, self.http_call_result.content
def execute_request(self, url, **kwargs): """ Uses QgsNetworkAccessManager and QgsAuthManager. """ method = kwargs.get('http_method', 'get') headers = kwargs.get('headers', {}) # This fixes a weird error with compressed content not being correctly # inflated. # If you set the header on the QNetworkRequest you are basically telling # QNetworkAccessManager "I know what I'm doing, please don't do any content # encoding processing". # See: https://bugs.webkit.org/show_bug.cgi?id=63696#c1 try: del headers[b'Accept-Encoding'] except KeyError as ke: # only debugging here as after 1st remove it isn't there anymore self.util.msg_log_debug( u'unexpected error deleting request header: {}'.format(ke)) pass # Avoid double quoting form QUrl url = unquote(url) self.util.msg_log_debug(u'http_call request: {} {}'.format( method, url)) class Response: status_code = 200 status_message = 'OK' text = '' ok = True headers = {} reason = '' exception = None def iter_content(self, _): return [self.text] self.http_call_result = Response() url = self.util.remove_newline(url) req = QNetworkRequest() req.setUrl(QUrl(url)) req.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) for k, v in headers.items(): self.util.msg_log_debug("%s: %s" % (k, v)) try: req.setRawHeader(k, v) except: self.util.msg_log_error( u'FAILED to set header: {} => {}'.format(k, v)) self.util.msg_log_last_exception() if self.settings.authcfg: self.util.msg_log_debug(u'before updateNetworkRequest') QgsApplication.authManager().updateNetworkRequest( req, self.settings.authcfg) self.util.msg_log_debug(u'before updateNetworkRequest') if self.reply is not None and self.reply.isRunning(): self.reply.close() self.util.msg_log_debug(u'getting QgsNetworkAccessManager.instance()') #func = getattr(QgsNetworkAccessManager.instance(), method) #func = QgsNetworkAccessManager().get(req) #manager = QNetworkAccessManager() #event = QEventLoop() #response = manager.get(QNetworkRequest(QUrl(url))) #response.downloadProgress.connect(self.download_progress) #response.finished.connect(event.quit) #event.exec() #response_msg = response.readAll() ##response_msg = str(response_msg) #response_msg = str(response_msg, encoding='utf-8') ##response_msg = response_msg.decode('utf-8') #response.deleteLater() #self.util.msg_log_debug(u'response message:\n{} ...'.format(response_msg[:255])) #self.http_call_result.text = response_msg # in Python3 all strings are unicode, so QString is not defined #return self.http_call_result # Calling the server ... self.util.msg_log_debug('before self.reply = func(req)') #self.reply = func(req) #self.reply = QgsNetworkAccessManager.instance().get(req) method_call = getattr(QgsNetworkAccessManager.instance(), method) self.reply = method_call(req) #self.reply.setReadBufferSize(1024*1024*1024) #self.reply.setReadBufferSize(1024 * 1024 * 1024 * 1024) self.reply.setReadBufferSize(0) self.util.msg_log_debug('after self.reply = func(req)') # Let's log the whole call for debugging purposes: if self.settings.debug: self.util.msg_log_debug("\nSending %s request to %s" % (method.upper(), req.url().toString())) headers = { str(h): str(req.rawHeader(h)) for h in req.rawHeaderList() } for k, v in headers.items(): try: self.util.msg_log_debug("%s: %s" % (k, v)) except: self.util.msg_log_debug('error logging headers') if self.settings.authcfg: self.util.msg_log_debug("update reply w/ authcfg: {0}".format( self.settings.authcfg)) QgsApplication.authManager().updateNetworkReply( self.reply, self.settings.authcfg) self.util.msg_log_debug('before connecting to events') # connect downloadProgress event try: self.reply.downloadProgress.connect(self.download_progress) #pass except: self.util.msg_log_error( 'error connecting "downloadProgress" event') self.util.msg_log_last_exception() # connect reply finished event try: self.reply.finished.connect(self.reply_finished) #pass except: self.util.msg_log_error( 'error connecting reply "finished" progress event') self.util.msg_log_last_exception() self.util.msg_log_debug('after connecting to events') # Call and block self.event_loop = QEventLoop() try: self.reply.finished.connect(self.event_loop.quit) except: self.util.msg_log_error( 'error connecting reply "finished" progress event to event loop quit' ) self.util.msg_log_last_exception() self.mb_downloaded = 0 # Catch all exceptions (and clean up requests) self.event_loop.exec() # Let's log the whole response for debugging purposes: if self.settings.debug: self.util.msg_log_debug( u'\nGot response [{}/{}] ({} bytes) from:\n{}\nexception:{}'. format(self.http_call_result.status_code, self.http_call_result.status_message, len(self.http_call_result.text), self.reply.url().toString(), self.http_call_result.exception)) headers = { str(h): str(self.reply.rawHeader(h)) for h in self.reply.rawHeaderList() } for k, v in headers.items(): self.util.msg_log_debug("%s: %s" % (k, v)) self.util.msg_log_debug("Payload :\n%s ......" % self.http_call_result.text[:255]) self.reply.close() self.util.msg_log_debug("Deleting reply ...") try: self.reply.deleteLater() except: self.util.msg_log_error('unexpected error deleting QNetworkReply') self.util.msg_log_last_exception() self.reply = None if self.http_call_result.exception is not None: self.util.msg_log_error('http_call_result.exception is not None') self.http_call_result.ok = False # raise self.http_call_result.exception return self.http_call_result