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

custom AbstractErrorWebExceptionHandler not triggered by connect timeout from netty ProxyHandler

Open
#3,606 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

I have a gateway service based on SCG, and it's been running great for years. However, I'm having trouble handling a particular exception, and I'm even out of ideas for how to reproduce/test the case.

Requirement: I'll spare you too many details, but one of our service's requirements is that in the event of a 5xx error or connect timeout from the upstream, it responds to the client with a 502 (whose body contains the upstream error details). This 502 is our way of telling the client "don't blame us, we're working as expected."

Status/Context:
After extending AbstractErrorWebExceptionHandler, I have this working for pretty much every ResponseStatusException (404, 500, 504, etc). I thought this was working for 503s as well, but in practice this mostly results in a connect timeout: Netty's ProxyHandler throws a ProxyConnectException instead of a ResponseStatusException. It's also usually accompanied by an SSL handshake exception (whose underlying cause is the connect timeout).

The Bug?
The above would be fine except for one thing: My custom exception handler never seems to hear about ProxyConnectException or the SSL exception, so I'm unable to handle them as I need to.

What I've Tried:

  1. Due to policies I can't put my exact code here, but my custom error handler is very close to this one from this Baeldung page. I've seen this work locally and in prod with plenty of other exceptions.
  2. I have WireMock tests, but it seems that it no longer has a way to trigger a connect timeout (due to underlying libraries not being able to do so reliably; see this). This in particular makes it hard to reproduce it locally (where I can add break points).

Ideas:

  1. I noticed the error handler code I linked has Order(-2). I'm aware of filter ordering, but it's not clear to me how it works with error handlers:
    1. Do error handlers and filters live within the same order "dimension" as filters?
    2. Or are multiple error handlers possible, and in the event of an error the ordering may give one "dibs" over an error before a lesser handler?
  2. Can I configure SCG to use a subclass of ProxyHandler that watches out for ProxyConnectException with "timeout" and throws a ResponseStatusException instead?
  3. Do I somehow need to increase the scope of exceptions that cause my error handler to be called?

Bonus: How I can programmatically cause this connect timeout to debug this locally + make sure it doesn't regress?

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

The issue points to Netty's ProxyHandler and ProxyConnectException and a custom AbstractErrorWebExceptionHandler; begin by tracing how these exceptions move through Spring Cloud Gateway's reactive error path. Use the existing WireMock tests if available, while investigating the reported connect-timeout reproduction limitation. Done means the desired 502 behavior is reproducible and covered by a regression test.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.