Hello All,
I have a http backend that accepts form data. I need to call this endpoint (from service callout policy) before calling the actual target. There is one form field that requires an entire json object as value. I have been trying to populate it using AssignMessage and Javascript policies(using JSON.Stringify) before servicecallout policy, but its not working. The formdata goes as url endcoded string and the target throws 400 bad request error. Not sure how to set it and need help. Attached the Service call out policy XML below. Please check <FormParam name="form-data"> for the data i need to send to backend.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ServiceCallout continueOnError="false" enabled="true" name="SC_Call_Service">
<DisplayName>SC_Call_Service</DisplayName>
<Properties/>
<Request clearPayload="true" variable="formRequest">
<Set>
<FormParams>
<FormParam name="form-data"><![CDATA[{"foo": ["abcd"],"bar": ["efgh"],
"html": "<html><body><h1>Hello</h1></body></html>","platform": "Apigee",
"project": "Apigee","priority": "1"}]]></FormParam>
</FormParams>
<Headers>
<Header name="Authorization">Bearer {token}</Header>
<Header name="Content-Type">multipart/form-data</Header>
</Headers>
</Set>
</Request>
<!-- <Response>calloutResponse</Response>-->
<HTTPTargetConnection>
<Properties/>
<URL>https://dummy.url.com</URL>
</HTTPTargetConnection>
</ServiceCallout>
Solved! Go to Solution.
Yes - the encoding you are describing is happening because Apigee is using content-type application/x-www-form-urlencoded . But I think you want multipart/form-data .
For the former, the data will be posted as a url encoded string. For the latter, it is a multi-part format, with a boundary, and the individual parts do not get encoded.
I see in your ServiceCallout that you are setting the content-type header to multipart/form-data . That in itself does not tell Apigee to "not encode the form params". If you use Set/FormParams, you will always get application/x-www-form-urlencoded , and Apigee will always url-encode the data for each formparam. Later setting the content-type header to something different, does not change that.
ok, so how do you do what you want? To state it clearly, I think you want to use ServiceCallout to send out a request with content-type = multipart/form-data .
As I said above, you cannot "build" the form using Set/FormParams .
You can manually construct a multipart/form-data payload using a JavaScript callout. Example here. or here. The caveat here is that if you use JavaScript, all of the "parts" must have TEXT data types. You cannot include "parts" that represent octet streams like images, PDFs, or other "binary" formats. If you need to send out a multipart/form-data payload that encodes octet-streams, then you need to resort to a Java or Python callout. Here is a Java callout that will help. It has a full readme.
Yes - the encoding you are describing is happening because Apigee is using content-type application/x-www-form-urlencoded . But I think you want multipart/form-data .
For the former, the data will be posted as a url encoded string. For the latter, it is a multi-part format, with a boundary, and the individual parts do not get encoded.
I see in your ServiceCallout that you are setting the content-type header to multipart/form-data . That in itself does not tell Apigee to "not encode the form params". If you use Set/FormParams, you will always get application/x-www-form-urlencoded , and Apigee will always url-encode the data for each formparam. Later setting the content-type header to something different, does not change that.
ok, so how do you do what you want? To state it clearly, I think you want to use ServiceCallout to send out a request with content-type = multipart/form-data .
As I said above, you cannot "build" the form using Set/FormParams .
You can manually construct a multipart/form-data payload using a JavaScript callout. Example here. or here. The caveat here is that if you use JavaScript, all of the "parts" must have TEXT data types. You cannot include "parts" that represent octet streams like images, PDFs, or other "binary" formats. If you need to send out a multipart/form-data payload that encodes octet-streams, then you need to resort to a Java or Python callout. Here is a Java callout that will help. It has a full readme.
I dont have a requirement to send octet steams, but just a json object as value.
Let me try out the javascript example and post back if it works. Thanks both @dchiesa1 and @gonzalezruben for the replies.