Skip to content

thiagorigonatti/sleeker

Repository files navigation

SLEEKER v0.0.10

TEST

public class Test {
    public static void main(String[] args) throws Exception {

        // Creating instances of Http1 and Http2 handler classes.
        final Http1ExampleHandler http1ExampleHandler = new Http1ExampleHandler();
        final Http2ExampleHandler http2ExampleHandler = new Http2ExampleHandler();

        //Creating Cors instance with origin, allowed methods, allowed headers, sending cookies, and cache time.
        final Cors cors = new Cors("http://localhost:54321",
                Set.of(HttpMethod.GET, HttpMethod.POST),
                Set.of(HttpHeaderNames.AUTHORIZATION), true, 3600L);

        // Creates a builder object for SleekerServer.
        new SleekerServer.Builder()
                // Adds an HTTP context, with an endpoint, a handler that will process the request,
                // and supported HTTP methods.
                .addHttp1Context("/http1_get_post", http1ExampleHandler,
                        HttpMethod.GET,
                        HttpMethod.POST)

                .addHttp1Context("/http1_put_patch_delete", http1ExampleHandler,
                        HttpMethod.PUT,
                        HttpMethod.PATCH,
                        HttpMethod.DELETE)

                .addHttp1Context("/http1_head", http1ExampleHandler, HttpMethod.HEAD)

                // Adds CORS for both http1 and http2
                .withCors(cors)

                // Configures SSL with cert file and private key.
                .withSsl(Path.of("localhost-cert.pem"), Path.of("localhost-key.pem"))

                .addHttp2Context("/http2_get", http2ExampleHandler, HttpMethod.GET)
                .addHttp2Context("/http2_post", http2ExampleHandler, HttpMethod.POST)

                // Builds a SleekerServer object.
                .build()

                // Starts the server with the address and port, as well as the type of I/O used.
                .startServer(new InetSocketAddress("localhost", 8080), ServerIo.TYPE_IOURING);
    }
}
2025-09-29 10:00:01 [INFO ] [main] m.t.s.c.SleekerServer: Sleeker server running at: http://localhost:8080

HTTP1.1 HANDLER

public class Http1ExampleHandler extends Http1SleekHandler {

    private static final Logger LOGGER = LogManager.getLogger(Http1ExampleHandler.class);
    private final StringBuilder stringBuilder = new StringBuilder();

    @Override
    protected void handleGET(Http1Request http1Request, Http1Response http1Response) {

        stringBuilder.setLength(0);

        stringBuilder
                .append("\r\n")
                .append("--------HTTP/1.1 REQUEST--------")
                .append("\r\n")
                .append("ip_port: ").append(http1Request.remoteAddress().getHostString())
                .append(":").append(http1Request.remoteAddress().getPort())
                .append("\r\n")
                .append("method: ").append(http1Request.method())
                .append("\r\n")
                .append("path: ").append(http1Request.path())
                .append("\r\n");

        for (Map.Entry<String, String> header : http1Request.headers()) {
            stringBuilder.append(header.getKey()).append(": ").append(header.getValue())
                    .append("\r\n");
        }

        http1Response.addHeader(HttpHeaderNames.CONTENT_TYPE, ContentType.TEXT_PLAIN_UTF8.getMimeType());
        http1Response.setBody("Hello from HTTP/1.1");
        http1Response.reply(HttpResponseStatus.OK);

        stringBuilder
                .append(http1Request.body())
                .append("\r\n")
                .append("--------------------------------")
                .append("\r\n");

        LOGGER.info(stringBuilder);
    }

    @Override
    protected void handlePOST(Http1Request http1Request, Http1Response http1Response) throws JsonProcessingException {

        if (http1Request.body().isEmpty() || http1Request.body().isBlank()) {

            throw new HttpSleekException.BaseBuilder<>()
                    .contentType(ContentType.APPLICATION_JSON_UTF8)
                    .httpResponseStatus(HttpResponseStatus.BAD_REQUEST)
                    .responseMessage(new ObjectMapper().writeValueAsString(Map.of("errorMessage", "Body cannot be empty or blank")))
                    .build();
        }

        stringBuilder.setLength(0);

        stringBuilder
                .append("\r\n")
                .append("--------HTTP/1.1 REQUEST--------")
                .append("\r\n")
                .append("ip_port: ").append(http1Request.remoteAddress().getHostString())
                .append(":").append(http1Request.remoteAddress().getPort())
                .append("\r\n")
                .append("method: ").append(http1Request.method())
                .append("\r\n")
                .append("path: ").append(http1Request.path())
                .append("\r\n");

        for (Map.Entry<String, String> header : http1Request.headers()) {
            stringBuilder.append(header.getKey()).append(": ").append(header.getValue())
                    .append("\r\n");
        }

        http1Response.addHeader(HttpHeaderNames.CONTENT_TYPE, ContentType.TEXT_PLAIN_UTF8.getMimeType());
        http1Response.setBody("Saved! (HTTP/1.1)");
        http1Response.reply(HttpResponseStatus.CREATED);

        stringBuilder
                .append(http1Request.body())
                .append("\r\n")
                .append("--------------------------------")
                .append("\r\n");

        LOGGER.info(stringBuilder);
    }
}

