Should empty request header values be allowed?

1,398 views
Skip to first unread message

Scott Langley

unread,
Apr 12, 2016, 1:10:26 PM4/12/16
to wiremock-user
I have an application that I'm proxying/recording with WireMock that sometimes populates a request header with an empty field value, for example the header named "Cookie".  I then constructed some WireMock stubs to respond to such requests.   WireMock certainly doesn't like empty header values and throws an exception when it receives such a request:

java.lang.IllegalStateException: No value for Cookie
    at wiremock.com.google.common.base.Preconditions.checkState(Preconditions.java:173)
    at com.github.tomakehurst.wiremock.http.MultiValue.checkPresent(MultiValue.java:55)
    at com.github.tomakehurst.wiremock.http.MultiValue.values(MultiValue.java:50)
    at com.github.tomakehurst.wiremock.http.HttpHeaders.<init>(HttpHeaders.java:53)
    at com.github.tomakehurst.wiremock.jetty9.JettyHttpServletRequestAdapter.getHeaders(JettyHttpServletRequestAdapter.java:142)
    at com.github.tomakehurst.wiremock.verification.LoggedRequest.createFrom(LoggedRequest.java:50)
    at com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal.requestReceived(InMemoryRequestJournal.java:66)
    at com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal.requestReceived(InMemoryRequestJournal.java:72)
    at com.github.tomakehurst.wiremock.core.WireMockApp.serveStubFor(WireMockApp.java:90)
    at com.github.tomakehurst.wiremock.http.StubRequestHandler.handleRequest(StubRequestHandler.java:37)
    at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:43)
    at com.github.tomakehurst.wiremock.jetty9.JettyHandlerDispatchingServlet.service(JettyHandlerDispatchingServlet.java:97)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at wiremock.org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)

I'm using: wiremock-standalone-2.0.10-beta.jar
 
Should WireMock be more tolerant of such requests?

Thanks.

Scott Langley

Tom Akehurst

unread,
Apr 12, 2016, 1:21:52 PM4/12/16
to wiremock-user
Could you post enough detail to replicate the problem? It sounds like a bug but it'd be good to confirm.

Scott Langley

unread,
Apr 12, 2016, 2:20:10 PM4/12/16
to wiremock-user
Below is a more detailed log.  The client application is a Play1 running a test case from inside Play:

play.libs.WS.WSRequest request = WS.url(destinalUrlasString);
request.setHeader("Cookie", null)

11:12:19,280 DEBUG [providers.netty.request.NettyRequestSender] Using cached Channel [id: 0x5b3acf8d, /127.0.0.1:55018 => hyena.pc.scharp.org/127.0.0.1:9020]
 for uri http://hyena.pc.scharp.org:9020/webservice/v/4/subscriber
