def loadModel(self): imd = None try: loader = ModelLoader(self.ui.mDataLineEdit.text()) models = loader.detect_models() model_names = map(lambda m: m.name, models) self._log_output("Looking up models: " + ', '.join(model_names)) ili = loader.gen_lookup_ili() qDebug(ili) wpsreq = self._create_wps_request(ili) url = self.ui.mIlisMetaUrlLineEdit.text() req = QNetworkRequest(QUrl(url)) req.setHeader(QNetworkRequest.ContentTypeHeader, 'application/xml') data = QByteArray() data.append(wpsreq) reply = QgsNetworkAccessManager.instance().blockingPost(req, data) if reply.error() == QNetworkReply.NoError: result = reply.content() imd = self._parse_wps_response(result) except Exception as e: qDebug("Exception during IlisModel download") if imd is None: self._show_log_window() QgsApplication.messageLog().logMessage( "Couldn't download Ilismeta model", "Interlis", Qgis.MessageLevel(1)) self.ui.mModelLineEdit.setText("") else: fh, imdfn = tempfile.mkstemp(suffix='.imd') os.close(fh) with codecs.open(imdfn, "w", encoding='utf-8') as file: file.write(imd) self.ui.mModelLineEdit.setText(imdfn)
def api_authentification(self): logger.debug("\n------------------ Authentication ------------------") # creating credentials header crd_header_value = QByteArray() crd_header_value.append("Basic ") crd_header_value.append( base64.b64encode("{}:{}".format(self.app_id, self.app_secrets).encode()) ) crd_header_name = QByteArray() crd_header_name.append("Authorization") # creating Content-Type header ct_header_value = QByteArray() ct_header_value.append("application/json") # creating request token_rqst = QNetworkRequest(QUrl(self.token_url)) # setting headers token_rqst.setRawHeader(crd_header_name, crd_header_value) token_rqst.setHeader(token_rqst.ContentTypeHeader, ct_header_value) # creating data data = QByteArray() data.append(urlencode({"grant_type": "client_credentials"})) # requesting and handle reply logger.debug("Asking for token") token_reply = self.naMngr.post(token_rqst, data) token_reply.finished.connect(partial(self.api_handle_token, reply=token_reply))
def prepare_request(self, url, content_type): url = self.get_url(url) req = QNetworkRequest(QUrl(url)) req.setHeader(QNetworkRequest.ContentTypeHeader, content_type) req.setRawHeader(b'Accept', b'application/json') if self._token: req.setRawHeader(b'Authorization', self.str_to_byte_array( 'Bearer {0}'.format(self._token))) return req
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 create_request(self, request_type: str): """Creates a QNetworkRequest() with appropriate headers and URL according to the 'request_type' parameter. :param str request_type: type of request to create. Options: - 'token' - 'search' - 'details' - 'shares' :returns: the QNetworkRequest to send to the Isogeo's API :rtype: QNetworkRequest """ # creating headers (same steps wathever request_type value) header_value = QByteArray() header_name = QByteArray() header_name.append("Authorization") # for token request if request_type == "token": # filling request header with credentials header_value.append("Basic ") header_value.append( base64.b64encode("{}:{}".format(self.app_id, self.app_secret).encode())) # creating the QNetworkRequest from oAuth2 authentication URL request = QNetworkRequest(QUrl(self.api_url_token)) # creating and setting the 'Content-type header' ct_header_value = QByteArray() ct_header_value.append("application/json") request.setHeader(request.ContentTypeHeader, ct_header_value) # for other request_type, setting appropriate url else: if request_type == "shares": url = QUrl("{}/shares".format(self.api_url_base)) elif request_type == "search" or request_type == "details": url = QUrl(self.currentUrl) else: logger.debug( "Unkown request type asked : {}".format(request_type)) raise ValueError return 0 # filling request header with token header_value.append(self.token) request = QNetworkRequest(url) # creating QNetworkRequest from appropriate url request.setRawHeader(header_name, header_value) return request
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 _post_sync(self, qurl: QUrl, timeout: int = 20000, data: bytes = b'', content_type=None): ''' synchronous POST-request ''' request = QNetworkRequest(qurl) if content_type: request.setHeader(QNetworkRequest.ContentTypeHeader, content_type) # newer versions of QGIS (3.6+) support synchronous requests if hasattr(self._manager, 'blockingPost'): reply = self._manager.blockingPost(request, data, forceRefresh=True) # use blocking event loop for older versions else: loop = QEventLoop() timer = QTimer() timer.setSingleShot(True) # reply or timeout break event loop, whoever comes first timer.timeout.connect(loop.quit) reply = self._manager.post(request, data) reply.finished.connect(loop.quit) timer.start(timeout) # start blocking loop loop.exec() loop.deleteLater() if not timer.isActive(): reply.deleteLater() raise ConnectionError('Timeout') timer.stop() if reply.error(): self.error.emit(reply.errorString()) raise ConnectionError(reply.errorString()) res = Reply(reply) self.finished.emit(res) return res
def do_request(self, point: QgsPointXY) -> None: query = QUrlQuery() query.addQueryItem("lat", str(point.y())) query.addQueryItem("lon", str(point.x())) query.addQueryItem("format", "json") url = QUrl(self.URL) url.setQuery(query) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, "*****@*****.**") response = self.nam.blockingGet(request) self._status_code = response.attribute( QNetworkRequest.HttpStatusCodeAttribute) self._content = json.loads(bytes(response.content())) if self._content.get("error"): self._error_string = self._content["error"] return
def run(): def sslVerifyNone(req): conf = req.sslConfiguration() conf.setPeerVerifyMode( QSslSocket.VerifyNone ) req.setSslConfiguration( conf ) req = QNetworkRequest( url ) sslVerifyNone( req ) # Need for Windows, error 'Handshake failed' if json_request is None: reply = self.nam.get( req ) else: req.setHeader( QNetworkRequest.ContentTypeHeader, "application/json" ) data = QByteArray() data.append( json.dumps( json_request ) ) reply = self.nam.post( req, data ) if reply is None: response = { 'isOk': False, 'message': "Network error", 'errorCode': -1 } self.finished.emit( response ) return self.abortReply.connect( reply.abort ) if not self.responseAllFinished: self._connectReply( reply )
def loadModel(self): imd = None try: loader = ModelLoader(self.ui.mDataLineEdit.text()) models = loader.detect_models() model_names = map(lambda m: m.name, models) self._log_output("Looking up models: " + ', '.join(model_names)) ili = loader.gen_lookup_ili() qDebug(ili) wpsreq = self._create_wps_request(ili) url = self.ui.mIlisMetaUrlLineEdit.text() req = QNetworkRequest(QUrl(url)) req.setHeader(QNetworkRequest.ContentTypeHeader, 'application/xml') reply = QgsNetworkAccessManager.instance().post(req, wpsreq) # Wait for reply or timeout loop = QEventLoop() reply.finished.connect(loop.quit) QTimer.singleShot(15000, reply.abort) loop.exec_() if reply.isFinished() and reply.error() == QNetworkReply.NoError: result = reply.readAll() imd = self._parse_wps_response(result) except: qDebug("Exception during IlisModel download") if imd is None: self._show_log_window() QgsApplication.messageLog().logMessage( "Couldn't download Ilismeta model", "Interlis", Qgis.MessageLevel(1)) self.ui.mModelLineEdit.setText("") else: fh, imdfn = tempfile.mkstemp(suffix='.imd') os.close(fh) with codecs.open(imdfn, "w", encoding='utf-8') as file: file.write(imd) self.ui.mModelLineEdit.setText(imdfn)
def result(self, result): # See if OK was pressed if result: project = QgsProject.instance() # First get all the values of the GUI items crs_input = self.dlg.crs_input.crs() crs_out = QgsCoordinateReferenceSystem( 'EPSG:4326') # we need this to be WGS84 for Nominatim lineedit_text = self.dlg.lineedit_xy.value() # Protect the free text field for coordinates from generic user failure try: lineedit_yx = [ float(coord.strip()) for coord in lineedit_text.split(',') ] except: QMessageBox.critical( self.iface.mainWindow(), 'QuickAPI error', "Did you really specify a coordinate in comma-separated Lat/Long?\nExiting..." ) return # Create a Point and transform if necessary point = QgsPointXY(*reversed(lineedit_yx)) if crs_input.authid() != 'EPSG:4326': xform = QgsCoordinateTransform(crs_input, crs_out, project) point_transform = xform.transform(point) point = point_transform # Set up the GET Request to Nominatim query = QUrlQuery() query.addQueryItem('lat', str(point.y())) query.addQueryItem('lon', str(point.x())) query.addQueryItem('format', 'json') url = QUrl('https://nominatim.openstreetmap.org/reverse') url.setQuery(query) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, '*****@*****.**') nam = QgsNetworkAccessManager() response: QgsNetworkReplyContent = nam.blockingGet(request) # Only process if HTTP status code is 200 status_code = response.attribute( QNetworkRequest.HttpStatusCodeAttribute) if status_code == 200: # Get the content of the response and process it response_json = json.loads(bytes(response.content())) if response_json.get('error'): QMessageBox.critical( self.iface.mainWindow(), "Quick API error", "The request was not processed succesfully!\n\n" "Message:\n" "{}".format(response_json['error'])) return x = float(response_json['lon']) y = float(response_json['lat']) address = response_json['display_name'] license = response_json['licence'] # Create the output memory layer layer_out = QgsVectorLayer( "Point?crs=EPSG:4326&field=address:string&field=license:string", "Nominatim Reverse Geocoding", "memory") # Create the output feature (only one here) point_out = QgsPointXY(x, y) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPointXY(point_out)) feature.setAttributes([address, license]) # Add feature to layer and layer to map layer_out.dataProvider().addFeature(feature) layer_out.updateExtents() project.addMapLayer(layer_out) # build bbox for auto-zoom feature bbox = [float(coord) for coord in response_json['boundingbox']] min_y, max_y, min_x, max_x = bbox bbox_geom = QgsGeometry.fromRect( QgsRectangle(min_x, min_y, max_x, max_y)) # Transform bbox if map canvas has a different CRS if project.crs().authid() != 'EPSG:4326': xform = QgsCoordinateTransform(crs_out, project.crs(), project) bbox_geom.transform(xform) self.iface.mapCanvas().zoomToFeatureExtent( QgsRectangle.fromWkt(bbox_geom.asWkt()))
def request(self, url, first_request_time=None, retry_counter=0, post_json=None): """Performs HTTP GET/POST with credentials, returning the body as JSON. :param url: URL extension for request. Should begin with a slash. :type url: string :param first_request_time: The time of the first request (None if no retries have occurred). :type first_request_time: datetime.datetime :param post_json: Parameters for POST endpoints :type post_json: dict :raises valhalla.utils.exceptions.ApiError: when the API returns an error. :returns: openrouteservice response body :rtype: dict """ if not first_request_time: first_request_time = datetime.now() elapsed = datetime.now() - first_request_time if elapsed > self.retry_timeout: raise exceptions.Timeout() if retry_counter > 0: # 0.5 * (1.5 ^ i) is an increased sleep time of 1.5x per iteration, # starting at 0.5s when retry_counter=1. The first retry will occur # at 1, so subtract that first. delay_seconds = 1.5**(retry_counter - 1) # Jitter this value by 50% and pause. time.sleep(delay_seconds * (random.random() + 0.5)) # Define the request params = {'access_token': self.key} authed_url = self._generate_auth_url( url, params, ) url_object = QUrl(self.base_url + authed_url) self.url = url_object.url() body = QJsonDocument.fromJson(json.dumps(post_json).encode()) request = QNetworkRequest(url_object) request.setHeader(QNetworkRequest.ContentTypeHeader, 'application/json') logger.log( "url: {}\nParameters: {}".format( self.url, # final_requests_kwargs json.dumps(post_json, indent=2)), 0) start = time.time() response: QgsNetworkReplyContent = self.nam.blockingPost( request, body.toJson()) self.response_time = time.time() - start try: self.handle_response(response, post_json['id']) except exceptions.OverQueryLimit: # Let the instances know smth happened self.overQueryLimit.emit() return self.request(url, first_request_time, retry_counter + 1, post_json) response_content = json.loads(bytes(response.content())) # Mapbox treats 400 errors with a 200 status code if 'error' in response_content: raise exceptions.ApiError(str(response_content['status_code']), response_content['error']) return response_content