Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Error: Request path cannot be empty

I have created an API proxy where I am setting the target endpoint dynamically using the JS Policy. The URL does not contain any path (i.e https://example.com). I can think of hacks to resolve this, but I want to know why am I getting this error. What if the target service has no path in the URL?

Here is a screenshot for your reference:

muq_ash_0-1736510607403.png

 

Solved Solved
0 7 292
1 ACCEPTED SOLUTION

Apigee behaves this way because when you don't specify a path in the TargetConnection, Apigee automatically adds a default path (/).
This is handled in the getTargetPath() method:

 

@Override
@XmlTransient
public String getTargetPath() {
    return this.path == null ? HttpProxyConnection.PATH_SEPARATOR : this.path;
}

 

However, when you set the target.url directly, this automatic behaviour doesn't occur. If the path is missing, Apigee throws an error due to the path validation logic:

private boolean validatePath(HTTPRequest request) {
    if (request != null && request.requestURI != null && !HTTPMethod.CONNECT.equals(request.method)) {
        if (request.requestURI.getURI().isEmpty()) {
            this.requestListener.onException(this, false, new BadRequestException(ErrorCodes.EMPTY_PATH));
            return true;
        } else if (request.requestURI.getURI().startsWith("?")) {
            this.requestListener.onException(this, false, new BadRequestException(ErrorCodes.BAD_PATH));
            return true;
        } else {
            return false;
        }
    }
    return false;
}

View solution in original post

7 REPLIES 7

Hello,

Are you sure the issue is the fact that there is no trailing character post base path name? The reason I ask is I can successfully call into https://example.com as a target proxy endpoint without any subsequent suffix in the domain. Reference can be seen below:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="TargetEndpoint-1">
<Description/>
<FaultRules/>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
<Flows/>
<HTTPTargetConnection>
<Properties/>
</HTTPTargetConnection>
</TargetEndpoint>

Are you sure the JS policy is properly mapping the response to a domain name, and the result is not coming out as null (debug can help with the above)? Is there a specific reason why you are using JS, conditionalizing aspects of your flow/policy files would work here as well without the need for custom scripting

To answer your first question, yes. There is no suffix involved. Secondly, I am using JS policy to dynamically set the target endpoint which is fetched from the request payload. 

Hi @muq_ash !

I agree, it would be great to check it in debug.
Also, pls make sure that the target.url must not be set before the targetrequest-flow (context.flow=="TARGET_REQ_FLOW").
Pls check this earlier thread as well, it might helps.

Best regards,
Marcelo

I have attached the JS policy in the request preflow of the target endpoint. I have replicated the scenario with a mock target and attached the trace of it.

muq_ash_0-1737014486353.pngmuq_ash_1-1737014521072.png

 

Just add a slash / at the end of your URL, https://example.com/

That's what I have been doing for now. But I want to know why Apigee is behaving this way.

Apigee behaves this way because when you don't specify a path in the TargetConnection, Apigee automatically adds a default path (/).
This is handled in the getTargetPath() method:

 

@Override
@XmlTransient
public String getTargetPath() {
    return this.path == null ? HttpProxyConnection.PATH_SEPARATOR : this.path;
}

 

However, when you set the target.url directly, this automatic behaviour doesn't occur. If the path is missing, Apigee throws an error due to the path validation logic:

private boolean validatePath(HTTPRequest request) {
    if (request != null && request.requestURI != null && !HTTPMethod.CONNECT.equals(request.method)) {
        if (request.requestURI.getURI().isEmpty()) {
            this.requestListener.onException(this, false, new BadRequestException(ErrorCodes.EMPTY_PATH));
            return true;
        } else if (request.requestURI.getURI().startsWith("?")) {
            this.requestListener.onException(this, false, new BadRequestException(ErrorCodes.BAD_PATH));
            return true;
        } else {
            return false;
        }
    }
    return false;
}