Not Able To Update proxy.pathsuffix Using Java Callout Policy

Requirement:

I need to update proxysuffix dynamically. Need to do this, as I need to append this parent information in the target suffix before redirection.

More Details about the usecase:

Client will be calling apigee with baseuri/pathsuffix, before this call is redirected to target I need to modify proxy path suffix to something like:

-----> proxy.pathsuffix = /parent/{id}/proxy.pathsuffix

My Approach - Not Working

Using a java call out policy as I need to do a bunch of steps to get this parent information, after which I append this in proxy.pathsuffix, like this:

...
somecode to get and update proxySuffix
...
messageContext.setVariable("proxy.pathsuffix", proxySuffix);
But when I check traces, proxysuffix is not updated. It shows not equal to symbol in front of updated suffix:

Screenshot 2021-07-26 at 6.21.11 PM.png

Solved Solved
0 11 442
2 ACCEPTED SOLUTIONS

yes, the flow variable in my illustration would be dynamic-path-to-use. I was assuming you were not selecting a HOST, but merely a path. The configuration example I showed:

 

 

<URL>https://my-target.com/{dynamic-path-to-use}</URL>

 

 

...employs a "message template". The value of the URL is determined dynamically at runtime, by replacing the variable reference in curly brackets with the actual value. It implies that you would have needed to set the variable dynamic-path-to-use at some point prior to the connection being initiated to the target, eg at some point in the proxy or target request flow. I can imagine setting it within a JS step, based on some routing table that you get dynamically, from an external system.

If setting the path is not sufficient, in other words if you need to select the target host too, and it's completely dynamic, then you need to set the target.url variable, and you need to do that within the target request flow.

 

View solution in original post

Yes that’s what I mean. Standard Java practice. Nothing specific to Apigee. Use a cache that can tolerate concurrent access. 

View solution in original post

11 REPLIES 11

Hi Shubham

You cannot update proxy.pathsuffix. It is a read-only variable.

proxy-pathsuffix-is-readonly.png

If you look in the Trace, you can see a small indication that your attempt to update proxy.pathsuffix has failed.  The equals sign with a strike through it. 

write-failed.png 

If you want to affect the URL path that the target receives, you have a couple options. 

  1.  update target.url. That variable is writeable. 
    It accepts the full URL for the target. You must write it in the context of the target request flow.  Not in the proxy request flow.  If you update it in the proxy request flow, the update of target.url will succeed, but your update will get overwritten at the initiation of the target request flow, so you won't get the results you seek.
    Keep in mind that Search the archives here, there are lot of examples showing how people update this variable. 
  2. Use a dynamic URL "template" in the target endpoint. 
    To use this, you would need to set target.copy.pathsuffix to false, and then use a template in the URL. 
    <AssignMessage name='AM-Disable-Copy-Pathsuffix'>
      <AssignVariable>
        <Name>target.copy.pathsuffix</Name>
        <Value>false</Value>
      </AssignVariable>
    </AssignMessage>
    ​

    And then in the target: 

    <TargetEndpoint name="target-1">
      <PreFlow name="PreFlow">
        <Request>
          <Step>
            <Name>AM-Disable-Copy-Pathsuffix</Name>
          </Step>
        </Request>
        <Response/>
      </PreFlow>
      <PostFlow name="PostFlow">
        <Request/>
        <Response/>
      </PostFlow>
      <Flows/>
      <HTTPTargetConnection>
        <SSLInfo>
           ...
        </SSLInfo>
        <URL>https://my-target.com/{dynamic-path-to-use}</URL>
      </HTTPTargetConnection>
    </TargetEndpoint>
      




Ok, I see. Based on the two approaches you suggested, I feel there are still concerns with respect to my requirements. I'll try to capture the details below.

I need to route to different targets based on conditions around proxy suffix pattern. There can be large number of such target url's in the system. 

Requirement is to just update suffix and keep on routing to a specific target based on route conditions.

Approach 1

There is no targetsuffix or similar attribute which I can configure and base uri can be picked based on conditional routes defined in proxy. Right now I keep them configured as different targets and keep on creating new targets as needed.

example:

Target 1: https://my-target-1.com

Target 2: https://my-target-2.com

...

Target n: https://my-target-n.com

 Approach 2

You mentioned the following:

<URL>https://my-target.com/{dynamic-path-to-use}</URL>

in this case {dynamic-path-to-use} is a new flow variable? not clear on this approach completely. 

yes, the flow variable in my illustration would be dynamic-path-to-use. I was assuming you were not selecting a HOST, but merely a path. The configuration example I showed:

 

 

<URL>https://my-target.com/{dynamic-path-to-use}</URL>

 

 

...employs a "message template". The value of the URL is determined dynamically at runtime, by replacing the variable reference in curly brackets with the actual value. It implies that you would have needed to set the variable dynamic-path-to-use at some point prior to the connection being initiated to the target, eg at some point in the proxy or target request flow. I can imagine setting it within a JS step, based on some routing table that you get dynamically, from an external system.

If setting the path is not sufficient, in other words if you need to select the target host too, and it's completely dynamic, then you need to set the target.url variable, and you need to do that within the target request flow.

 

Thanks for the help. This should work for our scenario.

I am trying to do something like the following in js policy:

String targetUrl = (String) messageContext.getVariable("target.url");
      messageContext.setVariable("target.url", targetUrl + updatedSuffix);

This is looking promising as it is picking base target.url which is already a predefined target and I can also modify suffix as per my needs. Only issue I see here is that I need to add this policy in all the targets pre flow. Is there any other way to achieve this?

There is a pre-target "flow hook" that might suit your purposes.

pre-target-flow-hook.png

There are two concepts you need to understand: flow hook, and shared flow.  A Flow Hook provides a way for admins to specify a sharedflow that always executes for every API proxy.   A sharedflow is a sequence of zero or more policies.  

So what you could do is code that JS policy, stuff it into a Sharedflow, and then configure that sharedflow on the pre-target flowhook.  I think that ought to allow you to avoid the need to attach the same policy to all the targets in all the API proxies.

See if it helps...

@dchiesa1  One more question. Can I maintain an in-memory cache using a jar in Java Callout policy.

This policy will be responsible for making some external calls, and a bunch of other steps along with maintaining an in memory cache in order to improve performance.

I am not able to get any reference to this in Java Callout documentation.

Yes, you can allocate and maintain a cache in a Java Callout. The callout class is instantiated once, and then invoked with multiple threads for each request. So your cache object should accommodate multi-threaded read/write access. You may need to perform appropriate locking to make that happen.

When you say locking, you mean locking cache data structure due to multiple threads trying to write on the same cache data structure, is that right?

Also, is there any document which tries to capture this information.

Yes that’s what I mean. Standard Java practice. Nothing specific to Apigee. Use a cache that can tolerate concurrent access.