geoserversld

Geoserver WMS-Style set dynamically


I am trying to dynamically style a Geoserver-WMS using userinput on my website.

My Idea was to use a proxy-script to create the new sld, delete the layer from the map and add a new one configured with the new style parameter. This is fine so far, but it seems like I am not able to set the style/sld parameter in the request accordingly.

This is the request I am using right now:

https://forestwatch.lup-umwelt.de/app_development/proxy/index.php/geoserver/forestwatch2/wms?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=forestwatch2%3Astart_veraenderung&TILED=true&STYLE=https%3A%2F%2Fforestwatch.lup-umwelt.de%252Fnew%252FSLD%252F200100.sld&WIDTH=256&HEIGHT=256&SRS=EPSG%3A25832&STYLES=&BBOX=574247.9574719232%2C5665728.630974121%2C574920.3574218744%2C5666401.0309240725

The XML:

<StyledLayerDescriptor version="1.0.0">
    <UserLayer>
    <sld:LayerFeatureConstraints>
    <sld:FeatureTypeConstraint/>
    </sld:LayerFeatureConstraints>
    <sld:UserStyle>
    <sld:Name>Veraenderungsstart</sld:Name>
    <FeatureTypeStyle>
    <Rule>
    <RasterSymbolizer>
    <ColorMap>
        <ColorMapEntry color="#FFFFFF" quantity="180100"/>
        <ColorMapEntry color="#FF0000" quantity="200100"/>
        <ColorMapEntry color="#800000" quantity="210100"/>
        <ColorMapEntry color="#00FF00" quantity="210101" opacity="1"/>
    </ColorMap>
    </RasterSymbolizer>
    </Rule>
    </FeatureTypeStyle>
    </sld:UserStyle>
    </UserLayer>
</StyledLayerDescriptor>

Things I tried so far:

Problem:

Any help would be appreciated, if someone has an idea how to do the dynamic-styling of the layer without creating new styles let me know, even though I think this is impossible as the GeoServer is serving pngs.

EDIT 1: This is my current request using &sld instead of &style: https://forestwatch.lup-umwelt.de/app_development/proxy/index.php/geoserver/forestwatch2/wms?SERVICE=WMS&VERSION=1.1.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=forestwatch2%3Astart_veraenderung&TILED=true&SLD=https://forestwatch.lup-umwelt.de/new/SLD/200100.sld&bbox=259026.34190395664,5232194.028899955,930593.5042616761,6111848.605691907&width=586&height=768&srs=EPSG:25832

However, it returns the error Error while getting SLD. See the log for details.

Here are the logs
        2023-07-31 14:46:08,419 ERROR [geoserver.ows] - 
org.geoserver.platform.ServiceException: Error while getting SLD.  See the log for details.
    at org.geoserver.wms.map.GetMapKvpRequestReader.read(GetMapKvpRequestReader.java:373)
    at org.geoserver.wms.map.GetMapKvpRequestReader.read(GetMapKvpRequestReader.java:85)
    at org.geoserver.ows.Dispatcher.parseRequestKVP(Dispatcher.java:1521)
    at org.geoserver.ows.Dispatcher.dispatch(Dispatcher.java:680)
    at org.geoserver.ows.Dispatcher.handleRequestInternal(Dispatcher.java:258)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:147)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
    at org.geoserver.filters.ThreadLocalsCleanupFilter.doFilter(ThreadLocalsCleanupFilter.java:28)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:75)
    at org.geoserver.wms.animate.AnimatorFilter.doFilter(AnimatorFilter.java:71)
    at org.geoserver.filters.SpringDelegatingFilter$Chain.doFilter(SpringDelegatingFilter.java:71)
    at org.geoserver.filters.SpringDelegatingFilter.doFilter(SpringDelegatingFilter.java:46)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.platform.AdvancedDispatchFilter.doFilter(AdvancedDispatchFilter.java:50)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerAnonymousAuthenticationFilter.doFilter(GeoServerAnonymousAuthenticationFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.geoserver.security.filter.GeoServerBasicAuthenticationFilter.doFilter(GeoServerBasicAuthenticationFilter.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:69)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at org.geoserver.security.filter.GeoServerSecurityContextPersistenceFilter$1.doFilter(GeoServerSecurityContextPersistenceFilter.java:53)
    at org.geoserver.security.filter.GeoServerCompositeFilter$NestedFilterChain.doFilter(GeoServerCompositeFilter.java:73)
    at org.geoserver.security.filter.GeoServerCompositeFilter.doFilter(GeoServerCompositeFilter.java:92)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
    at org.geoserver.security.GeoServerSecurityFilterChainProxy.doFilter(GeoServerSecurityFilterChainProxy.java:152)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.LoggingFilter.doFilter(LoggingFilter.java:87)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.XFrameOptionsFilter.doFilter(XFrameOptionsFilter.java:89)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.GZIPFilter.doFilter(GZIPFilter.java:48)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.SessionDebugFilter.doFilter(SessionDebugFilter.java:48)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.geoserver.filters.FlushSafeFilter.doFilter(FlushSafeFilter.java:44)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:499)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Unknown Source)

I updated my file to contain the layername (tested both with and without the workspace-name)

<StyledLayerDescriptor version="1.0.0">
<NamedLayer>
<Name>forestwatch2:start_veraenderung</Name>
<UserLayer>
<sld:UserStyle>
<sld:Name>Veraenderungsstart</sld:Name>
<IsDefault>1</IsDefault>
<FeatureTypeStyle>
<Rule>
<RasterSymbolizer>
<ColorMap>
<ColorMapEntry color="#FFFFFF" quantity="180100"/>
<ColorMapEntry color="#FF0000" quantity="200100"/>
<ColorMapEntry color="#00FF00" quantity="210100"/>
<ColorMapEntry color="#800000" quantity="220100"/>
</ColorMap>
</RasterSymbolizer>
</Rule>
</FeatureTypeStyle>
</sld:UserStyle>
</UserLayer>
</NamedLayer>
</StyledLayerDescriptor>

Solution

  • First, you need to use the "&sld" parameter rather than style. Then, mind the "library mode", you can read more about it here:

    https://docs.geoserver.org/maintain/en/user/styling/sld/working.html#external-styles

    In short, use a NamedLayer with the exact same name as the layer in the request, make it IsDefault=1. Here is a working example:

    https://gs-main.geosolutionsgroup.com/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=tiger:poi&bbox=-74.0118315772888%2C40.70754683896324%2C-74.00153046439813%2C40.719885123828675&width=641&height=768&srs=EPSG%3A4326&styles=burg&format=application/openlayers&sld=https://gs-main.geosolutionsgroup.com/geoserver/styles/burg-poi.sld