ok I see what you’re doing, maybe where it’s going wrong. Thanks for the screenshots.
The Flow in the Apigee Edge proxy endpoint is a key concept. Let’s make sure you’re clear on how it works. The image that depicts how flows work is:
The image that depicts the flows is:
As you can see there are 4 combinations. In the order in which they execute, they are:
- proxy request
- target request
- target response
- proxy response
But it’s not quite as simple as that. In Apigee Edge the proxy and the target each have a preflow, zero or more “conditional flows”, and a “postflow”. They execute in that order. Therefore each of the above 4 combinations is really 3, giving 12 attachment points in total. The order is like this:
-
proxy request
- preflow
- conditional flow
- postflow
-
target request
- preflow
- conditional flow
- postflow
-
target response
- preflow
- conditional
- postflow
-
proxy response
- preflow
- conditional
- postflow
In your XML, which looks like this:
…you have two flows. At most ONE of those flows will execute.
The first flow, the “/login” flow, will execute if the condition evaluates to true given the inbound (inbound to Apigee Edge) request. Basically if the inbound is a POST to /login, then… that flow executes; the other flow will not. If the inbound request is a POST and the path matches “/devices/*/sendRawData”, then the 2nd flow will execute, and not the first. If neither of those conditions evaluates to true, then neither flow executes.
I think what you want is a condition something like this:
<Flows>
<Flow name='f1'>
<Condition>(proxy.pathsuffix MatchesPath "/scantoprint") and (request.verb = "POST")</Condition>
<Request>... </Request>
<Response>...</Response>
</Flow>
...
</Flows>
Basically that says “the inbound request ought to be a POST and the path is /scantoprint” . THAT is the interface you want to expose to the callers. That acts as the facade for the steps you outlined in your post.
And under the Request element , you want to post out to the login element. You would do this with a ServiceCallout policy configured like so:
<ServiceCallout name='SC-1'>
<Request>
<Set>
<Headers>
<Header name='content-type'>application/x-www-form-urlencoded</Header>
</Headers>
<FormParams>
<FormParam name='username'>{request.form.username}</FormParam>
<FormParam name='password'>{request.form.password}</FormParam>
</FormParams>
<Verb>POST</Verb>
</Set>
</Request>
<Response>loginResponse</Response>
<HTTPTargetConnection>
<SSLInfo>
<Enabled>true</Enabled>
</SSLInfo>
<Properties>
<Property name='success.codes'>2xx, 3xx, 4xx, 5xx</Property>
</Properties>
<URL>https://myserver/PPME_API_Access_proxy/login</URL>
</HTTPTargetConnection>
</ServiceCallout><br>
What’s going on there? That thing is saying "take the username and password from the inbound request form parameters, and create a NEW outbound request to a login endpoint. Save the response into a message variable called loginResponse.
To execute that ServiceCallout, You would need to configure your flow like this:
<Flows>
<Flow name='f1'>
<Condition>(proxy.pathsuffix MatchesPath "/scantoprint") and (request.verb = "POST")</Condition>
<Request>
<Step>
<Name>SC-1</Name>
</Step>
...
</Request>
<Response>...</Response>
</Flow>
...
</Flows>
Then your extraction is:
<ExtractVariables name="Extract-Cookie">
<DisplayName>Extract-Cookie</DisplayName>
<Header name="Set-Cookie">
<Pattern ignoreCase="false">SESSION={cookie};*</Pattern>
</Header>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<Source>loginResponse</Source>
<VariablePrefix>login</VariablePrefix>
</ExtractVariables>
Notice the source is loginResponse, which is the thing returned from that ServiceCallout. And this policy fits in right after SC-1 in the flow:
<Flows>
<Flow name='f1'>
<Condition>(proxy.pathsuffix MatchesPath "/scantoprint") and (request.verb = "POST")</Condition>
<Request>
<Step>
<Name>SC-1</Name>
</Step>
<Step>
<Name>Extract-Cookie</Name>
</Step>
...
</Request>
<Response>...</Response>
</Flow>
...
</Flows>
ok, now what you want to do is dynamically construct the URL for the “target”. In Apigee Edge you can do this by setting the target.url context variable. You can do that with JavaScript policy, like this:
var printerSN = context.getVariable('request.formparam.printersn');
context.setVariable('target.url',
'https://PPME_server/devices/' + printerSN + '/sendRawData');
But you need to take care when setting it - that variable gets reset at the inception of the target flow. So that JS policy needs to run in the target. This looks like this:
<TargetEndpoint name="sendraw">
<Description/>
<FaultRules/>
<PreFlow name="PreFlow">
<Request>
<Step>
<Name>JS-SetTargetUrl</Name>
</Step>
</Request>
<Response/>
</PreFlow>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
<Flows/>
<HTTPTargetConnection>
<Properties/>
<URL>https://will-be-overwrtitten.com/</URL>
</HTTPTargetConnection>
</TargetEndpoint>