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

UriComponents needs support for URL building ending with trailing slash [SPR-13678]

Closed
spring-projects-issues opened this issue Nov 12, 2015 · 5 comments
Assignees
Labels
in: web status: declined type: enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Nov 12, 2015

Ivan Orešković opened SPR-13678 and commented

REST conventions suggest that resource paths should end with trailing slash.

When using UriComponentsBuilder to build UriComponents, it has no option to append trailing slash at the end of path segments, before query params and fragments.

    @Test
    public void testBuildUriFromNonTrailingSlash() {
        String url = "http://127.0.0.1:30001/basePath";
        UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);

        List<String> prefixPaths = new ArrayList<>();
        prefixPaths.add("foo");
        prefixPaths.add("bar");

        String id = "baz";

        List<String> suffixPaths = new ArrayList<>();
        suffixPaths.add("123");
        suffixPaths.add("456");

        Map<String, String> requestParams = new HashMap<>();
        requestParams.put("param1", "value1");
        requestParams.put("param2", "value2");

        prefixPaths.stream()
                .filter(path -> path != null && !path.toString().trim().isEmpty())
                .forEach(path -> uriBuilder.pathSegment(path));

        if (id != null && !id.toString().trim().isEmpty()) {
            uriBuilder.pathSegment(id.toString().trim());
        }

        suffixPaths.stream()
                .filter(path -> path != null && !path.toString().trim().isEmpty())
                .forEach(path -> uriBuilder.pathSegment(path));


        requestParams.entrySet().stream()
                .filter(e -> stringExists(e.getKey()) && stringExists(e.getValue()))
                .forEach(e -> uriBuilder.queryParam(e.getKey(), wrap(e.getKey())));

        UriComponents uri = uriBuilder.build();
        System.out.println(uri.toUriString());

        UriComponentsPathTrailingSlashDecorator uriWrapper = new UriComponentsPathTrailingSlashDecorator(uri, true);
        System.out.println(uriWrapper.toUriString());
    }

gives output

http://127.0.0.1:30001/basePath/foo/bar/baz/123/456?param1={param1}&param2={param2}
http://127.0.0.1:30001/basePath/foo/bar/baz/123/456/?param1={param1}&param2={param2}

The first line is how the current UriComponents#toUriString method does it, and the second is how it should do it provided the option to end the path with a trailing slash.


Affects: 4.2.2

Referenced from: commits 5f2d34f

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 13, 2015

Rossen Stoyanchev commented

It's true that currently pathSegment expects a non-empty path segment and ignores empty ones. I don't think we should change that. You can however make a call to path after appending all path segments:

uriBuilder.pathSegment("foo");
uriBuilder.pathSegment("bar");
...
uriBuilder.path("/");

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 13, 2015

Ivan Orešković commented

I agree that that is a remedy, but it would be convenient to be able to configure that option in UriComponentsBuilder.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 16, 2015

Rossen Stoyanchev commented

It feels a bit odd to have a property like that on UriComponentsBuilder. Are you holding on to the builder instance and re-using it? Otherwise it seems more natural to append to the URL with a call to path("/") vs setting a property such as enableTrailingSlash(true). We do have some options on the build methods (the encoded flag and a shortcut for URI vars) but I don't like the idea of further overloading the build methods with yet another boolean flag.

Could you provide a little more context about your use case and also what you mean with REST conventions for resource paths to end with a trailing slash? Maybe I'm misreading what you meant with it but should really all resource paths end with "/"?

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 16, 2015

Rossen Stoyanchev commented

Yet another thought might be to create your own static method that creates UriComponentsBuilder sub-class which invoke path("/") every time build is called. It sounds like that's the effect you're looking for.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 17, 2015

Rossen Stoyanchev commented

Never mind the UriComponentsBuilder sub-class idea (I gave that a try myself and doesn't work out too well).

I've updated the Javadoc on pathSegments to make this more obvious. I think use of path("/") fits quite well the specific example above.

If you have more comments on uses please do share.

@spring-projects-issues spring-projects-issues added status: declined type: enhancement in: web labels Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web status: declined type: enhancement
Projects
None yet
Development

No branches or pull requests

2 participants