Search code examples
restpostamazon-ec2amazon-web-servicesrestlet

AWS EC2 HTTP Post Content Size Limit


I am communicating via REST to a program on my EC2 instance and everything runs fine until the size of the JSON I send via a POST request reaches ~20KB. I don't have these issues when I run the code on a local machine webserver, however when I upload the code to the EC2, the packets never reach the server.

Is amazon blocking packets over ~20KB to prevent DoS attacks? If so how can I remove this feature. I need to be able to POST at least 500KB of JSON to my instance.

I am running Restlet 2.1 and using Google GSON 2.2.2 so to run the code below you need the org.restlet.jar and gson.jar from the previous links.

This code launches a restlet server on the EC2 instance:

import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.routing.Router;
import org.restlet.service.LogService;

public class StringApplication extends Application {
    public static final int PORT = 8005;
    public static void main(String[] args) throws Exception {

        Component component = new Component();
        component.setLogService(new LogService(false));

        component.getDefaultHost().attach(new StringApplication());

        component.getServers().add(Protocol.HTTP, PORT);
        component.start();
    }

    @Override
    public synchronized Restlet createInboundRoot() {
        Router router = new Router(getContext());
        router.attachDefault(StringResource.class);
        return router;
    }
}    

Here is the code for my restlet resource

import java.lang.reflect.Type;
import java.util.ArrayList;

import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class StringResource extends ServerResource {
    private static ArrayList<String> strings = new ArrayList<String>();

    @Get
    public String getStrings() {
    Gson gson = new Gson();
    String output = gson.toJson(strings);
    return output;
    }

    @Post
    public void postStrings(String input) {
        Gson gson = new Gson();
        Type collectionType = new TypeToken<ArrayList<String>>() {
        }.getType();
        strings = gson.fromJson(input, collectionType);
    }
}

and finally, here is the code I created to test the different packet sizes. With count = 100 (10KB) it works, with count = 1000 (100KB) it times out.

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;

import org.restlet.Client;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Protocol;
import org.restlet.representation.Representation;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class StringDemo {

    private static final int COUNT = 1000;
    private static final String STRING = "THIS IS MY VERY LONG STRING AND IT IS FUN TO READ";
    private static final String SERVER_ADDRESS = "http://localhost:" + StringApplication.PORT;

    public static void main(String[] args) throws IOException {
        Gson gson = new Gson();
        Client client = new Client(Protocol.HTTP);
        Request request = new Request();
        request.setResourceRef(SERVER_ADDRESS);
        request.setMethod(Method.POST);
        ArrayList<String> strings = generateStrings();
        String json = gson.toJson(strings);
        request.setEntity(json, MediaType.APPLICATION_JSON);

        System.out.println("JSON bytesize " + json.length() * Character.SIZE / Byte.SIZE);
        Response handle = client.handle(request);
        Representation entity = handle.getEntity();

        if (handle.getStatus().isSuccess()) {
            System.out.println("Successfully uploaded strings");
        } else {
            System.out.println(entity != null ? entity.getText() : "no response from server");
        }

        request = new Request();
        request.setResourceRef(SERVER_ADDRESS);
        request.setMethod(Method.GET);

        handle = client.handle(request);
        entity = handle.getEntity();

        if (handle.getStatus().isSuccess()) {
            Type collectionType = new TypeToken<ArrayList<String>>() {
            }.getType();
            strings = gson.fromJson(entity.getReader(), collectionType);
            System.out.println("Received " + strings.size() + " strings");
        } else {

            System.out.println(entity != null ? entity.getText() : "no response from server");
        }

    }

    private static ArrayList<String> generateStrings() {
        ArrayList<String> strings = new ArrayList<String>(COUNT);
        for (int i = 0; i < COUNT; i++) {
            strings.add(STRING);
        }
        return strings;
    }

}

You must change the SERVER_ADDRESS to the EC2 instance you run the code on


Solution

  • The issue goes away when you use one of the larger instances. The issues appear to be related to the default configuration of the free tier machines that amazon offers.