Configured in Proxy Endpoint
<HTTPProxyConnection>
<BasePath>/abc/def</BasePath>
</HTTPProxyConnection>
If I try basepath with upper case letters, e.g. /AbC/Def, I get classification error:
{ "fault":
{ "faultstring": "Classification failed for host: .. url: /AbC/Def",
"detail": { "code": "CLASSIFICATION_FAILED" }
}
}
How to make the basepath case insensitive?
Solved! Go to Solution.
What you can do is - have basepath as - '/',
Then you could create a conditional flow for a path suffix - the condition can accept a regex, so it can be case insensitive [/abc/def] -
http://docs.apigee.com/api-services/reference/conditions-reference
To answer your question - How to make the basepath case insensitive? - I don't think its possible
I had a similar issue when placing the Apigee layer over our current api. We already had a number of partners hitting our case insensitive api and did not want to make them change their integration when adding the Apigee layer. Additionally, I did not want to lose the built in features Apigee provides by using the suggestion of having one proxy with "/" as a base path.
I was able to set up a number of proxies in Apigee and wrote a workaround to make them all case insensitive.
1. All base paths for our proxies are now set up in lower case.
2. I created a "Master Proxy" which all of our traffic flows through with a base path of "/v1"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ProxyEndpoint name="default"> <Description/> <FaultRules/> <PreFlow name="PreFlow"> <Request> <Step> <Name>Raise-Fault-404</Name> <Condition>(request.header.X-STOP-ME-404 = "true")</Condition> </Step> </Request> <Response/> </PreFlow> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> <HTTPProxyConnection> <BasePath>/v1</BasePath> <Properties/> <VirtualHost>secure</VirtualHost> </HTTPProxyConnection> <RouteRule name="default"> <TargetEndpoint>default</TargetEndpoint> </RouteRule> </ProxyEndpoint>
3. The "Master Proxy" target endpoint uses path chaining with a path of "/" to point to our other local proxies on Apigee
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <TargetEndpoint name="default"> <Description/> <FaultRules/> <PreFlow name="PreFlow"> <Request> <Step> <Name>JavaScript-2</Name> </Step> </Request> <Response/> </PreFlow> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> <Flows/> <LocalTargetConnection> <Path>/</Path> </LocalTargetConnection> </TargetEndpoint>
4. The "Master Proxy" has a JavaScript policy on the default target PreFlow which turns the requested message path into lowercase. This has been updated provide support for query parameters and to stop infinite loops.
// Need to stop infinite loop, in case someone hits an endpoint that does not exist var stop = context.targetRequest.headers['X-STOP-ME-404'] if(stop != 'true') { // Since we will be constructing the uri ourselves tell Apigee not to copy over the path suffix context.setVariable("target.copy.pathsuffix", false); // Need to stop infinite loop, in case someone hits an endpoint that does not exist context.targetRequest.headers['X-STOP-ME-404']='true'; // RegEx for unique case sensitive Ids var sfIdRegEx = new RegExp("(?=.*[A-Za-z]+)(?=.*[0-9]+)([A-Za-z0-9]{18}|[A-Za-z0-9]{15})"); var queryParams = context.getVariable("message.querystring") var messagePath = context.getVariable("message.path") var constructedMessagePath = ""; var messagePathParts; if (messagePath) { messagePathParts = messagePath.split('/'); for (var i = 0; i <= messagePathParts.length; i++) { if(messagePathParts[i]) { constructedMessagePath = constructedMessagePath + '/'; // If it is an Id that is case sensitive. if(sfIdRegEx.test(messagePathParts[i])) { constructedMessagePath = constructedMessagePath + messagePathParts[i] } else { constructedMessagePath = constructedMessagePath + messagePathParts[i].toLowerCase(); } } } } if(queryParams) { queryParams = '?' + queryParams ; } context.setVariable("message.path", constructedMessagePath); context.setVariable("Debug", queryParams); context.setVariable("target.url", context.getVariable("target.url") + constructedMessagePath + queryParams); }
5. In order to stop recursion when someone passes in a uri that does not hit one of our proxies I added a Raise Fault policy to send back a 404. This was added on the "Master Proxy" endpoint default PreFlow.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <RaiseFault async="false" continueOnError="false" enabled="true" name="Raise-Fault-404"> <DisplayName>Raise Fault-404</DisplayName> <Properties/> <FaultResponse> <Set> <Headers/> <Payload contentType="text/plain"/> <StatusCode>404</StatusCode> <ReasonPhrase>NotFound</ReasonPhrase> </Set> </FaultResponse> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> </RaiseFault>
So now I have a proxy with a base path of /v1/abc/def/* that can be accessed using
/v1/abc/def/003q000000RTElQ
/v1/Abc/dEf/003q000000RTElQ
/v1/ABC/DEF/003q000000RTElQ
/v1/aBc/DeF/003q000000RTElQ
and the above uris will point to proxy /v1/abc/def/003q000000RTElQ
If someone was to pass a url that does not match a proxy in our org we would return a 404
It works for us because it is a temporary solution until we can notify all are partners that we will be going to case sensitive uris and we don't lose any of the analytics .
What you can do is - have basepath as - '/',
Then you could create a conditional flow for a path suffix - the condition can accept a regex, so it can be case insensitive [/abc/def] -
http://docs.apigee.com/api-services/reference/conditions-reference
To answer your question - How to make the basepath case insensitive? - I don't think its possible
Thanks for answer.
With the solution basepath '/', I can have only one proxy deployed (2 different proxies cannot have same basepath deployed on same env).
Ok, I'll take the answer as 'not possible' then.
@crina.cimpian
Just wanted to correct you that
2 different proxies with same basepath but different VHOST can be deployed on same env.
So in case you require to have proxy with similar basepath, you can create a separate VHOST for it.
But I did not get your point when you say "With the solution basepath '/', I can have only one proxy deployed"
In my ORG, proxies with basepath "/" with vhost default, basepath "/" with VHOST secure and other basepaths for different proxy are deployed.
So why this question?
Different VHOST means different domain and/or port.
I have a couple of API Proxies, each independent revisions. They need to have same domain with different basepaths, that are case insensitive. E.g. 'Proxy1' on basepath /base1 and 'Proxy2' on basepath /base2. Based on the above suggestion, in order for 'Proxy1', and 'Proxy2' to support case insensitive basepath - /base1, /BASE1, /Base2 etc - then these 2 proxies have to use same basepath '/', which means they have to be same proxy. Not separate proxies that can be deployed independent.
@crina.cimpian
One domain can have different VHOST but they listen to different ports. So the domain name can be same but PORT number should be different. I hope you got this point.
So one Domain can have multiple VHOST.
There are few benefits for keeping Same Domain with Different VHOST Name. The benefits are a seperate thread for discussion. In case you want to know the benefits, do let me know
I had a similar issue when placing the Apigee layer over our current api. We already had a number of partners hitting our case insensitive api and did not want to make them change their integration when adding the Apigee layer. Additionally, I did not want to lose the built in features Apigee provides by using the suggestion of having one proxy with "/" as a base path.
I was able to set up a number of proxies in Apigee and wrote a workaround to make them all case insensitive.
1. All base paths for our proxies are now set up in lower case.
2. I created a "Master Proxy" which all of our traffic flows through with a base path of "/v1"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ProxyEndpoint name="default"> <Description/> <FaultRules/> <PreFlow name="PreFlow"> <Request> <Step> <Name>Raise-Fault-404</Name> <Condition>(request.header.X-STOP-ME-404 = "true")</Condition> </Step> </Request> <Response/> </PreFlow> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> <HTTPProxyConnection> <BasePath>/v1</BasePath> <Properties/> <VirtualHost>secure</VirtualHost> </HTTPProxyConnection> <RouteRule name="default"> <TargetEndpoint>default</TargetEndpoint> </RouteRule> </ProxyEndpoint>
3. The "Master Proxy" target endpoint uses path chaining with a path of "/" to point to our other local proxies on Apigee
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <TargetEndpoint name="default"> <Description/> <FaultRules/> <PreFlow name="PreFlow"> <Request> <Step> <Name>JavaScript-2</Name> </Step> </Request> <Response/> </PreFlow> <PostFlow name="PostFlow"> <Request/> <Response/> </PostFlow> <Flows/> <LocalTargetConnection> <Path>/</Path> </LocalTargetConnection> </TargetEndpoint>
4. The "Master Proxy" has a JavaScript policy on the default target PreFlow which turns the requested message path into lowercase. This has been updated provide support for query parameters and to stop infinite loops.
// Need to stop infinite loop, in case someone hits an endpoint that does not exist var stop = context.targetRequest.headers['X-STOP-ME-404'] if(stop != 'true') { // Since we will be constructing the uri ourselves tell Apigee not to copy over the path suffix context.setVariable("target.copy.pathsuffix", false); // Need to stop infinite loop, in case someone hits an endpoint that does not exist context.targetRequest.headers['X-STOP-ME-404']='true'; // RegEx for unique case sensitive Ids var sfIdRegEx = new RegExp("(?=.*[A-Za-z]+)(?=.*[0-9]+)([A-Za-z0-9]{18}|[A-Za-z0-9]{15})"); var queryParams = context.getVariable("message.querystring") var messagePath = context.getVariable("message.path") var constructedMessagePath = ""; var messagePathParts; if (messagePath) { messagePathParts = messagePath.split('/'); for (var i = 0; i <= messagePathParts.length; i++) { if(messagePathParts[i]) { constructedMessagePath = constructedMessagePath + '/'; // If it is an Id that is case sensitive. if(sfIdRegEx.test(messagePathParts[i])) { constructedMessagePath = constructedMessagePath + messagePathParts[i] } else { constructedMessagePath = constructedMessagePath + messagePathParts[i].toLowerCase(); } } } } if(queryParams) { queryParams = '?' + queryParams ; } context.setVariable("message.path", constructedMessagePath); context.setVariable("Debug", queryParams); context.setVariable("target.url", context.getVariable("target.url") + constructedMessagePath + queryParams); }
5. In order to stop recursion when someone passes in a uri that does not hit one of our proxies I added a Raise Fault policy to send back a 404. This was added on the "Master Proxy" endpoint default PreFlow.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <RaiseFault async="false" continueOnError="false" enabled="true" name="Raise-Fault-404"> <DisplayName>Raise Fault-404</DisplayName> <Properties/> <FaultResponse> <Set> <Headers/> <Payload contentType="text/plain"/> <StatusCode>404</StatusCode> <ReasonPhrase>NotFound</ReasonPhrase> </Set> </FaultResponse> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> </RaiseFault>
So now I have a proxy with a base path of /v1/abc/def/* that can be accessed using
/v1/abc/def/003q000000RTElQ
/v1/Abc/dEf/003q000000RTElQ
/v1/ABC/DEF/003q000000RTElQ
/v1/aBc/DeF/003q000000RTElQ
and the above uris will point to proxy /v1/abc/def/003q000000RTElQ
If someone was to pass a url that does not match a proxy in our org we would return a 404
It works for us because it is a temporary solution until we can notify all are partners that we will be going to case sensitive uris and we don't lose any of the analytics .
Thanks. This helps.
Great Question & Great Answer, Thank you @jwerra & @crina.cimpian
User | Count |
---|---|
2 | |
1 | |
1 | |
1 | |
1 |