Newest zio & tapir seem to break rewriting middleware

I posted this as well in the zio discord because I’m not sure which of the two updates broke it.

Thanks for the help!

After the last update to zio-http, a middleware I have has stopped working (it could also have to do with the newer version of tapir). My middleware rewrites the path based on the content of the body, it’s (I’m paraphrasing), something like this:

def reportRewriter(request: Request): ZIO[Any, Nothing, Request] = {
  for{
    str <- request.body,asString
  } yield {
    if(str.contains("json")) {
      request.copy(url = URL.decode("/jsonStream").toOption.get)
    } else {
      request
    }
  }
}

And then I use it as:

  def routes: Routes[ApplicationEnvironment, Response] = TapirRoutes.routes @@ reportRewriterMiddleware

The error line in Tapir’s code is:

          // shape path mismatch - input path too long; there are more segments in the request path than expected by
          // that input. Reporting a failure on the last path input.
          val failure =
            DecodeBasicInputsResult.Failure(lastPathInput, DecodeResult.Multiple(collectRemainingPath(Vector.empty, ctx)._1))

To make sure my middleware wasn’t the issue, I replaced it with

TapirRoutes.routes @@ Middleware.updatePath(path => Path.decode("/a/analytics/report/jsonStream"))```

And I get the same failure

I think that Tapir is doing it's parsing based on the original request, not the new request modified by the middleware, but it's hard to know

This worked fine in RC6 (and tapir v 1.10.7)

Damn... totally unexpected, I also get the same exact failure if I use a tapir interceptor instead of the zio middleware:

```scala
.addInterceptor(RequestInterceptor.transformServerRequest { case req: ZioHttpServerRequest =>
for{
    str <- request.body,asString
  } yield {
          val newUri =  if(str.contains("json")) {
            Uri.parse("/a/analytics/report/jsonStream").toOption
          } else None
          req.withOverride(protocolOverride = None, connectionInfoOverride = None, uriOverride = newUri)
  }

Latest info…
I think that what’s happening is that zio is prefiltering the endpoints passed in to the interceptors ahead of time, and leaving only those endpoints that match the original request uri! So of course, the new uri will never be matched. Now to find out how to change that pre-filtering (and no, adding a filterServerEndpoints did not work because the list is already filtered by the time it gets there)

Hm yes this might be on tapir’s side. Can you maybe create a possible small example to reproduce the problem?