How do I transform the path between the proxy and the target?

Our old backend uses PHP directly so exposes URLs like this…

GET /foo/bar.php?param=mumble

We want to isolate API consumers from that sort of implementation detail (as we will probably be changing the backend in future) so we would like to have…

GET /foo/bar?param=mumble GET /foo/bar.php?param=mumble on the backend.

The documentation explicitly states that putting the following in an AssignMessage policy should acheive the desired result…

<Set>
    <Path>/a/b/c</Path>
</Set>

But no matter where I put it in the flow, Apigee seems to use the public facing path to talk to the backend. I have seen various other examples involving hacking around with target.url and target.copy.pathsuffix but I haven’t found anything which works for me.

Has anybody had to do this recently?

Is the a standard pattern for this

You can either use AssignMessage or a simple JS script policy to change the target URL. You need to have these policies under the TargetEndPoint flow, otherwise you don’t see it work.

Yes, and also, if you want to eliminate the proxy path from the target path, do not forget to set the context variable target.copy.pathsuffix to false. This also must be done in the target flow.

There’s a detailed example in the docs on rewriting a target URL using a JavaScript policy.

Thanks all. It seems that the documentation in this case is not correct and the only way to do it is via target.url, in the target flow as @sudheendra1 suggested (which isn’t very pretty)

<AssignMessage async="false" continueOnError="false" enabled="true" name="Transform-Request">
  <DisplayName>Transform Request</DisplayName>
   ...
  <AssignVariable>
    <Name>target.url</Name>
    <Value>{myhost}/foo/bar.php?{request.querystring}</Value>
  </AssignVariable>    
</AssignMessage>

It does not look like `target.copy.pathsuffix’ is required in this case. It seems to only have an effect for me when I used Set/Path but not when I set the url directly.

@sudheendra1 I am still missing something on changing the proxy path. I added an AssignMessage policy in the PreFlow of the TargetEndPoint:

<AssignMessage async="false" continueOnError="false" enabled="true" name="SetPath">
    <DisplayName>SetPath</DisplayName>
    <Set>
        <Path>/a/b/c</Path>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

But if you look at the trace, the request is still going to the default proxy endpoint:

I then set it by using the and it worked.

<AssignVariable>
    <Name>target.url</Name>
    <Value>http://weather.yahooapis.com/a/b/c?{request.querystring}</Value>
</AssignVariable> 

What is the setting actually doing in the AssignMessage policy then?

Stephen

The behavior you are seeing is as designed.

The path that you set in the AssignMessage policy will get overwritten unless you also set target.copy.pathsuffix to false (as @Dino points out). In the target execution phase target.copy.pathsuffix is checked - if it is true (the default value) then the default path is used regardless of what you had previously done in the AssignMessage policy.

When you change the value of target.url via the AssignVariable policy - Apigee creates a variable (dynamic.target) which essentially acts the same as target.copy.pathsuffix being set to false. The target execution will not overwrite the path when dynamic.target exists.

While this may not be entirely consistent behavior, it is the way the system functions today.

Thanks @David Allen, but that is not working either. Here is my updated policy that sets target.copy.pathsuffix to false:

<AssignMessage async="false" continueOnError="false" enabled="true" name="SetPath">
    <DisplayName>SetPath</DisplayName>
    <Set>
        <Path>/a/b/c</Path>
    </Set>
    <AssignVariable>
        <Name>target.copy.pathsuffix</Name>
        <Value>false</Value>
    </AssignVariable>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

In the trace output, you can see that it is false but the Set/Path still does not take affect.

It looks like there is an open issue in the latest release. This should be working as described above. I have filed the report.

Stephen

The bug mentioned @sgilson still occurs at this date. Will it ever be fixed, or will the documentation be updated to indicate that some other technique should be used?

@arghya das do you know when this fix could be expected?

@Birute Awasthi There are couple of bugs related to this feature. I have already bumped up the priority on those since it seems to be impacting multiple folks. However I don’t have an ETA on the fixes yet.

Thanks @arghya das. Then in the meantime the best is to use a workaround described in the accepted answer on this thread.

Thanks for the update. I look forward to hearing this has been resolved.

While the methods explained here work for a normal endpoint, nothing seems to get the job done when using ScriptTarget instead of HTTPTargetConnection.

@Miguel Balsevich for script target you can set the target.url variable

@arghya das

I followed the documentation for Set Path in AssignMessage Policy which didnt work as expected.But Set Targeturl is working.

But I dont feel its good to hardcode the complete TargetUrl in the Assignmessage Policy rather giving URIPath alone.

Not sure whether the bug still exists.Kindly let me know if the issue has been fixed.

Any fixes for Set Path? target.url approach works for me.!

Any fixes for Set Path? target.url approach works for me.!

Hi,

I personally chose to go with Javascript policy.

if (context.flow=="TARGET_REQ_FLOW") {
    var path = context.getVariable("target.url").slice(0, -1) + context.getVariable("proxy.pathsuffix") + ".php?" + context.getVariable("request.querystring");
    context.setVariable("target.url", path);
    print("path", path);
}