Projet

Général

Profil

Development #38865

opengis: traiter (ou pas) les contenus XML

Ajouté par Nicolas Roche il y a plus de 4 ans. Mis à jour il y a plus de 2 ans.

Statut:
Rejeté
Priorité:
Normal
Assigné à:
Version cible:
-
Début:
09 janvier 2020
Echéance:
% réalisé:

0%

Temps estimé:
Patch proposed:
Oui
Planning:
Non

Description

Le serveur OpenData de Toulouse (https://data.toulouse-metropole.fr/) retourne des contenus XML,
or le connecteur opengis s'attend à recevoir du JSON.

cf https://docs.geoserver.org/latest/en/user/services/wfs/outputformats.html

smihai‎: le outputformat=json est bien envoyé?

oui : https://data.toulouse-metropole.fr/api/wfs?version=1.1.0&OUTPUTFORMAT=json&CQL_FILTER=DWITHIN%28the_geom%2CPoint%281.412+43.596%29%2C5%2Cmeters%29&SERVICE=WFS&REQUEST=GetFeature&TYPENAME=ods%3Apoints_apport_volontaire_dmt&VERSION=1.0.0

cf https://help.opendatasoft.com/apis/wfs/#getfeature
(aucune mention du paramètre outputformat)

smihai‎: alors p'tet une couille dans OpenDataSoft


Fichiers


Demandes liées

Lié à Passerelle - Bug #38851: opengis: adapter le paramètre typeNames à la version du serveurFermé08 janvier 2020

Actions
Lié à Passerelle - Development #41224: opengis: json n'est pas un format standardFermé01 avril 2020

Actions

Historique

#1

Mis à jour par Nicolas Roche il y a plus de 4 ans

  • Lié à Bug #38851: opengis: adapter le paramètre typeNames à la version du serveur ajouté
#2

Mis à jour par Frédéric Péters il y a plus de 4 ans

https://data.toulouse-metropole.fr/api/wfs?version=1.1.0&request=GetCapabilities&service=WFS

On y note <wfs:OutputFormats><wfs:Format>text/xml; subtype=gml/3.1.1</wfs:Format></wfs:OutputFormats> l'absence de sortie possible en json.

À comparer, https://download.data.grandlyon.com/wfs/grandlyon?request=GetCapabilities&service=WFS.

<ows:AllowedValues>
  <ows:Value>application/gml+xml; version=3.2</ows:Value>
  <ows:Value>text/xml; subtype=gml/3.2.1</ows:Value>
  <ows:Value>text/xml; subtype=gml/3.1.1</ows:Value>
  <ows:Value>text/xml; subtype=gml/2.1.2</ows:Value>
  <ows:Value>application/shapefile</ows:Value>
  <ows:Value>application/json; subtype=geojson</ows:Value>
</ows:AllowedValues>

Et je dirais donc qu'ici comme pour TYPENAMES, il faut interroger le serveur en fonction de ce qu'il peut faire. Et que le rôle du connecteur est de fournir un comportement identique peu importe ce qu'on trouve derrière. Et donc transformer ce FeatureCollection XML en FeatureCollection geojson.

Pour un exemple de format : https://download.data.grandlyon.com/wfs/grandlyon?SERVICE=WFS&VERSION=2.0.0&outputformat=GEOJSON&request=GetFeature&typename=ter_territoire.maison_de_la_metropole&SRSNAME=urn:ogc:def:crs:EPSG::4326

#3

Mis à jour par Nicolas Roche il y a environ 4 ans

En copiant la configuration de toulouse, https://passerelle-moncompte.cutm-ea-dev-publik.nfrance.com/opengis/opendata-tm/
ce patch semble fonctionner sur cet appel : /opengis/opendata-tm/reverse?lat=45.79689&lon=4.78414

{"lat": "1.474023", "lon": "43.564278", "err": 0, "address": {"city": "TOULOUSE"}}

(je veux bien plus de billes pour aller plus loin)

A noter : j'ai modifié les tests des connecteurs grenoble_gru et vivaticket à cause des problèmes d'encodage sur la réponse que l'on obtient avec la requête testée ci-dessus.

#4

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

Nicolas Roche a écrit :

En copiant la configuration de toulouse, https://passerelle-moncompte.cutm-ea-dev-publik.nfrance.com/opengis/opendata-tm/
ce patch semble fonctionner sur cet appel : /opengis/opendata-tm/reverse?lat=45.79689&lon=4.78414
[...]
(je veux bien plus de billes pour aller plus loin)

A noter : j'ai modifié les tests des connecteurs grenoble_gru et vivaticket à cause des problèmes d'encodage sur la réponse que l'on obtient avec la requête testée ci-dessus.

Si tu veux émuler FakedResponse au plus près tu dois respecter son API, .content doit être un str/bytes (force_bytes) et .text un unicode/str (force_text). Je pense que l'API devrait ressembler à ça :

def __init__(self, text=None, content=None):
    if content is not None:
        self.content = content
    elif text is not None:
        self.content = force_bytes(text)

@property
def text(self):
    return force_text(self.content)

Ça devrait éviter d'avoir à changer grenoble gru et vivaticket.

#5

Mis à jour par Nicolas Roche il y a environ 4 ans

Si tu veux émuler FakedResponse au plus près ...

Nickel ! Mais je pense que ça attendra #38781, et que d'ici là ce premier patch ne sera plus nécessaire.

Concernant directement ce ticket, le second patch ne fait que marcher les endpoints reverse et features.
#8

Mis à jour par Nicolas Roche il y a environ 4 ans

Le endpoint features semble en fait ne fonctionner que si l'on ne passe pas de valeur à propertyName.
J'ai l'impression que le serveur visé ne gère pas ce paramètre décrit dans
https://docs.geoserver.org/latest/en/user/services/wfs/reference.html#getfeature

Par exemple, cette requête au connecteur :
https://passerelle.dev.publik.love/opengis/aaa/features?property_name=index&type_names=gymnases
déclenche celle-ci sur le serveur openData :
https://data.toulouse-metropole.fr/api/wfs?OUTPUTFORMAT=xml&SERVICE=WFS&PROPERTYNAME=index&REQUEST=GetFeature&TYPENAME=gymnases&VERSION=1.0.0
qui répond une 400 :

<Exception exceptionCode="InvalidParameterValue" locator="PropertyName"/>

#10

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

Nicolas Roche a écrit :

Le endpoint features semble en fait ne fonctionner que si l'on ne passe pas de valeur à propertyName.
J'ai l'impression que le serveur visé ne gère pas ce paramètre décrit dans
https://docs.geoserver.org/latest/en/user/services/wfs/reference.html#getfeature

Par exemple, cette requête au connecteur :
https://passerelle.dev.publik.love/opengis/aaa/features?property_name=index&type_names=gymnases
déclenche celle-ci sur le serveur openData :
https://data.toulouse-metropole.fr/api/wfs?OUTPUTFORMAT=xml&SERVICE=WFS&PROPERTYNAME=index&REQUEST=GetFeature&TYPENAME=gymnases&VERSION=1.0.0
qui répond une 400 :
[...]

Deux choses qui me choquent :
  • dans la doc les noms des attributs semble sensible à la casse (en tout cas ils capitalisent bizarrement) mais c'est peut-être pas le cas
  • ils utilisent version=2.0.0 (ceci explique cela certainement)

Dans la norme 1.0.0 ça semble existe, chercher PROPERTYNAME= dans http://portal.opengeospatial.org/files/?artifact_id=7176 sur https://www.opengeospatial.org/standards/wfs .

#11

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

Je remarque que c'est la valeur de PROPERTYNAME qui l'embête aussi, pas la clé. Donc c'est juste pas index qu'il faut demander.

#12

Mis à jour par Nicolas Roche il y a environ 4 ans

les noms des attributs semble sensible à la casse

dans l'ensemble ça à l'air de fonctionner avec les majuscules, comme le montre le test du endpoint reverse si dessus.

ils utilisent version=2.0.0 (ceci explique cela certainement)

non, c'est tout l'objet du ticket (plutôt #38848 en fait) : faire fonctionner le connecteur opengis sur leur opendata (https://data.toulouse-metropole.fr) qui tourne WFS en 1.1.0 alors que le connecteur a été développé sur leur geoserver (https://geows.extranet.toulouse-metropole.fr/geoserver/gisements/ows?service=WFS&request=GetCapabilities&service=WFS) qui tourne WFS en 2.0.0

(merci pour la doc, qui dit :)

The <PropertyName> element is used to enumerate the feature properties that should be
selected during a query and whose values should be included in the response to a
GetFeature request. A client application can determine the properties of a feature by
making a DescribeFeatureType request before composing a GetFeature request. The
DescribeFeatureType operation [sec. 8] will generate a GML application schema
defining the schema of the feature type.

cf https://data.toulouse-metropole.fr/api/wfs?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=points_apport_volontaire_dmt

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema ...>
  <xsd:import .../>
  <xsd:element substitutionGroup="gml:_Feature" type="ods:points_apport_volontaire_dmt_Type" name="points_apport_volontaire_dmt"/>
  <xsd:complexType name="points_apport_volontaire_dmt_Type">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" nillable="true" type="xsd:string" name="adresse" minOccurs="0"/>
          <xsd:element maxOccurs="1" nillable="true" type="xsd:string" name="commune" minOccurs="0"/>
...
          <xsd:element maxOccurs="1" nillable="true" type="xsd:string" name="zone" minOccurs="0"/>
          <xsd:element maxOccurs="1" nillable="true" type="xsd:string" name="num_prest" minOccurs="0"/>
          <xsd:element maxOccurs="1" nillable="true" type="gml:GeometryPropertyType" name="geo_shape" minOccurs="0"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
</xsd:schema>

The client can then select the properties to be
fetched.
...

cf https://data.toulouse-metropole.fr/api/wfs?SERVICE=WFS&REQUEST=GetFeature&TYPENAME=points_apport_volontaire_dmt&PROPERTYNAME=commune

<Exception exceptionCode="InvalidParameterValue" locator="PropertyName"/>

If no <PropertyName> elements are specified, then all feature properties should be
fetched.

cf https://data.toulouse-metropole.fr/api/wfs?SERVICE=WFS&REQUEST=GetFeature&TYPENAME=points_apport_volontaire_dmt
...

  <gml:featureMember>
    <ods:points_apport_volontaire_dmt gml:id="points_apport_volontaire_dmt.3757c88a87f28488c314717a52331451b96fe021">
      <ods:geo_shape>
        <gml:Point srsName="urn:x-ogc:def:crs:EPSG:4326">
          <gml:pos>43.6247999998 1.47496000344</gml:pos>
        </gml:Point>
      </ods:geo_shape>
      <ods:commune>TOULOUSE</ods:commune>
      <ods:centre_ville>N</ods:centre_ville>
      <ods:zone>B</ods:zone>
      <ods:flux>TX</ods:flux>
      <ods:prestataire>LE RELAIS</ods:prestataire>
      <ods:adresse>64 ROUTE D'AGDE</ods:adresse>
      <ods:code_com>31555</ods:code_com>
      <ods:longitude>1.47496</ods:longitude>
      <ods:geo_point_2d>
        <gml:Point srsName="urn:x-ogc:def:crs:EPSG:4326">
          <gml:pos>43.6247999998 1.47496000344</gml:pos>
        </gml:Point>
      </ods:geo_point_2d>
      <ods:volume>0.0</ods:volume>
      <ods:marque>CONTENEUR</ods:marque>
      <ods:a_e>A</ods:a_e>
      <ods:code_tm>TLSTX5056</ods:code_tm>
      <ods:mes>20041101</ods:mes>
      <ods:latitude>43.6248</ods:latitude>
      <ods:num_prest>05.63.98.96.28</ods:num_prest>
      <ods:modele>PUBLIC</ods:modele>
    </ods:points_apport_volontaire_dmt>
  </gml:featureMember>
  ...

Il me manque un cas d'usage pour avancer.
Peut-être que l'on pourrait pousser en l'état et dans un premier temps laisser Cyril continuer à tester (#38848) ?

#13

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

J'ai compris la syntaxe :

https://data.toulouse-metropole.fr/api/wfs?SERVICE=WFS&REQUEST=GetFeature&PROPERTYNAME=points_apport_volontaire_dmt/commune&TYPENAME=points_apport_volontaire_dmt

(en lisant la page 67 du doc pointé plus haut, il faut donc mettre le nom du type séparé par un slash du nom de l'attribut, ensuite séparé la liste d'attributs par des virgules).

#14

Mis à jour par Nicolas Roche il y a environ 4 ans

Donc cette requête fonctionne bien : https://passerelle.dev.publik.love/opengis/aaa/features?property_name=gymnases/index&type_names=gymnases
Merci Benjamin !!

Maintenant si je veux aller au bout (intégrer tous les paramètres du endpoint dans la requête), j'ai un dernier problème avec le paramètre q :
https://passerelle.dev.publik.love/opengis/aaa/features?cql_filter=commune=%27TOULOUSE%27&filter_property_name=index&case-insensitive=true&property_name=gymnases/index&type_names=gymnases
=>
https://data.toulouse-metropole.fr/api/wfs?version=1.1.0&OUTPUTFORMAT=xml&CQL_FILTER=commune%3D%27TOULOUSE%27&SERVICE=WFS&PROPERTYNAME=gymnases%2Findex&REQUEST=GetFeature&TYPENAME=gymnases&VERSION=1.0.0
(ok)

https://passerelle.dev.publik.love/opengis/aaa/features?cql_filter=commune=%27TOULOUSE%27&filter_property_name=index&case-insensitive=true&property_name=gymnases/index&type_names=gymnases&q=eau
=>
https://data.toulouse-metropole.fr/api/wfs?version=1.1.0&OUTPUTFORMAT=xml&CQL_FILTER=commune%3D%27TOULOUSE%27+AND+index+ILIKE+%27%25eau%25%27&SERVICE=WFS&PROPERTYNAME=gymnases%2Findex&REQUEST=GetFeature&TYPENAME=gymnases&VERSION=1.0.0
403 Forbidden (à priori de la part de nginx)

Rq : s/AND/AAND/ + s/index/inddex/ et ça passe
https://data.toulouse-metropole.fr/api/wfs?version=1.1.0&OUTPUTFORMAT=xml&CQL_FILTER=commune%3D%27TOULOUSE%27+AAND+inddex+ILIKE+%27%25eau%25%27&SERVICE=WFS&PROPERTYNAME=gymnases%2Findex&REQUEST=GetFeature&TYPENAME=gymnases&VERSION=1.0.0

Un problème de filtrage côté nginx ?

#15

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

Là je pense qu'il faut prendre contact avec Toulouse Strasbourg pour comprendre, expose ton problème sur le ticket #38848.

#16

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

À finir si on dispose d'un service WFS en version 1.0 qui accepte le paramètre CQL_FILTER (on aurait ça à Strabourg?), ou alors on pousse comme cela en sachant que le support du CQL_FILTER n'est pas testé et on verra le jour où on en aura besoin.

#17

Mis à jour par Nicolas Roche il y a environ 4 ans

Non, je n'ai pas l'impression qu'il y ait un service WFS à Strasbourg : http://adict.strasbourg.eu/mapproxy/demo/

#18

Mis à jour par Valentin Deniaud il y a environ 4 ans

#20

Mis à jour par Thomas Noël il y a presque 4 ans

  • Assigné à mis à Nicolas Roche
#21

Mis à jour par Nicolas Roche il y a plus de 2 ans

  • Statut changé de Solution proposée à Rejeté

Je rejette.
Si un jour on veut parser du contenu XML (service WFS en version 1.0) sans gérer le paramètre CQL_FILTER,
alors on ré-ouvrira.

Formats disponibles : Atom PDF