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
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.