1 module hunt.http.routing.impl.HttpSessionHandlerImpl; 2 3 import hunt.http.routing.AbstractHttpSessionHandler; 4 import hunt.http.routing.RoutingContext; 5 import hunt.http.server.HttpSession; 6 7 import hunt.http.Cookie; 8 import hunt.http.Exceptions; 9 10 import hunt.logging; 11 12 import std.algorithm; 13 import std.string; 14 import std.range; 15 import std.uuid; 16 import std.variant; 17 18 /** 19 * 20 */ 21 class HttpSessionHandlerImpl : AbstractHttpSessionHandler { 22 23 private SessionStore sessionStore; 24 private string contextSessionKey = "_contextSessionKey"; 25 26 this(RoutingContext routingContext, SessionStore sessionStore, 27 string sessionIdParameterName, int defaultMaxInactiveInterval) { 28 super(routingContext, sessionIdParameterName, defaultMaxInactiveInterval); 29 this.sessionStore = sessionStore; 30 } 31 32 string getContextSessionKey() { 33 return contextSessionKey; 34 } 35 36 void setContextSessionKey(string contextSessionKey) { 37 this.contextSessionKey = contextSessionKey; 38 } 39 40 // override 41 HttpSession getSessionById(string id) { 42 return sessionStore.get(id); 43 } 44 45 // override 46 HttpSession getSession() { 47 return getSession(true); 48 } 49 50 // override 51 HttpSession getSession(bool create) { 52 return _getSession(create, -1); 53 } 54 55 // override 56 HttpSession getAndCreateSession(int maxAge) { 57 return _getSession(true, maxAge); 58 } 59 60 private HttpSession _getSession(bool create, int maxAge) { 61 Variant attr = routingContext.getAttribute(contextSessionKey); 62 HttpSession currentSession; 63 if (attr.type == typeid(HttpSession)) { 64 currentSession = attr.get!(HttpSession); 65 if(currentSession !is null) 66 return currentSession; 67 } 68 69 try { 70 string sid = getSessionId(create); 71 version(HUNT_HTTP_DEBUG) infof("SessionId: %s, size: %d", sid, sessionStore.size()); 72 if(sessionStore.contains(sid)) { 73 currentSession = sessionStore.get(sid); 74 routingContext.setAttribute(contextSessionKey, currentSession); 75 } else { 76 currentSession = createSession(maxAge); 77 } 78 } catch(Exception ex) { 79 version(HUNT_DEBUG) warning(ex.msg); 80 if(create) { 81 SessionInvalidException cause1 = cast(SessionInvalidException)ex; 82 SessionNotFoundException cause2 = cast(SessionNotFoundException)ex; 83 if(cause1 !is null || cause2 !is null) { 84 currentSession = createSession(maxAge); 85 } else { 86 version(HUNT_HTTP_DEBUG) warning(ex); 87 } 88 } else { 89 SessionInvalidException cause = cast(SessionInvalidException)ex; 90 if(cause !is null) { 91 removeCookie(); 92 } else { 93 version(HUNT_HTTP_DEBUG) warning(ex); 94 } 95 } 96 } 97 98 return currentSession; 99 } 100 101 private void removeCookie() { 102 Cookie cookie = new Cookie(sessionIdParameterName, requestedSessionId); 103 cookie.setMaxAge(0); 104 routingContext.addCookie(cookie); 105 } 106 107 108 // override 109 int getSessionSize() { 110 return sessionStore.size(); 111 } 112 113 // override 114 bool removeSession() { 115 try { 116 sessionStore.remove(requestedSessionId); 117 removeCookie(); 118 routingContext.getAttributes().remove(contextSessionKey); 119 } catch(Exception ex) { 120 version(HUNT_DEBUG) warning(ex.msg); 121 version(HUNT_HTTP_DEBUG) warning(ex); 122 return false; 123 } 124 return true; 125 } 126 127 // override 128 bool removeSessionById(string id) { 129 return sessionStore.remove(id); 130 } 131 132 // override 133 bool updateSession(HttpSession httpSession) { 134 routingContext.setAttribute(contextSessionKey, httpSession); 135 return sessionStore.put(requestedSessionId, httpSession); 136 } 137 138 protected string getSessionId(bool create) { 139 if (create && requestedSessionId.empty()) { 140 requestedSessionId = randomUUID().toString().replace("-", ""); 141 } 142 version(HUNT_HTTP_DEBUG_MORE) tracef("create: %s, requestedSessionId: %s", create, requestedSessionId); 143 return requestedSessionId; 144 } 145 146 protected HttpSession createSession(int maxAge) { 147 version(HUNT_HTTP_DEBUG) info("creating new session: ", requestedSessionId); 148 HttpSession newSession = HttpSession.create(requestedSessionId, defaultMaxInactiveInterval); 149 sessionStore.put(newSession.getId(), newSession); 150 createCookie(maxAge); 151 routingContext.setAttribute(contextSessionKey, newSession); 152 return newSession; 153 } 154 155 private void createCookie(int maxAge) { 156 Cookie cookie = new Cookie(sessionIdParameterName, requestedSessionId); 157 if (maxAge > 0) { 158 cookie.setMaxAge(maxAge); 159 } 160 routingContext.addCookie(cookie); 161 } 162 }