Friday, December 30, 2016

Disable Chunking in WSO2 API Manager

By default in WSO2 API Manager, chunking is enabled. You can check it by enabling wire logs in API Manager. If you send a "PUT" or "POST" request, you will see "Transfer-Encoding: chunked" header like below in outgoing request.

[2016-12-30 11:57:27,125] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "POST /am/sample/pizzashack/v1/api/order HTTP/1.1[\r][\n]"
[2016-12-30 11:57:27,125] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Accept-Language: en-US,en;q=0.8[\r][\n]"
[2016-12-30 11:57:27,125] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Accept-Encoding: gzip, deflate[\r][\n]"
[2016-12-30 11:57:27,125] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Origin: https://localhost:9443[\r][\n]"
[2016-12-30 11:57:27,125] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Type: application/json; charset=UTF-8[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Accept: application/json[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Transfer-Encoding: chunked[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Host: localhost:9443[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Connection: Keep-Alive[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "a4[\r][\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "{[\n]"
[2016-12-30 11:57:27,126] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "customerName": "string",[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "delivered": true,[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "address": "string",[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "pizzaType": "string",[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "creditCardNumber": "string",[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "quantity": 0,[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "orderId": 0[\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "}[\r][\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "0[\r][\n]"
[2016-12-30 11:57:27,127] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"

But sometimes backends don't support chunking. In such cases you have to disable chunking. For that there are two ways.

Method 01 :

If you want to disable chunking in all APIs,  you can add highlighted line to <inSequence> of velocity.xml in <APIM_HOME>/repository/resources/api_templates/

<inSequence>

## check and set response caching
#if($responseCacheEnabled)
<cache scope="per-host" collector="false" hashGenerator="org.wso2.caching.digest.REQUESTHASHGenerator" timeout="$!responseCacheTimeOut">
    <implementation type="memory" maxSize="500"/>
</cache>
#end
<property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/>
##############  define the filter based on environment type production only, sandbox only , hybrid ############

#if(($environmentType == 'sandbox') || ($environmentType =='hybrid' && !$endpoint_config.get("production_endpoints") ))
#set( $filterRegex = "SANDBOX" )
#else
#set( $filterRegex = "PRODUCTION" )
#end
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/> 
#if($apiStatus != 'PROTOTYPED')
<filter source="$ctx:AM_KEY_TYPE" regex="$filterRegex">
    <then>
        #end        
        #if(($environmentType == 'sandbox') || ($environmentType =='hybrid' && ! $endpoint_config.get("production_endpoints") ))
        #draw_endpoint( "sandbox" $endpoint_config )
        #else
        #draw_endpoint( "production" $endpoint_config )
        #end
        #if($apiStatus != 'PROTOTYPED')
    </then>
    <else>
        #if($environmentType !='hybrid')
        <payloadFactory>
            <format>
                <error xmlns="">
                    #if($environmentType == 'production')
                    <message>Sandbox Key Provided for Production Gateway</message>
                    #elseif($environmentType == 'sandbox')
                    <message>Production Key Provided for Sandbox Gateway</message>
                    #end
                </error>
            </format>
        </payloadFactory>
        <property name="ContentType" value="application/xml" scope="axis2"/>
        <property name="RESPONSE" value="true"/>
        <header name="To" action="remove"/>
        <property name="HTTP_SC" value="401" scope="axis2"/>
        <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
        <send/>
        #else
        #if($endpoint_config.get("production_endpoints") && $endpoint_config.get("sandbox_endpoints"))
        #draw_endpoint( "sandbox" $endpoint_config )
        #elseif($endpoint_config.get("production_endpoints"))
        <sequence key="_sandbox_key_error_"/>
        #elseif($endpoint_config.get("sandbox_endpoints"))
        <sequence key="_production_key_error_"/>
        #end
        #end
    </else>
</filter>
#end
</inSequence>

Then restart the server. Changing this file will affect future APIs created in API manager. If you want to disable chunking in old APIs as well, you have to republish old APIs.

Method 02 :
If you want to disable chunking only for certain APIs, you can use a custom mediation extension.

1. Create a sequence to disable chunking like below and save it in the file system.


<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse"
          name="chunk-disable-sequence">
        <property name="DISABLE_CHUNKING" value="true" scope="axis2" />
</sequence>

2. Edit the API from API Publisher.

3. Go to "Implement" Tab and check "Enable Message Mediation".

4. Upload above created sequence to "In Flow" under "Message Mediation Policies"

5. Then save API.

Now chunking is disabled for that particular API.

If you send a "PUT" or "POST" request,  you will see "Content-Length" header instead of "Transfer-Encoding: chunked" header like below in outgoing request.

[2016-12-30 13:22:18,877] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "POST /am/sample/pizzashack/v1/api/order HTTP/1.1[\r][\n]"
[2016-12-30 13:22:18,877] DEBUG - wire HTTPS-Sender I/O dispatcher-1 <<<< "Accept-Language: en-US,en;q=0.8[\r][\n]"
[2016-12-30 13:22:18,877] DEBUG - wire HTTPS-Sender I/O dispatcher-1  "Accept-Encoding: gzip, deflate[\r][\n]"
[2016-12-30 13:22:18,877] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Origin: https://localhost:9443[\r][\n]"
[2016-12-30 13:22:18,877] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Type: application/json; charset=UTF-8[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Accept: application/json[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Length: 135[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Host: localhost:9443[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Connection: Keep-Alive[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2016-12-30 13:22:18,878] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "{"customerName":"string","delivered":true,"address":"string","pizzaType":"string","creditCardNumber":"string","quantity":0,"orderId":0}"
[2016-12-30 13:22:19,084] DEBUG - wire HTTPS-Sender I/O dispatcher-1 >> "HTTP/1.1 201 Created[\r][\n]"


2 comments:

  1. I just wanted to let you know, this post was useful for me :)

    ReplyDelete