def testGet(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.downloadFinished) handler = mockedwebserver.SequentialHandler() handler.add('GET', '/test.html', 200, {'Content-type': 'text/html'}, '<html></html>\n') with mockedwebserver.install_http_handler(handler): err = request.get( QNetworkRequest( QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/test.html')), True) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.NoError) self.assertEqual(request.errorMessage(), '') reply = request.reply() self.assertEqual(reply.error(), QNetworkReply.NoError) self.assertEqual(reply.content(), '<html></html>\n') self.assertEqual( reply.rawHeaderList(), [b'Server', b'Date', b'Content-type', b'Content-Length']) self.assertEqual(reply.rawHeader(b'Content-type'), 'text/html') self.assertEqual(reply.rawHeader(b'xxxxxxxxx'), '') self.assertEqual( reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), 200) self.assertEqual( reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute), 'OK') self.assertEqual( reply.attribute(QNetworkRequest.RedirectionTargetAttribute), None)
def fetch_and_apply_style(layer: QgsMapLayer, url: str, style_attr: str = '') -> Optional[str]: """ Fetches a QML style from the specified URL, and applies it to a layer. @param layer: target layer to apply style to @param url: URL for QML content @param style_attr: optional str specifying name of existing field in layer to automatically update classified references to @return: Returns a str if an error occurred, or None if the fetch and apply was successful """ request = QgsBlockingNetworkRequest() if request.get(QNetworkRequest( QUrl(url))) != QgsBlockingNetworkRequest.NoError: return 'Error while fetching QML style: {}'.format( request.errorMessage()) reply = request.reply().content() tmp_file = QTemporaryFile('{}/XXXXXX.qml'.format(QDir.tempPath())) tmp_file.open() tmp_file_name = tmp_file.fileName() tmp_file.close() with open(tmp_file_name, 'wt', encoding='utf8') as f: f.write(reply.data().decode()) layer.loadNamedStyle(tmp_file_name) if style_attr: StyleUtils.update_class_attribute(layer, style_attr) layer.triggerRepaint() return None
def fetchResults(self, search, context, feedback): self.dbg_info("start GMF locator search...") url = self.service.url if not url: self.emit_bad_configuration() return if len(search) < 2: return params = { 'query': search, 'limit': str(self.service.total_limit), 'partitionlimit': str(self.service.category_limit) } url = self.url_with_param(url, params) self.dbg_info(url.url()) _request = QNetworkRequest(url) _request.setRawHeader(b'User-Agent', self.USER_AGENT) request = QgsBlockingNetworkRequest() if self.service.authid: request.setAuthCfg(self.service.authid) response = request.get(_request, False, feedback) if response == QgsBlockingNetworkRequest.NoError: self.handle_response(request.reply().content()) else: error_msg = request.reply().errorString() self.emit_bad_configuration(error_msg) self.info(error_msg, Qgis.Critical) self.finished.emit()
def testGet(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.downloadFinished) err = request.get( QNetworkRequest( QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/qgis_local_server/index.html'))) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.NoError) self.assertEqual(request.errorMessage(), '') reply = request.reply() self.assertEqual(reply.error(), QNetworkReply.NoError) self.assertEqual( reply.content(), '<!DOCTYPE html>\n<html lang="en">\n<head>\n\t<meta charset="utf-8" />\n\t<title>Local QGIS Server Default Index</title>\n</head>\n<body>\n <h2 style="font-family:Arial;">Web Server Working<h2/>\n</body>\n</html>\n' ) self.assertEqual(reply.rawHeaderList(), [ b'Server', b'Date', b'Content-type', b'Content-Length', b'Last-Modified' ]) self.assertEqual(reply.rawHeader(b'Content-type'), 'text/html') self.assertEqual(reply.rawHeader(b'xxxxxxxxx'), '') self.assertEqual( reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), 200) self.assertEqual( reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute), 'OK') self.assertEqual( reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), 200) self.assertEqual( reply.attribute(QNetworkRequest.RedirectionTargetAttribute), None)
def testFetchEmptyUrl(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.downloadFinished) err = request.get(QNetworkRequest(QUrl())) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.ServerExceptionError) self.assertEqual(request.errorMessage(), 'Protocol "" is unknown') reply = request.reply() self.assertFalse(reply.content())
def testFetchBadUrl(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.downloadFinished) err = request.get(QNetworkRequest(QUrl('http://x'))) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.ServerExceptionError) self.assertEqual(request.errorMessage(), 'Host x not found') reply = request.reply() self.assertFalse(reply.content())
def testDelete(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.finished) handler = mockedwebserver.SequentialHandler() handler.add('DELETE', '/test.html', 200) with mockedwebserver.install_http_handler(handler): err = request.deleteResource(QNetworkRequest(QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/test.html'))) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.NoError) self.assertEqual(request.errorMessage(), '')
def testFetchBadUrl2(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.downloadFinished) err = request.get(QNetworkRequest(QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/ffff'))) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.ServerExceptionError) self.assertIn('File not found', request.errorMessage()) reply = request.reply() self.assertEqual(reply.error(), QNetworkReply.ContentNotFoundError) self.assertFalse(reply.content())
def testHead(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.finished) handler = mockedwebserver.SequentialHandler() handler.add('HEAD', '/test.html', 200, {'Content-type': 'text/html'}) with mockedwebserver.install_http_handler(handler): err = request.head(QNetworkRequest(QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/test.html')), True) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.NoError) self.assertEqual(request.errorMessage(), '')
def fetch_raw( url: str, encoding: str = ENCODING, authcfg_id: str = "", params: Optional[Dict[str, str]] = None, ) -> Tuple[bytes, str]: """ Fetch resource from the internet. Similar to requests.get(url) but is recommended way of handling requests in QGIS plugin :param url: address of the web resource :param encoding: Encoding which will be used to decode the bytes :param authcfg_id: authcfg id from QGIS settings, defaults to '' :param params: Dictionary to send in the query string :return: bytes of the content and default name of the file or empty string """ if params: url += "?" + urlencode(params) LOGGER.debug(url) req = QNetworkRequest(QUrl(url)) # http://osgeo-org.1560.x6.nabble.com/QGIS-Developer-Do-we-have-a-User-Agent-string-for-QGIS-td5360740.html user_agent = QSettings().value("/qgis/networkAndProxy/userAgent", "Mozilla/5.0") user_agent += " " if len(user_agent) else "" # noinspection PyUnresolvedReferences user_agent += f"QGIS/{Qgis.QGIS_VERSION_INT}" user_agent += f" {plugin_name()}" # https://www.riverbankcomputing.com/pipermail/pyqt/2016-May/037514.html req.setRawHeader(b"User-Agent", bytes(user_agent, encoding)) request_blocking = QgsBlockingNetworkRequest() if authcfg_id: request_blocking.setAuthCfg(authcfg_id) _ = request_blocking.get(req) reply: QgsNetworkReplyContent = request_blocking.reply() reply_error = reply.error() if reply_error != QNetworkReply.NoError: # Error content will be empty in older QGIS versions: # https://github.com/qgis/QGIS/issues/42442 message = (bytes(reply.content()).decode("utf-8") if len( bytes(reply.content())) else None) # bar_msg will just show a generic Qt error string. raise QgsPluginNetworkException( message=message, error=reply_error, bar_msg=bar_msg(reply.errorString()), ) # https://stackoverflow.com/a/39103880/10068922 default_name = "" if reply.hasRawHeader(CONTENT_DISPOSITION_BYTE_HEADER): header: QByteArray = reply.rawHeader(CONTENT_DISPOSITION_BYTE_HEADER) default_name = bytes(header).decode(encoding).split("filename=")[1] if default_name[0] in ['"', "'"]: default_name = default_name[1:-1] return bytes(reply.content()), default_name
def testPost(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.finished) handler = mockedwebserver.SequentialHandler() handler.add('POST', '/test.html', 200, expected_body=b"foo") with mockedwebserver.install_http_handler(handler): req = QNetworkRequest(QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/test.html')) req.setHeader(QNetworkRequest.ContentTypeHeader, 'text/plain') err = request.post(req, b"foo") self.assertEqual(err, QgsBlockingNetworkRequest.NoError) self.assertEqual(request.errorMessage(), '')
def testFetchBadUrl2(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.downloadFinished) handler = mockedwebserver.SequentialHandler() handler.add('GET', '/ffff', 404) with mockedwebserver.install_http_handler(handler): err = request.get(QNetworkRequest(QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/ffff'))) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.ServerExceptionError) self.assertIn('Not Found', request.errorMessage()) reply = request.reply() self.assertEqual(reply.error(), QNetworkReply.ContentNotFoundError) self.assertFalse(reply.content())
def testFetchBadUrl2(self): request = QgsBlockingNetworkRequest() spy = QSignalSpy(request.finished) handler = mockedwebserver.SequentialHandler() handler.add('GET', '/ffff', 404, {}, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n <head>\n <meta http-equiv="Content-Type" content="text/html;charset=utf-8">\n <title>Error response</title>\n </head>\n <body>\n <h1>Error response</h1>\n <p>Error code: 404</p>\n <p>Message: File not found.</p>\n <p>Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.</p>\n </body>\n</html>\n') with mockedwebserver.install_http_handler(handler): err = request.get(QNetworkRequest(QUrl('http://localhost:' + str(TestQgsBlockingNetworkRequest.port) + '/ffff'))) self.assertEqual(len(spy), 1) self.assertEqual(err, QgsBlockingNetworkRequest.ServerExceptionError) self.assertIn('Not Found', request.errorMessage()) reply = request.reply() self.assertEqual(reply.error(), QNetworkReply.ContentNotFoundError) self.assertEqual(reply.content(), '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n <head>\n <meta http-equiv="Content-Type" content="text/html;charset=utf-8">\n <title>Error response</title>\n </head>\n <body>\n <h1>Error response</h1>\n <p>Error code: 404</p>\n <p>Message: File not found.</p>\n <p>Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.</p>\n </body>\n</html>\n')
def _get_json_results(path, feedback): req = QgsBlockingNetworkRequest() req_status = req.get( QNetworkRequest(QUrl(urljoin(_TAXREF_API_BASE_URL, path)))) if req_status != QgsBlockingNetworkRequest.NoError: for error_name in ('NetworkError', 'TimeoutError', 'ServerExceptionError'): if req_status == getattr(QgsBlockingNetworkRequest, error_name): feedback.reportError('{}: {}'.format(error_name, req.errorMessage())) break return None content = bytes(req.reply().content()) if not content: feedback.reportError('Error while downloading data from {}.'.format( urljoin(_TAXREF_API_BASE_URL, path))) return None return json.loads(content)['_embedded']
def get_reply(url): qgs_request = QgsBlockingNetworkRequest() request = QNetworkRequest(QUrl(url)) request.setRawHeader(b"User-Agent", b"qgis-pdokservices-plugin") err = qgs_request.get(request, True) if err is QgsBlockingNetworkRequest.NoError: # TODO: add proper error handling QgsMessageLog.logMessage("SERVER ERROR OCCURED", PLUGIN_NAME, level=Qgis.Info) reply = qgs_request.reply() if reply.error() is QNetworkReply.NoError: # TODO: add proper error handling QgsMessageLog.logMessage("SERVER ERROR OCCURED", PLUGIN_NAME, level=Qgis.Info) return reply
def fetchResults(self, search, context, feedback): if len(search) < 2: return # see https://operations.osmfoundation.org/policies/nominatim/ # "Auto-complete search This is not yet supported by Nominatim and you must not implement such a service on the client side using the API." # so end with a space to trigger a search: if search[-1] != ' ': return url = '{}{}'.format(self.SEARCH_URL, search) self.info('Search url {}'.format(url)) try: # see https://operations.osmfoundation.org/policies/nominatim/ # "Pro4 vide a valid HTTP Referer or User-Agent identifying the application (QGIS geocoder)" # TODO #headers = {b'User-Agent': self.USER_AGENT} # nam = Network Access Manager nam = QgsBlockingNetworkRequest() request = QNetworkRequest(QUrl(url)) request.setHeader(QNetworkRequest.UserAgentHeader, self.USER_AGENT) nam.get(request, forceRefresh=True) reply = nam.reply() if reply.attribute( QNetworkRequest.HttpStatusCodeAttribute ) == 200: # other codes are handled by NetworkAccessManager content_string = reply.content().data().decode('utf8') locations = json.loads(content_string) for loc in locations: result = QgsLocatorResult() result.filter = self result.displayString = '{} ({})'.format( loc['display_name'], loc['type']) # use the json full item as userData, so all info is in it: result.userData = loc self.resultFetched.emit(result) except Exception as err: # Handle exception.. # only this one seems to work self.info(err)
def SearchPTH(queryString, language): request = QNetworkRequest() request.setUrl(QUrl("https://paikkatietojentuottajat-koekaytto.maanmittauslaitos.fi/api/public/v1/search?X-CLIENT-LANG=FI")) request.setHeader(request.ContentTypeHeader, "application/json") jsonByteArray = QJsonDocument(createJson(queryString, language)).toJson() blockingNetworkRequest = QgsBlockingNetworkRequest() err = blockingNetworkRequest.post(request, jsonByteArray, True) if not err: response = blockingNetworkRequest.reply().content() dict_str = response.data().decode("utf-8") if dict_str: resp_json = json.loads(dict_str) return resp_json.get("hits") else: #No result returned LOG("Nothing returned") pass else: LOG(blockingNetworkRequest.errorMessage())
def downloadCapabilities(self, wmsUrl): """Download a remote capabilities file.""" # we get the WMS 1.1.1 XML because OWSLib actually works with it capabilitiesUrl = f"{wmsUrl}?request=GetCapabilities&version=1.1.1" request = QNetworkRequest(QUrl(capabilitiesUrl)) # suppress errors from SSL for the capabilities request (NTG network is dodgy) sslConfig = request.sslConfiguration() sslConfig.setPeerVerifyMode(QSslSocket.VerifyNone) request.setSslConfiguration(sslConfig) # use a blocking request here blockingRequest = QgsBlockingNetworkRequest() result = blockingRequest.get(request) if result == QgsBlockingNetworkRequest.NoError: reply = blockingRequest.reply() if reply.error() == QNetworkReply.NoError: xml = bytes(reply.content()).decode() self.capabilitiesDownloaded.emit(xml) else: connectionError(reply.errorString()) else: connectionError(blockingRequest.errorMessage())