Hi Alessandro,
as you guessed, WFS, as the official protocol, provides no support for on-the-fly geometry simpification.
GeoServer has no WFS vendor extension for it either. There is a lot of simplification support in the WMS machinery, either doing it on the fly, or leveraging pre-generalized sidecar tables (see the pregeneralized datastore plugin), but in general, those try to get as much simplification as possible, as quickly as possible, to the expense of topological correctness.
If you need something today, you can use WPS, there is a process to simplify geometries on the fly retaining topological validity. The simplification is performed on the cartesian space, so the distance must be specified in the unit of measure of the input (which can be weird for geographic data).
Get a GeoSever with a demo dataset, and POST this XML request to “http://localhost:8080/geoserver/wps”:
<?xml version="1.0" encoding="UTF-8"?><wps:Execute version="1.0.0" service="WPS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.opengis.net/wps/1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wcs="http://www.opengis.net/wcs/1.1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd">
<ows:Identifier>gs:Simplify</ows:Identifier>
<wps:DataInputs>
<wps:Input>
<ows:Identifier>features</ows:Identifier>
<wps:Reference mimeType="text/xml" xlink:href="http://geoserver/wfs?service=WFS&version=1.0.0&typeNames=topp:states" method="GET"/>
</wps:Input>
<wps:Input>
<ows:Identifier>distance</ows:Identifier>
<wps:Data>
<wps:LiteralData>0.1</wps:LiteralData>
</wps:Data>
</wps:Input>
<wps:Input>
<ows:Identifier>preserveTopology</ows:Identifier>
<wps:Data>
<wps:LiteralData>true</wps:LiteralData>
</wps:Data>
</wps:Input>
</wps:DataInputs>
<wps:ResponseForm>
<wps:RawDataOutput mimeType="text/xml; subtype=wfs-collection/1.0">
<ows:Identifier>result</ows:Identifier>
</wps:RawDataOutput>
</wps:ResponseForm>
</wps:Execute>
and you’ll get something like:
<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:feature="http://www.openplans.org/topp" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc">
<gml:boundedBy>
<gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:coord>
<gml:X>-124.73142200000001</gml:X>
<gml:Y>24.955967</gml:Y>
</gml:coord>
<gml:coord>
<gml:X>-66.969849</gml:X>
<gml:Y>49.371735</gml:Y>
</gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<feature:states fid="states.1">
<gml:boundedBy>
<gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:coord>
<gml:X>-91.449188</gml:X>
<gml:Y>36.988113</gml:Y>
</gml:coord>
<gml:coord>
<gml:X>-87.508316</gml:X>
<gml:Y>42.50936100000001</gml:Y>
</gml:coord>
</gml:Box>
</gml:boundedBy>
<feature:the_geom>
<gml:MultiPolygon srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:polygonMember>
<gml:Polygon>
<gml:outerBoundaryIs>
<gml:LinearRing>
<gml:coordinates>-88.071564,37.51099000000001 -88.467644,37.400757 -88.476799,37.072143999999994 -88.993172,37.22003599999999 -89.12986,36.988113 -89.38295,37.049212999999995 -89.521523,37.694798000000006 -90.364769,38.23429899999999 -90.113121,38.830467 -90.413071,38.96233000000001 -90.627213,38.880795000000006 -90.738083,39.24780999999999 -91.449188,39.86304899999999 -91.411118,40.572970999999995 -90.960709,40.950503999999995 -91.055786,41.40137899999999 -90.348366,41.586849 -90.154518,41.93077500000001 -90.176086,42.12050199999999 -90.638329,42.50936100000001 -87.79731,42.48913200000001 -87.529861,41.723591 -87.540215,39.350525000000005 -87.670326,39.146679000000006 -87.508316,38.73663300000001 -87.986008,38.234814 -88.15937,37.660686 -88.071564,37.51099000000001</gml:coordinates>
</gml:LinearRing>
</gml:outerBoundaryIs>
</gml:Polygon>
</gml:polygonMember>
</gml:MultiPolygon>
</feature:the_geom>
<feature:STATE_NAME>Illinois</feature:STATE_NAME>
<feature:STATE_FIPS>17</feature:STATE_FIPS>
<feature:SUB_REGION>E N Cen</feature:SUB_REGION>
<feature:STATE_ABBR>IL</feature:STATE_ABBR>
<feature:LAND_KM>143986.61</feature:LAND_KM>
<feature:WATER_KM>1993.335</feature:WATER_KM>
<feature:PERSONS>1.1430602E7</feature:PERSONS>
<feature:FAMILIES>2924880.0</feature:FAMILIES>
<feature:HOUSHOLD>4202240.0</feature:HOUSHOLD>
<feature:MALE>5552233.0</feature:MALE>
<feature:FEMALE>5878369.0</feature:FEMALE>
<feature:WORKERS>4199206.0</feature:WORKERS>
<feature:DRVALONE>3741715.0</feature:DRVALONE>
<feature:CARPOOL>652603.0</feature:CARPOOL>
<feature:PUBTRANS>538071.0</feature:PUBTRANS>
<feature:EMPLOYED>5417967.0</feature:EMPLOYED>
<feature:UNEMPLOY>385040.0</feature:UNEMPLOY>
<feature:SERVICE>1360159.0</feature:SERVICE>
<feature:MANUAL>828906.0</feature:MANUAL>
<feature:P_MALE>0.486</feature:P_MALE>
<feature:P_FEMALE>0.514</feature:P_FEMALE>
<feature:SAMP_POP>1747776.0</feature:SAMP_POP>
</feature:states>
</gml:featureMember>
...
which is a lot less coordinates than the original topp:states dataset.
If you really want to have it in WFS instead, I would not be opposed to see an extension for on the fly simplification, but you’ll have to provide the development resources/funds to make it happen, see here for a guide on how that is done:
Hope this helps
Andrea