wso2 am gateway forwarding of multipart/form-data post requests
<p>I am using a demo API which receives a file and note as multipart/form-data input and displays the content of the file and the note. Here is a sample HTML which runs the API correctly:</p>

<pre><code>&lt;html&gt;   
  &lt;body&gt;
    &lt;FORM action="http://cgi-lib.berkeley.edu/ex/fup.cgi" method="post"&gt;
      &lt;P&gt;Choose file: &lt;INPUT type="file" name="upfile"&gt;
      &lt;p&gt;Note: &lt;INPUT type="text" name="note"&gt;
      &lt;p&gt;&lt;INPUT type="submit" value="Send"&gt; 
    &lt;/FORM&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>Now I'm trying to created a managed API in the WSO2 APIM publisher. Below are the parameters I filled in:</p>

<p><a href="https://i.stack.imgur.com/vsUo8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vsUo8.png" alt="enter image description here"></a></p>

<p>I'm replacing the action of the HTML to go through the API I added:</p>

<pre><code>&lt;FORM action="http://ec2-52-48-93-41.eu-west-1.compute.amazonaws.com:8280/test" method="post"&gt;
</code></pre>

<p>But now when I run the HTML I get the following error from the API:</p>

<pre><code>cgi-lib.pl: Unknown Content-type: application/x-www-form-urlencoded; charset=UTF-8
</code></pre>

<p>Seems like the WSO2 gateway forwarded the request as application/x-www-form-urlencoded rather than as mulipart/form-data.</p>

<p>Based on the following discussion <a href="https://stackoverflow.com/questions/29025525/multipart-form-data-file-upload-using-wso2-api-manger">multipart form data file upload using WSO2 API manger ?</a> I tried to comment out</p>

<pre><code>   &lt;messageFormatter contentType="multipart/form-data"
        class="org.apache.axis2.transport.http.MultipartFormDataFormatter"/&gt;
   &lt;messageBuilder contentType="multipart/form-data"
        class="org.apache.axis2.builder.MultipartFormDataBuilder"/&gt;
</code></pre>

<p>And replace them with</p>

<pre><code> &lt;messageFormatter contentType="multipart/form-data" 
     class="org.wso2.carbon.relay.ExpandingMessageFormatter"/&gt; 
 &lt;messageBuilder contentType="multipart/form-data" 
     class="org.wso2.carbon.relay.BinaryRelayBuilder"/&gt;
</code></pre>

<p>Then restarted the server, but it did not cause any impact.</p>

<p>Any ideas will be appreciated.</p>

<p>Some log messages that I collected. The target API is different, but it is also a multipart/form-data API which dumps whatever it receives. </p>

<p>The incoming request does have content-type multipart/form-data, with content-length of 292 </p>

