nesty

Http RESTful api implemention on Netty async io

Nesty

Http Restful API framework implemention with Netty

Homepage please visit http://gugemichael.github.io/nesty/

Lastest version

stable with master branch or v0.0.3 branch

develop with v0.0.4 branch

Features

GET, POST, UPDAT, EDELETE

Annotation From
@Header http header
@RequestParam http url query string or http body key value pairs
@PathVariabl http uri path vairable with {path}
@Body http body
Class Type Default value (require = false is set) Description
int,short,long 0 primitive
float,double 0.0d primitive
String null string value
Enum null enum class type
Class null from http body serializer parsed

TODO

Usage

public class SimpleHttpServer {

	public static void main(String[] args) throws ControllerRequestMappingException {
		AsyncServerProvider.builder().port(8080).service(NestyProtocol.HTTP)
			.scanHttpController("org.nesty.example.httpserver.handler").start();
	}
}

public static void main(String[] args) {

	// 1. build httpserver
	NestyServer server = AsyncServerProvider.builder().port(8080).service(NestyProtocol.HTTP);

	// 2. choose http params. this is unnecessary
	server.option(NestyOptions.IO_THREADS, Runtime.getRuntime().availableProcessors())
		  .option(NestyOptions.WORKER_THREADS, 128)
		  .option(NestyOptions.TCP_BACKLOG, 1024)
		  .option(NestyOptions.TCP_NODELAY, true);

	// 3. scan defined controller class with package name
	server.scanHttpController("com.nesty.test.neptune")
		  .scanHttpController("com.nesty.test.billing")
		  .scanHttpController("org.nesty.example.httpserver.handler");

	// 4. start http server
	if (!server.start())
		System.err.println("NestServer run failed");

	try {
		// join and wait here
		server.join();
		server.shutdown();
	} catch (InterruptedException ignored) {
	}
}
@Controller
@RequestMapping("/projects")
public class ServiceController {

	@RequestMapping(value = "/{projectId}", method = RequestMethod.GET)
	public ServiceResponse getProjectById(@PathVariable("projectId") Integer projectId) {
		System.out.println("getProjectById() projectId " + projectId);
		return new ServiceResponse();
	}
}

@Interceptor
public class ServiceInterceptor extends HttpInterceptor {

	@Override
	public boolean filter(final HttpContext context) {

		// count the request
		totalRequest.incrementAndGet();

		// show remote address
		if (!context.getRemoteAddress().isEmpty())
			System.out.println(String.format("request from client %s", context.getRemoteAddress()));

		// reject some one which is not we want
		if (context.getRemoteAddress().equals("192.168.1.1"))
			return false;

		// reject request from agent like curl
		if (context.getHttpHeaders().containsKey("User-Agent"))
			return false;

		// OK
		return true;
	}   

	@Override
	public DefaultFullHttpResponse handler(final HttpContext context, DefaultFullHttpResponse response) {

		// compress content if client support
		if ("gzip".equalsIgnoreCase(context.getHttpHeaders().get("Accept-Encoding"))) {
			// compress the body
			ByteBuf compressContent = compressWithGzip(response.content());
			DefaultFullHttpResponse newResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, compressContent);
			response = newResponse;
		}   

		// add more header
		response.headers().add("NestyInceptor", "Nesty is Good");

		return response;
	}   
}

Please visit https://github.com/gugemichael/nesty/wiki/More-Examples

Threads Model

screenshot

Performance

java -server -Xmx4G -Xms4G -Xmn1536M -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC

Http short connection

Http long connection (Connection: keep-alive)

detail : https://github.com/gugemichael/nesty/wiki/Performance-Detail