Skip to content

Plus signs are not encoded #1034

@nictas

Description

@nictas

Plus signs are interpreted as whitespaces by the CF controller. The CLI commands executed below clearly demonstrate this (note the GUID of the space returned by cf curl:

$ cf space "foo+bar" --guid
2c094d32-4c01-460b-94d0-f73484850d1f
$ cf space "foo bar" --guid
34f23458-0456-4dcf-b15c-a60474bef3ec
$ cf curl "/v2/spaces?q=name:foo+bar"
{
   "total_results": 1,
   "total_pages": 1,
   "prev_url": null,
   "next_url": null,
   "resources": [
      {
         "metadata": {
            "guid": "34f23458-0456-4dcf-b15c-a60474bef3ec",
            "url": "/v2/spaces/34f23458-0456-4dcf-b15c-a60474bef3ec",
            "created_at": "2020-01-30T11:09:34Z",
            "updated_at": "2020-01-30T11:09:34Z"
         },
         "entity": {
            "name": "foo bar",
            ...
         }
      }
   ]
}

Due to this, "+" should be encoded to "%2C" by the CF Java client, in order to keep the intention of the request unchanged. This is not done, however, as can be seen in the output of this test:

import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.client.v2.spaces.CreateSpaceRequest;
import org.cloudfoundry.client.v2.spaces.CreateSpaceResponse;
import org.cloudfoundry.client.v2.spaces.ListSpacesRequest;
import org.cloudfoundry.client.v2.spaces.ListSpacesResponse;
import org.cloudfoundry.client.v2.spaces.SpaceResource;
import org.cloudfoundry.reactor.ConnectionContext;
import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;

import reactor.core.publisher.Mono;

public class PlusEncoding {

    private static final String OAUTH_TOKEN = "bearer <TOKEN>"; // Set your OAuth token here (retrievable via "cf oauth-token").
    private static final String ORGANIZATION_GUID = "<ORGANIZATION_GUID>"; // Set the GUID of an organization in which you can create spaces.
    private static final String API_HOST = "<API_HOST>"; // Set an API host here.
    
    public static void main(String[] args) {
        CloudFoundryClient client = createClient();
        System.out.println("Creating space \"foo+bar\"...");
        CreateSpaceResponse response = client.spaces()
                                             .create(CreateSpaceRequest.builder()
                                                                       .organizationId(ORGANIZATION_GUID)
                                                                       .name("foo+bar")
                                                                       .build())
                                             .block();
        // Space is created just fine, because the + is in the body of the POST request.
        System.out.println("Created space: " + response.getEntity()
                                                       .getName());
        System.out.println("Getting space \"foo+bar\"...");
        // However, retrieving it is impossible, because the + sign is not encoded in the URL of the GET request.
        ListSpacesResponse spaces = client.spaces()
                                          .list(ListSpacesRequest.builder()
                                                                 .name("foo+bar")
                                                                 .build())
                                          .block();
        for (SpaceResource space : spaces.getResources()) {
            System.out.println("Space: " + space.getEntity()
                                                .getName());
        }
        System.out.println("Getting space \"foo+bar\" with manually encoded plus sign...");
        // Even encoding the plus manually does not work, because the % gets encoded:
        spaces = client.spaces()
                       .list(ListSpacesRequest.builder()
                                              .name("foo%2Cbar")
                                              .build())
                       .block();
        for (SpaceResource space : spaces.getResources()) {
            System.out.println("Space: " + space.getEntity()
                                                .getName());
        }
    }

    private static CloudFoundryClient createClient() {
        TokenProvider tokenProvider = createTokenProvider();
        ConnectionContext connectionContext = createConnectionContext();
        return ReactorCloudFoundryClient.builder()
                                        .connectionContext(connectionContext)
                                        .tokenProvider(tokenProvider)
                                        .build();
    }

    private static ConnectionContext createConnectionContext() {
        return DefaultConnectionContext.builder()
                                       .apiHost(API_HOST)
                                       .secure(true)
                                       .build();
    }

    private static TokenProvider createTokenProvider() {
        return connectionContext -> Mono.just(OAUTH_TOKEN);
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions