Hi All,
I have a proxy that accepts an uploaded file as part of multipart/form-data request. I would like to pass the uploaded file on to a target rest server.
What is the best way to approach this? Currently, I'm using an assign-message policy that copies the incoming request and modifies it into the request that target expects i.e.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AssignMessage async="false" continueOnError="false" enabled="true" name="PassthroughAssign"> <DisplayName>PassthroughAssign</DisplayName> <Properties/> <Copy source="request"> <Headers/> <FormParams/> <Payload/> <Verb/> </Copy> <Remove> <Headers> <Header name="jwt"/> </Headers> </Remove> <Add> <Headers> <Header name="x-facade-token">XXXX-XXXXXXXXXXX-XXXXXXXXXXXX</Header> </Headers> </Add> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <AssignTo createNew="true" transport="http" type="request">target.passthru</AssignTo> </AssignMessage>
...and then I use a callout policy to call the target rest service i.e.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ServiceCallout async="false" continueOnError="false" enabled="true" name="Call-File-Upload-Service"> <DisplayName>Call File Upload Service</DisplayName> <Properties/> <Request clearPayload="false" variable="target.passthru"> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> </Request> <Response>openTextResponse</Response> <HTTPTargetConnection> <Properties> <Property name="success.codes">1xx,2xx,3xx,4xx,5xx</Property> </Properties> <URL>http://{ot.host}/{ot.base.path}/workspace/{target.clientId}/{target.workspacePath}</URL> </HTTPTargetConnection> </ServiceCallout>
However, the target server responds with an error 500 - "unexpected end of input".
Is there something I'm doing obviously wrong? Should I handle this differently?
Solved! Go to Solution.
After much wrangling, I managed to solve the issue - actually a couple of issues
The quick one to resolve (after getting a view of the request sent out) was the fact that my content body was missing. This is because my initial <copy> from my question needed to look more like this:
<Copy source="request"> <Headers/> <Payload>true</Payload> <Verb>true</Verb> </Copy>
I eventually shifted away from the copy and built a new request (due to a change of requirements)
The more difficult issue to resolve (and having a more annoying resolution) was that content length was being calculated incorrectly. The answer lay in my AssignMessage policy which looked as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AssignMessage name="PassthroughAssign"> <DisplayName>PassthroughAssign</DisplayName> <Set> <Headers> <Header name="x-facade-token">XXXXXXXXXXXXXXXXXXX</Header> <Header name="Content-Type">multipart/form-data; boundary={boundary}</Header> <Header name="content-length">{multipartLength}</Header> </Headers> <Verb>POST</Verb> <Payload variablePrefix="@" variableSuffix="#"> @multipart# </Payload> </Set> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <AssignTo createNew="true" transport="http" type="request">target.passthru</AssignTo> </AssignMessage>
I found out that the formatting inside the <Payload> tag was actually being added to the payload. i.e. apigee was sending "\n {contents of multipart}". So payload ended up larger than my contentLength header. Also, because there were spaces before the payload boundary, the target server would reject the message.
I changed the <Payload> XML to look as follows:
<Payload variablePrefix="@" variableSuffix="#">@multipart#</Payload>
That resolved my issues. Thanks for your assistance @Dino