spring-cloud / spring-cloud/spring-cloud-gateway

When a websocket request is initiated, the response header type is ReadOnlyHttpHeaders

Open
#2,258 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Dependent version

  • spring-cloud-dependencies: 2020.0.3
  • spring-boot-starter-parent: 2.4.6

1. application.yml

Add one of SetResponseHeader or DedupeResponseHeader under "default-filters"

spring:
  cloud:
    gateway:
      default-filters:
        - SetResponseHeader=Access-Control-Expose-Headers, Content-Disposition
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin Vary, RETAIN_UNIQUE

2. a websocket request

ws://localhost:8080/hpfm/websocket?access_token=0d261199-b39e-4424-82f9-9055b92119fd

3. exception

2021-06-04 14:41:48.161 ERROR 20152 --- [ctor-http-nio-7] o.s.w.s.adapter.HttpWebHandlerAdapter    : [ee2db0e7-1] Error [java.lang.UnsupportedOperationException] for HTTP GET "/hpfm/websocket?access_token=0d261199-b39e-4424-82f9-9055b92119fd", but ServerHttpResponse already committed (200 OK)
2021-06-04 14:41:48.164 ERROR 20152 --- [ctor-http-nio-7] r.n.http.server.HttpServerOperations     : [id:ee2db0e7-1, L:/10.215.0.89:8080 - R:bojiangzhou/10.215.0.89:53965] Error finishing response. Closing connection

java.lang.UnsupportedOperationException: null
	at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:126) ~[spring-web-5.3.7.jar:5.3.7]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ org.springframework.boot.actuate.web.trace.reactive.HttpTraceWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.hzero.gateway.filter.GateWayHelperFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.hzero.gateway.filter.IpCheckedFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ HTTP GET "/hpfm/websocket?access_token=0d261199-b39e-4424-82f9-9055b92119fd" [ExceptionHandlingWebHandler]
Stack trace:
		at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:126) ~[spring-web-5.3.7.jar:5.3.7]
		at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.dedupe(DedupeResponseHeaderGatewayFilterFactory.java:147) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
		at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.dedupe(DedupeResponseHeaderGatewayFilterFactory.java:130) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
		at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory$1.lambda$filter$0(DedupeResponseHeaderGatewayFilterFactory.java:93) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
		at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:73) ~[reactor-core-3.4.6.jar:3.4.6]
		at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:32) ~[reactor-core-3.4.6.jar:3.4.6]
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:224) [reactor-core-3.4.6.jar:3.4.6]
..............

4. the reason

When the websocket request is completed, the request will be completed ahead of time.

image

Then the status of ServerHttpResponse will be changed to COMMITTED.

image

When finally entering DedupeResponseHeaderGatewayFilterFactory to get HttpHeaders, since the status of ServerHttpResponse is COMMITTED, it returns ReadOnlyHttpHeaders.

image
image

Is this a bug, or how to solve it ?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with DedupeResponseHeaderGatewayFilterFactory.dedupe, using the reported Spring Cloud Gateway versions and the websocket request with SetResponseHeader or DedupeResponseHeader enabled. Reproduce the ReadOnlyHttpHeaders exception and determine the appropriate handling when the response is already committed; done means the websocket request completes without the filter failing.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.