package core.framework.impl.web.session;
import core.framework.api.util.Exceptions;
import core.framework.api.web.CookieSpec;
import core.framework.api.web.Response;
import core.framework.api.web.Session;
import core.framework.impl.web.request.RequestImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
/**
* @author neo
*/
public final class SessionManager {
private final Logger logger = LoggerFactory.getLogger(SessionManager.class);
private CookieSpec sessionId;
private Duration timeout = Duration.ofMinutes(20);
private SessionStore store;
public SessionManager() {
cookie("SessionId", null); // default domain is null, which is current host
}
public Session load(RequestImpl request) {
if (store == null) return null; // session store is not initialized
if (!"https".equals(request.scheme())) return null; // only load session under https
SessionImpl session = new SessionImpl();
request.cookie(sessionId).ifPresent(sessionId -> {
logger.debug("load session");
Map<String, String> values = store.getAndRefresh(sessionId, timeout);
if (values != null) {
logger.debug("[session] values={}", values);
session.id = sessionId;
session.values.putAll(values);
}
});
return session;
}
public void save(RequestImpl request, Response response) {
SessionImpl session = (SessionImpl) request.session;
if (session == null) return;
if (session.invalidated && session.id != null) {
logger.debug("invalidate session");
store.invalidate(session.id);
response.cookie(sessionId, null);
} else if (session.changed()) {
logger.debug("save session");
if (session.id == null) {
session.id = UUID.randomUUID().toString();
response.cookie(sessionId, session.id);
}
store.save(session.id, session.values, session.changedFields, timeout);
}
}
public void sessionStore(SessionStore store) {
if (this.store != null) throw Exceptions.error("session store is already configured, previous={}", this.store);
this.store = store;
}
public void timeout(Duration timeout) {
if (timeout == null) throw Exceptions.error("timeout must not be null");
this.timeout = timeout;
}
public void cookie(String name, String domain) {
if (name == null) throw Exceptions.error("name must not be null");
sessionId = new CookieSpec(name).domain(domain).path("/").sessionScope().httpOnly().secure();
}
}