11:12:19,280 DEBUG [providers.netty.request.NettyRequestSender] Using cached Channel [id: 0x5b3acf8d, /127.0.0.1:55018 => hyena.pc.scharp.org/127.0.0.1:9020] for POST '/webservice/v/4/subscriber'
11:12:19,280 DEBUG [eclipse.jetty.io.SelectorManager] Selector loop woken up from select, 1/1 selected
11:12:19,280 DEBUG [eclipse.jetty.io.SelectChannelEndPoint] Key interests updated 1 -> 0 on SelectChannelEndPoint@54350fd8{/127.0.0.1:55018<->9020,Open,in,out,R,-,54/30000,HttpConnection}{io=1,kio=0,kro=1}
11:12:19,281 DEBUG [eclipse.jetty.io.SelectChannelEndPoint] Local interests updating 1 -> 0 for SelectChannelEndPoint@54350fd8{/127.0.0.1:55018<->9020,Open,in,out,R,-,54/30000,HttpConnection}{io=0,kio=0,kro=1}
11:12:19,281 DEBUG [eclipse.jetty.io.SelectorManager] Queued change wiremock.org.eclipse.jetty.io.SelectChannelEndPoint$1@35428261
11:12:19,281 DEBUG [eclipse.jetty.io.AbstractConnection] FILL_INTERESTED-->FILLING HttpConnection@1b9f6a51{FILLING}
11:12:19,281 DEBUG [eclipse.jetty.io.SelectorManager] Running change wiremock.org.eclipse.jetty.io.SelectChannelEndPoint$1@35428261
11:12:19,281 DEBUG [eclipse.jetty.io.SelectorManager] Selector loop waiting on select
11:12:19,281 DEBUG [eclipse.jetty.server.HttpConnection] HttpConnection@1b9f6a51{FILLING} onFillable HttpChannelState@22bf2361{s=IDLE i=true a=null}
11:12:19,281 DEBUG [eclipse.jetty.io.ChannelEndPoint] filled 364 SelectChannelEndPoint@54350fd8{/127.0.0.1:55018<->9020,Open,in,out,-,-,55/30000,HttpConnection}{io=0,kio=0,kro=1}
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] parseNext s=START HeapByteBuffer@6471b2a1[p=0,l=364,c=8192,r=364]={<<<POST /webservice/...lopment_SESSION>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] START --> SPACE1
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] SPACE1 --> URI
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] URI --> SPACE2
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] SPACE2 --> REQUEST_VERSION
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] REQUEST_VERSION --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_IN_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_IN_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_VALUE --> HEADER_IN_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_IN_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_IN_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_IN_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_IN_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_IN_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_IN_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_IN_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> HEADER_IN_VALUE
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER_IN_VALUE --> HEADER
11:12:19,281 DEBUG [eclipse.jetty.http.HttpParser] HEADER --> CONTENT
11:12:19,281 DEBUG [eclipse.jetty.server.HttpChannel] HttpChannelOverHttp@1f26aa1b{r=3,c=false,a=IDLE,uri=-} handle enter
11:12:19,281 DEBUG [eclipse.jetty.server.HttpChannelState] HttpChannelState@22bf2361{s=IDLE i=true a=null} handling IDLE
11:12:19,281 DEBUG [eclipse.jetty.server.HttpChannel] HttpChannelOverHttp@1f26aa1b{r=3,c=false,a=DISPATCHED,uri=/webservice/v/4/subscriber} action REQUEST_DISPATCH
11:12:19,282 DEBUG [eclipse.jetty.server.Server] REQUEST POST /webservice/v/4/subscriber on HttpChannelOverHttp@1f26aa1b{r=3,c=false,a=DISPATCHED,uri=/webservice/v/4/subscriber}
11:12:19,282 DEBUG [jetty.server.handler.ContextHandler] scope null||/webservice/v/4/subscriber @ w.o.e.j.s.ServletContextHandler@126b50a9{/__admin,null,AVAILABLE}
11:12:19,282 DEBUG [jetty.server.handler.ContextHandler] scope null||/webservice/v/4/subscriber @ w.o.e.j.s.ServletContextHandler@62f5dc95{/,null,AVAILABLE}
11:12:19,282 DEBUG [jetty.server.handler.ContextHandler] context=||/webservice/v/4/subscriber @ w.o.e.j.s.ServletContextHandler@62f5dc95{/,null,AVAILABLE}
11:12:19,282 DEBUG [eclipse.jetty.servlet.ServletHandler] servlet |/webservice/v/4/subscriber|null -> com.github.tomakehurst.wiremock.jetty9.JettyHandlerDispatchingServlet-1e0f9a0a@dd19e9e4==com.github.tomakehurst.wiremock.jetty9.JettyHa
ndlerDispatchingServlet,-1,true
11:12:19,282 DEBUG [eclipse.jetty.servlet.ServletHandler] chain=wiremock.org.eclipse.jetty.servlets.GzipFilter-28230b3->com.github.tomakehurst.wiremock.jetty9.JettyHandlerDispatchingServlet-1e0f9a0a@dd19e9e4==com.github.tomakehurst.wirem
ock.jetty9.JettyHandlerDispatchingServlet,-1,true
11:12:19,282 DEBUG [eclipse.jetty.servlet.ServletHandler] call filter wiremock.org.eclipse.jetty.servlets.GzipFilter-28230b3
11:12:19,282 DEBUG [eclipse.jetty.servlet.ServletHandler] call servlet com.github.tomakehurst.wiremock.jetty9.JettyHandlerDispatchingServlet-1e0f9a0a@dd19e9e4==com.github.tomakehurst.wiremock.jetty9.JettyHandlerDispatchingServlet,-1,true
11:12:19,283 WARN  [eclipse.jetty.servlet.ServletHandler] /webservice/v/4/subscriber

java.lang.IllegalStateException: No value for Cookie
        at wiremock.com.google.common.base.Preconditions.checkState(Preconditions.java:173)
        at com.github.tomakehurst.wiremock.http.MultiValue.checkPresent(MultiValue.java:55)
        at com.github.tomakehurst.wiremock.http.MultiValue.values(MultiValue.java:50)
        at com.github.tomakehurst.wiremock.http.HttpHeaders.<init>(HttpHeaders.java:53)
        at com.github.tomakehurst.wiremock.jetty9.JettyHttpServletRequestAdapter.getHeaders(JettyHttpServletRequestAdapter.java:142)
        at com.github.tomakehurst.wiremock.verification.LoggedRequest.createFrom(LoggedRequest.java:50)
        at com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal.requestReceived(InMemoryRequestJournal.java:66)
        at com.github.tomakehurst.wiremock.verification.InMemoryRequestJournal.requestReceived(InMemoryRequestJournal.java:72)
        at com.github.tomakehurst.wiremock.core.WireMockApp.serveStubFor(WireMockApp.java:90)
        at com.github.tomakehurst.wiremock.http.StubRequestHandler.handleRequest(StubRequestHandler.java:37)
        at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:43)
        at com.github.tomakehurst.wiremock.jetty9.JettyHandlerDispatchingServlet.service(JettyHandlerDispatchingServlet.java:97)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at wiremock.org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
        at wiremock.org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83)
        at wiremock.org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:300)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
        at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
        at wiremock.org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
        at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
        at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at wiremock.org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
        at wiremock.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
        at wiremock.org.eclipse.jetty.server.Server.handle(Server.java:499)
        at wiremock.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
        at wiremock.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
        at wiremock.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
        at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
        at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
        at java.lang.Thread.run(Thread.java:745)
