Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add matchedRoutePath to Request #1126

Closed

Conversation

bradenschmidt
Copy link

@bradenschmidt bradenschmidt commented Jun 6, 2019

We're in the processing of adding request tracing to all of our java systems, all of which are using Spark as their web framework. To do so we implemented global before and an afterAfter filter which records information about the request and the response and sends it off to our tracing implementation. After the first version was released we noticed an improvement could be made by sanitizing paths params and using the route parameter key as the cleaned version.

This technique was noted in #959 and #1048 with #1049 appearing to close both those issues.

The problem for our use case occurs because we implement automatic tracing of requests as ALL_PATHS filters. This becomes a problem because matchedUri() in a global after filter will return all paths and not that actual matched route path (#1049 (comment)).

The proposal in this PR is to introduce a new field called matchedRoutePath with a getter and setter. The setter records the path during the route execution so it is available in the getter for after and afterAfter filters to use.

@bradenschmidt
Copy link
Author

The naming of this field and thus the getter is up for debate. I had toyed with using an original prefix but decided it didn't make sense. Arguably this could be matchedRoute but I decided to leave that available to return the actual RouteMatch object should that be required in the future.

@perwendel
Copy link
Owner

Hmm, I've reviewed this quickly and I fail to see how this new method would return anything different the the already existing matchedPath() in Request?

@perwendel
Copy link
Owner

I've checked some more and concluded that this is just duplicate functionality of matchedPath(). I'll close for now.

@bradenschmidt
Copy link
Author

Hey there, glad to get the review!

Initially I thought matchedPath() was what I was looking for but it didn't turn out to be the case which is why the PR ended up being raised with very similar yet subtly different semantics.

The problem with matchedPath() is that it returns the matched path of the filters instead of the path of the original matching route that the filter is operating on. This means that when you're looking to attach tracing information from an afterAfter(), for example, you'll get the filters matched path which will generally never be the actual route that was matched. In most cases it will indeed return ALL_PATHS==+/*paths.

The following snippet shows the difference adapted from one of the new tests added:

@Test
    public void shouldBeAbleToGetTheMatchedRoutePathInAfter() throws Exception {
        final AtomicReference<String> matchedRoutePath = new AtomicReference<>();
        final AtomicReference<String> matchedPath = new AtomicReference<>();
        after((q, p) -> {
            matchedRoutePath.set(q.matchedRoutePath());
            matchedPath.set(q.matchedPath());
        });

        http.get("/users/bob");

        assertNotNull(matchedRoutePath.get());
        assertThat(matchedRoutePath.get(), is(THE_MATCHED_ROUTE));
        assertThat(matchedPath.get(), is(THE_MATCHED_ROUTE)); // Assertion Failure
    }

This fails because the last assertion for the matchedPath.get() actually returns +/*paths which is the ALL_PATHS filter used as the default if none is specified.

This behaviour is further reinforced by the tests like this one. The test ensures the matchedPath() returns the filters path and not the original THE_MATCHED_ROUTE that was called.

assertEquals("Should have returned the matched route from the afterafter filter", AFTERAFTER_MATCHED_ROUTE, q.matchedPath());

This situation was pointed out in the original implementation of matchedPath() here #1049 (comment) but really could be considered a feature and I do feel both are required to cover both cases.

Happy to discuss more cases and why I ended up requiring this feature. I've been using it for quite some time now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants