Wiremock __admin with form data header fails without readable error
Proposal
We've been manually calling the admin interface, because we control the stubs from Swift. We had a really hard time figuring out why Wiremock keeps returning 500 when there's a % sign in the JSON body. We've only seen a 500 through a proxy, there was no additional info (see WM server log below). We've tried to set up a similar thing in Java and it "just worked".
After many hours of debugging, we noticed that the for some weird reason Swift added application/x-www-form-urlencoded so we were essentially sending:
curl -i -X POST 'http://localhost:8089/__admin/mappings' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-raw '{"id":"93702552-962B-41DA-AD1F-56C932932D9E","request":{"method":"GET","urlPath":"\/foo\/bar"},"response":{"statusMessage":"OK","headers":{"Content-Type":"application\/json"},"body":"{\"baz\":\"qux %2\"}","status":200}}'This resulted in the %2 being interpreted as a URL-encoding, which is clearly invalid. %20 worked fine.
With this knowledge we were able to reproduce the problem in Java, and got a stack trace. Looking at the code it's clear-ish that the decoding happens before the request is handed to Wiremock (an "interceptor" fails), so that's why there are no logs.
So my plea is to somehow improve the error handling here, so we get a stack trace on the server side, not just a quiet 500 on the client side.
References
Version: 3.13.1
docker composeservices:
example.com:
image: wiremock/wiremock:3.13.1
command:
- "--global-response-templating"
- "--disable-gzip"
- "--use-chunked-encoding"
- "never"
- "--verbose"
container_name: example.com
ports:
- "9000:8080"
volumes:
- "./wiremock/example.com/__files:/home/wiremock/__files"
- "./wiremock/example.com/mappings:/home/wiremock/mappings"�██ ██ ██ ██████ ███████ ███ ███ ██████ ██████ ██ ██
�██ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██
�██ █ ██ ██ ██████ █████ ██ ████ ██ ██ ██ ██ █████
�██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
� ███ ███ ██ ██ ██ ███████ ██ ██ ██████ ██████ ██ ██
----------------------------------------------------------------
| Cloud: https://wiremock.io/cloud |
| |
| Slack: https://slack.wiremock.org/ |
----------------------------------------------------------------
version: 3.13.1
port: 8080
enable-browser-proxying: false
disable-banner: false
no-request-journal: false
verbose: true
extensions: response-template,webhook
2025-12-24 14:53:18.066 Admin request received:
10.89.2.16 - GET /health
Host: [localhost:9000]
Accept: [*/*]
User-Agent: [DemoUITests-Runner/1 CFNetwork/3826.500.131 Darwin/24.6.0]
Accept-Language: [en-GB,en;q=0.9]
Accept-Encoding: [gzip, deflate]
Connection: [keep-alive]
2025-12-24 14:53:18.092 Admin request received:
10.89.2.16 - POST /reset
Host: [localhost:9000]
Connection: [keep-alive]
Accept: [*/*]
User-Agent: [DemoUITests-Runner/1 CFNetwork/3826.500.131 Darwin/24.6.0]
Accept-Language: [en-GB,en;q=0.9]
Content-Length: [0]
Accept-Encoding: [gzip, deflate]
======== NOTHING HERE (this is where the 500 was received on the client side =========
2025-12-24 14:53:18.286 Admin request received:
10.89.2.16 - POST /shutdown
Host: [localhost:9000]
Connection: [keep-alive]
Accept: [*/*]
User-Agent: [DemoUITests-Runner/1 CFNetwork/3826.500.131 Darwin/24.6.0]
Accept-Language: [en-GB,en;q=0.9]
Content-Length: [0]
Accept-Encoding: [gzip, deflate][main] INFO org.eclipse.jetty.server.Server - jetty-11.0.24; built: 2024-08-26T18:11:22.448Z; git: 5dfc59a691b748796f922208956bd1f2794bcd16; jvm 21.0.8+-14196175-b1038.72
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@26dcd8c0{/__admin,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.handler.ContextHandler.ROOT - RequestHandlerClass from context returned com.github.tomakehurst.wiremock.http.StubRequestHandler. Normalized mapped under returned 'null'
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@7aad3f7d{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started NetworkTrafficServerConnector@241a0c3a{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8089}
[main] INFO org.eclipse.jetty.server.Server - Started Server@5486887b{STARTING}[11.0.24,sto=1000] @625ms
[qtp1756160273-50] INFO org.eclipse.jetty.server.handler.ContextHandler.__admin - RequestHandlerClass from context returned com.github.tomakehurst.wiremock.http.AdminRequestHandler. Normalized mapped under returned 'null'
[qtp1756160273-50] WARN org.eclipse.jetty.server.HttpChannel - /__admin/mappings
java.lang.IllegalArgumentException: Not valid encoding '%2\'
at org.eclipse.jetty.util.UrlEncoded.decodeHexByte(UrlEncoded.java:842)
at org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:305)
at org.eclipse.jetty.util.UrlEncoded.decodeTo(UrlEncoded.java:183)
at org.eclipse.jetty.util.UrlEncoded.decodeTo(UrlEncoded.java:166)
at com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.getFormParameters(WireMockHttpServletRequestAdapter.java:334)
at com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.<init>(WireMockHttpServletRequestAdapter.java:69)
at com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet.service(WireMockHandlerDispatchingServlet.java:149)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:587)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)
at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:314)
at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:267)
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1381)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1303)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at org.eclipse.jetty.server.Server.handle(Server.java:563)
at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:287)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
at java.base/java.lang.Thread.run(Unknown Source)
Exception in thread "main" java.lang.Exception: Response{protocol=http/1.1, code=500, message=Server Error, url=http://localhost:8089/__admin/mappings}
at MainKt.makeRequest2(main.kt:78)
at MainKt.main(main.kt:42)
at MainKt.main(main.kt)Source: wiremock/wiremock