11:12:19,284 DEBUG [eclipse.jetty.servlet.ServletHandler] (POST /webservice/v/4/subscriber)@430615700 wiremock.org.eclipse.jetty.server.Request@19aaac94
11:12:19,285 DEBUG [eclipse.jetty.server.HttpConnection] wiremock.org.eclipse.jetty.server.HttpConnection$SendCallback@1b14db24[PROCESSING][i=ResponseInfo{HTTP/1.1 500 null,346,false},cb=wiremock.org.eclipse.jetty.server.HttpChannel$Comm
itCallback@536d65d8] generate: NEED_HEADER (null,[p=0,l=346,c=2048,r=346],true)@START
11:12:19,285 DEBUG [eclipse.jetty.server.HttpConnection] wiremock.org.eclipse.jetty.server.HttpConnection$SendCallback@1b14db24[PROCESSING][i=ResponseInfo{HTTP/1.1 500 null,346,false},cb=wiremock.org.eclipse.jetty.server.HttpChannel$Comm
itCallback@536d65d8] generate: FLUSH ([p=0,l=232,c=8192,r=232],[p=0,l=346,c=2048,r=346],true)@COMPLETING
11:12:19,285 DEBUG [eclipse.jetty.io.WriteFlusher] write: WriteFlusher@62d2fafd{IDLE} [HeapByteBuffer@161de537[p=0,l=232,c=8192,r=232]={<<<HTTP/1.1 500 Serv...z-SNAPSHOT)\r\n\r\n>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00},HeapByteBuffer@3c8854c0[p=0,l=346,c=2048,r=346]={<<<<html>\n<head>\n<me.../body>\n</html>\n>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}]
11:12:19,285 DEBUG [eclipse.jetty.io.WriteFlusher] update WriteFlusher@62d2fafd{WRITING}:IDLE-->WRITING
11:12:19,285 DEBUG [eclipse.jetty.io.ChannelEndPoint] flushed 578 SelectChannelEndPoint@54350fd8{/127.0.0.1:55018<->9020,Open,in,out,-,W,4/30000,HttpConnection}{io=0,kio=0,kro=1}
11:12:19,285 DEBUG [eclipse.jetty.io.WriteFlusher] update WriteFlusher@62d2fafd{IDLE}:WRITING-->IDLE
11:12:19,285 DEBUG [providers.netty.handler.HttpProtocol]

Request DefaultHttpRequest(chunked: false)
POST /webservice/v/4/subscriber HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Cookie:
Content-Length: 135
Connection: keep-alive
Host: hyena.pc.scharp.org:9020
Accept: */*
User-Agent: AHC/1.0

Response DefaultHttpResponse(chunked: false)
HTTP/1.1 500 Server Error
Date: Tue, 12 Apr 2016 18:12:19 GMT
Cache-Control: must-revalidate,no-cache,no-store
Content-Type: text/html; charset=ISO-8859-1
Content-Length: 346
Connection: close
Server: Jetty(9.2.z-SNAPSHOT)

Tom Akehurst

unread,
Apr 13, 2016, 4:50:13 AM4/13/16
to wiremock-user
Thanks for posting this.

It definitely looks like WM should handle null header values better, perhaps treating them as absent rather than the somewhat undefined behaviour you've seen.

Incidentally, why would you want to send a null Cookie header? Is this something you've seen a real UA do?

Scott Langley

unread,
Apr 13, 2016, 2:23:05 PM4/13/16
to wiremock-user
No, I don't think the null Cookie header is desirable.  But it's what a real UA currently does that was written in my group.  It works with our current integration tests, I'm attempting to migrate our tests to not require a working live instance of each of our web services.

Thanks.

Scott

Tom Akehurst

unread,
Apr 15, 2016, 8:26:22 AM4/15/16
to wiremock-user
OK, I'll have a look at making that bit of code null safe for the next release. Making it equivalent to there being no values present for the header seems most sensible. Any thoughts on this?

Mathieu Lavoie

unread,
May 26, 2016, 10:27:35 PM5/26/16
to wiremock-user
Hi,

I'm facing the exact same issue. Any development on a solution yet?

Thanks

Tom Akehurst

unread,
May 27, 2016, 2:26:19 PM5/27/16
to wiremock-user
Progress, but it's not complete yet as I'm doing it as part of a large refactor.

kapil aggarwal

unread,
Jul 12, 2016, 7:32:24 AM7/12/16
to wiremock-user
Hi 

I am facing the same issue , any further updates , seems 2.1.7 the latest version is not having any fix for this.

Thanks
Kapil Aggarwal

Ariel Stolerman

unread,
Jul 15, 2016, 1:40:37 PM7/15/16
to wiremock-user
Hi,

I'm also experiencing this issue trying to upgrade from WM 1.57 to 2.1.7.
Any estimates on when a fix will be out?

Thanks!
--Ariel

Tom Akehurst

unread,
Jul 27, 2016, 5:28:15 AM7/27/16
to wiremock-user
Fix now on master. Will release later today.
Reply all
Reply to author
Forward
0 new messages