<pre><code>DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; POST /test/1.0.0 HTTP/1.1 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Host: ec2-52-48-93-41.eu-west-1.compute.amazonaws.com:8280 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Connection: keep-alive {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Content-Length: 292 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Cache-Control: max-age=0 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Origin: null {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Upgrade-Insecure-Requests: 1 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqwBdAwOnlDYeHNNR {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Accept-Encoding: gzip, deflate {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Accept-Language: en-US,en;q=0.8,he;q=0.6 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &gt;&gt; Cookie: region3_registry_menu=visible; region1_manage_menu=visible; region1_identity_menu=visible; menuPanel=visible; menuPanelType=main; csrftoken=n1g69f3slt1d90qvtaa28rtm1b {org.apache.synapse.transport.http.headers}
</code></pre>

<p>The outgoing request does not have content-type:</p>

<pre><code>DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; POST /sample2/api/company/upload HTTP/1.1 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Cookie: region3_registry_menu=visible; region1_manage_menu=visible; region1_identity_menu=visible; menuPanel=visible; menuPanelType=main; csrftoken=n1g69f3slt1d90qvtaa28rtm1b {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Origin: null {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Cache-Control: max-age=0 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Upgrade-Insecure-Requests: 1 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Accept-Encoding: gzip, deflate {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Accept-Language: en-US,en;q=0.8,he;q=0.6 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Transfer-Encoding: chunked {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Host: localhost:8080 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; Connection: Keep-Alive {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &gt;&gt; User-Agent: Synapse-PT-HttpComponents-NIO {org.apache.synapse.transport.http.headers}
</code></pre>

<p>Naturally, the incoming response has HTTP 415, unsupported media:</p>

<pre><code>DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &lt;&lt; HTTP/1.1 415 Unsupported Media Type {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &lt;&lt; Server: Apache-Coyote/1.1 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &lt;&lt; Content-Length: 0 {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1 &lt;&lt; Date: Mon, 28 Mar 2016 13:53:05 GMT {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; HTTP/1.1 415 Unsupported Media Type {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; Access-Control-Allow-Origin: * {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; Access-Control-Allow-Methods: POST {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; Access-Control-Allow-Headers: authorization,Access-Control-Allow-Origin,Content-Type {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; Date: Mon, 28 Mar 2016 13:53:05 GMT {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; Transfer-Encoding: chunked {org.apache.synapse.transport.http.headers}
DEBUG {org.apache.synapse.transport.http.headers} -  http-incoming-1 &lt;&lt; Connection: keep-alive {org.apache.synapse.transport.http.headers}
</code></pre>

<p>Also worth loading is the synapse of the API:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;api xmlns="http://ws.apache.org/ns/synapse"
     name="admin--test"
     context="/test/1.0.0"
     version="1.0.0"
     version-type="context"&gt;
   &lt;resource methods="POST" url-mapping="/*" faultSequence="fault"&gt;
      &lt;inSequence&gt;
         &lt;filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION"&gt;
            &lt;then&gt;
               &lt;property name="api.ut.backendRequestTime"
                         expression="get-property('SYSTEM_TIME')"/&gt;
               &lt;send&gt;
                  &lt;endpoint name="admin--test_APIproductionEndpoint_0"&gt;
                     &lt;http uri-template="http://localhost:8080/sample2/api/company/upload"/&gt;
                  &lt;/endpoint&gt;
               &lt;/send&gt;
            &lt;/then&gt;
            &lt;else&gt;
               &lt;sequence key="_sandbox_key_error_"/&gt;
            &lt;/else&gt;
         &lt;/filter&gt;
      &lt;/inSequence&gt;
      &lt;outSequence&gt;
         &lt;class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"/&gt;
         &lt;send/&gt;
      &lt;/outSequence&gt;
   &lt;/resource&gt;
   &lt;handlers&gt;
      &lt;handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler"&gt;
         &lt;property name="apiImplementationType" value="ENDPOINT"/&gt;
      &lt;/handler&gt;
      &lt;handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/&gt;
      &lt;handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.APIThrottleHandler"&gt;
         &lt;property name="policyKey" value="gov:/apimgt/applicationdata/tiers.xml"/&gt;
         &lt;property name="policyKeyApplication"
                   value="gov:/apimgt/applicationdata/app-tiers.xml"/&gt;
         &lt;property name="policyKey" value="gov:/apimgt/applicationdata/tiers.xml"/&gt;
         &lt;property name="policyKeyApplication"
                   value="gov:/apimgt/applicationdata/app-tiers.xml"/&gt;
         &lt;property name="id" value="A"/&gt;
         &lt;property name="policyKeyResource"
                   value="gov:/apimgt/applicationdata/res-tiers.xml"/&gt;
      &lt;/handler&gt;
      &lt;handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler"/&gt;
      &lt;handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtGoogleAnalyticsTrackingHandler"&gt;
         &lt;property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/&gt;
      &lt;/handler&gt;
      &lt;handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/&gt;
   &lt;/handlers&gt;
&lt;/api&gt;
</code></pre>