dev.mccue.microhttp.session

What is it

dev.mccue.microhttp.session provides an interface for encoding session data in microhttp responses and decoding session data from microhttp requests.

Last one from me for this series, I promise. This just took a lot of build up.

Why use it

If you are making a classical web app, and maybe you should, then you will want to store persistent data about your users.

Most often logins, but other things like flash data are also fair game.

This provides a composable interface to that capability.

Getting Started

This example uses ScopedValues so will require preview features.

import dev.mccue.json.JsonDecoder;
import dev.mccue.microhttp.handler.DelegatingHandler;
import dev.mccue.microhttp.handler.RouteHandler;
import dev.mccue.microhttp.html.HtmlResponse;
import dev.mccue.microhttp.session.ScopedSession;
import dev.mccue.microhttp.session.SessionManager;
import dev.mccue.microhttp.session.SessionStore;
import org.microhttp.EventLoop;
import org.microhttp.Options;

import java.util.List;
import java.util.regex.Pattern;

import static dev.mccue.html.Html.HTML;


void main() throws Exception {
    var indexHandler = RouteHandler.of(
            "GET",
            Pattern.compile("/"),
            request -> {
                var name = ScopedSession.get()
                        .get("name", JsonDecoder::string)
                        .orElse("?");

                return new HtmlResponse(HTML."""
                        <h1> Your name is \{name} </h1>
                        """);
            }
    );

    var nameHandler = RouteHandler.of(
            "GET",
            Pattern.compile("/name/(?<name>.+)"),
            (matcher, request) -> {
                ScopedSession.update(data ->
                        data.with("name", matcher.group("name")));
                return new HtmlResponse(HTML."Go back to /");
            }
    );


    var notFound = new HtmlResponse(404, HTML."Not Found");
    var error = new HtmlResponse(500, HTML."Internal Server Error");

    // Can also store in encrypted cookies
    var store = SessionStore.inMemory();
    var manager = SessionManager.builder()
            .store(store)
            .build();

    var rootHandler = ScopedSession.wrap(manager,
            new DelegatingHandler(List.of(indexHandler, nameHandler), notFound)
    );
    
    var eventLoop = new EventLoop((request, callback) -> {
        try {
            callback.accept(rootHandler.handle(request).intoResponse());
        } catch (Exception e) {
            callback.accept(error.intoResponse());
        }
    });

    eventLoop.start();
    eventLoop.join();
}

<- Index