HTTP1.1 REQUEST

2025-10-16 21:07:37 [INFO ] [pool-2-thread-2] m.t.s.a.Http1ExampleHandler:
--------HTTP/1.1 REQUEST--------
ip_port: 127.0.0.1:38010
method: POST
path: /http1_get_post
Content-Type: application/json
User-Agent: PostmanRuntime/7.48.0
Accept: */*
Postman-Token: 88ac587d-fe03-4fc3-bca1-e5a1e10ef087
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 37
{
"id": "abc",
"level": 123
}
--------------------------------

HTTP2 HANDLER

public class Http2ExampleHandler extends Http2SleekHandler {

    private static final Logger LOGGER = LogManager.getLogger(Http2ExampleHandler.class);
    private final StringBuilder stringBuilder = new StringBuilder();

    @Override
    protected void handleGET(Http2Request http2Request, Http2Response http2Response) {

        stringBuilder.setLength(0);

        stringBuilder
                .append("\r\n")
                .append("--------HTTP/2 REQUEST--------")
                .append("\r\n")
                .append("ip_port: ").append(http2Request.remoteAddress().getHostString())
                .append(":").append(http2Request.remoteAddress().getPort())
                .append("\r\n")
                .append("method: ").append(http2Request.method())
                .append("\r\n")
                .append("path: ").append(http2Request.path())
                .append("\r\n");

        for (Map.Entry<CharSequence, CharSequence> header : http2Request.headers()) {
            stringBuilder.append(header.getKey()).append(": ").append(header.getValue())
                    .append("\r\n");
        }

        http2Response.addHeader(HttpHeaderNames.CONTENT_TYPE, ContentType.TEXT_PLAIN_UTF8.getMimeType());
        http2Response.setBody("Hello from HTTP/2");
        http2Response.reply(HttpResponseStatus.OK);

        stringBuilder
                .append(http2Request.body())
                .append("\r\n")
                .append("--------------------------------")
                .append("\r\n");

        LOGGER.info(stringBuilder);
    }

    @Override
    protected void handlePOST(Http2Request http2Request, Http2Response http2Response) throws JsonProcessingException {

        if (http2Request.body().isEmpty() || http2Request.body().isBlank()) {

            throw new HttpSleekException.BaseBuilder<>()
                    .contentType(ContentType.APPLICATION_JSON_UTF8)
                    .httpResponseStatus(HttpResponseStatus.BAD_REQUEST)
                    .responseMessage(new ObjectMapper().writeValueAsString(Map.of("errorMessage", "Body cannot be empty or blank")))
                    .build();
        }

        stringBuilder.setLength(0);

        stringBuilder
                .append("\r\n")
                .append("--------HTTP/2 REQUEST--------")
                .append("\r\n")
                .append("ip_port: ").append(http2Request.remoteAddress().getHostString())
                .append(":").append(http2Request.remoteAddress().getPort())
                .append("\r\n")
                .append("method: ").append(http2Request.method())
                .append("\r\n")
                .append("path: ").append(http2Request.path())
                .append("\r\n");

        for (Map.Entry<CharSequence, CharSequence> header : http2Request.headers()) {
            stringBuilder.append(header.getKey()).append(": ").append(header.getValue())
                    .append("\r\n");
        }

        http2Response.addHeader(HttpHeaderNames.CONTENT_TYPE, ContentType.TEXT_PLAIN_UTF8.getMimeType());
        http2Response.setBody("Saved! (HTTP/2)");
        http2Response.reply(HttpResponseStatus.CREATED);

        stringBuilder
                .append(http2Request.body())
                .append("\r\n")
                .append("--------------------------------")
                .append("\r\n");

        LOGGER.info(stringBuilder);
    }
}

HTTP2 REQUEST

2025-10-16 21:08:21 [INFO ] [pool-2-thread-2] m.t.s.a.Http2ExampleHandler:
--------HTTP/2 REQUEST--------
ip_port: 127.0.0.1:51564
method: POST
path: /http2_post
:path: /http2_post
:method: POST
:authority: localhost:8080
:scheme: https
content-type: application/json
user-agent: PostmanRuntime/7.48.0
accept: */*
postman-token: 21a37fed-2750-4b09-941d-49d47a9eeb6f
accept-encoding: gzip, deflate, br
content-length: 37
{
"id": "abc",
"level": 123
}
--------------------------------

About

A lightweight sub-millisecond p99 latency ultra high-performance non-blocking I/O io_uring and unix-domain-sockets compatible HTTP1/2/3 server module with easy TLS integration support.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors