1 module hunt.http.routing.RoutingContext; 2 3 import hunt.http.server.HttpSession; 4 import hunt.http.server.HttpServerRequest; 5 import hunt.http.server.HttpServerResponse; 6 7 import hunt.http.codec.http.model; 8 import hunt.http.routing.handler; 9 10 import hunt.http.Cookie; 11 import hunt.http.HttpConnection; 12 import hunt.http.HttpHeader; 13 import hunt.http.HttpFields; 14 import hunt.http.HttpOutputStream; 15 import hunt.http.HttpStatus; 16 import hunt.http.HttpVersion; 17 18 import hunt.io.ByteBuffer; 19 import hunt.collection.List; 20 import hunt.collection.Map; 21 import hunt.concurrency.Promise; 22 import hunt.Exceptions; 23 import hunt.Functions; 24 import hunt.io.BufferUtils; 25 import hunt.logging; 26 import hunt.net.util.HttpURI; 27 import hunt.stream.Common; 28 import hunt.util.Common; 29 30 import std.conv; 31 import std.variant; 32 33 alias RoutingHandler = void delegate(RoutingContext routingContext); 34 35 deprecated("Using RouteHandler instead.") 36 alias Handler = RouteHandler; 37 38 /** 39 * 40 */ 41 interface RouteHandler { 42 void handle(RoutingContext context); 43 } 44 45 46 /** 47 * A new RoutingContext(ctx) instance is created for each HTTP request. 48 * <p> 49 * You can visit the RoutingContext instance in the whole router chain. 50 * It provides HTTP request/response API and allows you to maintain arbitrary data that lives for the lifetime of the context. 51 * Contexts are discarded once they have been routed to the handler for the request. 52 * <p> 53 * The context also provides access to the Session, cookies and body for the request, given the correct handlers in the application. 54 * 55 * 56 */ 57 abstract class RoutingContext : Closeable { 58 59 final T getAttributeAs(T)(string key) { 60 return getAttribute(key).get!T(); 61 } 62 63 final void setAttribute(T)(string key, T value) if(!is(T == Variant)) { 64 setAttribute(key, value.Variant()); 65 } 66 67 Variant getAttribute(string key); 68 69 void setAttribute(string key, Variant value); 70 71 Variant removeAttribute(string key); 72 73 Variant[string] getAttributes(); 74 75 HttpServerResponse getResponse(); 76 77 void response(HttpServerResponse response); 78 79 // HttpResponse getAsyncResponse(); 80 81 HttpServerRequest getRequest(); 82 83 // HttpOutputStream getOutputStream(); 84 OutputStream outputStream(); 85 86 int getConnectionId(); 87 88 HttpConnection httpConnection(); 89 90 string getRouterParameter(string name); 91 92 string getWildcardMatchedResult(int index) { 93 return getRouterParameter("param" ~ index.to!string()); 94 } 95 96 string getRegexGroup(int index) { 97 return getRouterParameter("group" ~ index.to!string()); 98 } 99 100 string getPathParameter(string name) { 101 return getRouterParameter(name); 102 } 103 104 // Optional!string getRouterParamOpt(string name) { 105 // return Optional.ofNullable(getRouterParameter(name)); 106 // } 107 108 /** 109 * Set the HTTP body packet receiving callback. 110 * 111 * @param content The HTTP body data receiving callback. When the server receives the HTTP body packet, it will be called. 112 * @return RoutingContext 113 */ 114 // RoutingContext onContent(Action1!ByteBuffer content); 115 116 /** 117 * Set the HTTP body packet complete callback. 118 * 119 * @param contentComplete The HTTP body packet complete callback. 120 * @return RoutingContext 121 */ 122 // RoutingContext onContentComplete(Action1!(HttpRequest) contentComplete); 123 124 /** 125 * Set the HTTP message complete callback. 126 * 127 * @param messageComplete the HTTP message complete callback. 128 * @return RoutingContext 129 */ 130 // RoutingContext onMessageComplete(Action1!(HttpRequest) messageComplete); 131 132 /** 133 * If return true, it represents you has set a HTTP body data receiving callback. 134 * 135 * @return If return true, it represents you has set a HTTP body data receiving callback 136 */ 137 bool isAsynchronousRead(); 138 139 void enableAsynchronousRead(); 140 141 /** 142 * Execute the next handler. 143 * 144 * @return If return false, it represents current handler is the last. 145 */ 146 void next(); 147 148 /** 149 * If return false, it represents current handler is the last. 150 * 151 * @return If return false, it represents current handler is the last. 152 */ 153 bool hasNext(); 154 155 // <T> RoutingContext complete(Promise<T> promise); 156 157 // <T> bool next(Promise<T> promise); 158 159 // <T> T> nextFuture() { 160 // Promise.Completable<T> completable = new Promise.Completable<>(); 161 // next(completable); 162 // return completable; 163 // } 164 165 // <T> T> complete() { 166 // Promise.Completable<T> completable = new Promise.Completable<>(); 167 // complete(completable); 168 // return completable; 169 // } 170 171 172 void succeed(bool t) { 173 version(HUNT_HTTP_DEBUG) trace("do nothing"); 174 } 175 176 void fail(Exception ex) { 177 // version(HUNT_DEBUG) warning(ex); 178 // if(!isCommitted()) { 179 // HttpServerResponse res = getResponse(); 180 // if(res !is null) { 181 // res.setStatus(HttpStatus.BAD_REQUEST_400); 182 // } 183 // end(ex.msg); 184 // } 185 } 186 187 // request wrap 188 string getMethod() { 189 return getRequest().getMethod(); 190 } 191 192 HttpURI getURI() { 193 return getRequest().getURI(); 194 } 195 196 HttpVersion getHttpVersion() { 197 return getRequest().getHttpVersion(); 198 } 199 200 HttpFields getFields() { 201 return getRequest().getFields(); 202 } 203 204 long getContentLength() { 205 return getRequest().getContentLength(); 206 } 207 208 Cookie[] getCookies() { 209 return getRequest().getCookies(); 210 } 211 212 string getParameter(string name); 213 214 List!string getParameterValues(string name); 215 216 Map!(string, List!string) getParameterMap(); 217 218 // Collection!Part getParts(); 219 220 // Part getPart(string name); 221 222 // InputStream getInputStream(); 223 224 // BufferedReader getBufferedReader(); 225 226 string getStringBody(string charset); 227 228 string getStringBody(); 229 230 // <T> T getJsonBody(Class<T> clazz); 231 232 // <T> T getJsonBody(GenericTypeReference<T> typeReference); 233 234 // JsonObject getJsonObjectBody(); 235 236 // JsonArray getJsonArrayBody(); 237 238 // response wrap 239 RoutingContext setStatus(int status) { 240 getResponse().setStatus(status); 241 return this; 242 } 243 244 RoutingContext setReason(string reason) { 245 getResponse().setReason(reason); 246 return this; 247 } 248 249 RoutingContext setHttpVersion(HttpVersion httpVersion) { 250 getResponse().setHttpVersion(httpVersion); 251 return this; 252 } 253 254 // RoutingContext put(HttpHeader header, string value) { 255 // getResponse().getFields().put(header, value); 256 // return this; 257 // } 258 259 // RoutingContext put(string header, string value) { 260 // getResponse().getFields().put(header, value); 261 // return this; 262 // } 263 264 // RoutingContext add(HttpHeader header, string value) { 265 // getResponse().getFields().add(header, value); 266 // return this; 267 // } 268 269 // RoutingContext add(string name, string value) { 270 // getResponse().getFields().add(name, value); 271 // return this; 272 // } 273 274 HttpFields getResponseHeaders() { 275 return getResponse().getFields(); 276 } 277 278 void responseHeader(HttpHeader header, HttpHeaderValue value) { 279 getResponse().getFields().put(header, value); 280 } 281 282 void responseHeader(string header, string value) { 283 getResponse().getFields().put(header, value); 284 } 285 286 void responseHeader(HttpHeader header, string value) { 287 getResponse().getFields().put(header, value); 288 } 289 290 RoutingContext addCookie(Cookie cookie) { 291 getResponse().addCookie(cookie); 292 return this; 293 } 294 295 RoutingContext write(string value); 296 297 // RoutingContext writeJson(Object object) { 298 // put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON_UTF_8.asString()).write(Json.toJson(object)); 299 // return this; 300 // } 301 302 RoutingContext write(byte[] b, int off, int len); 303 304 RoutingContext write(byte[] b) { 305 return write(b, 0, cast(int)b.length); 306 } 307 308 RoutingContext end(string value) { 309 return write(value).end(); 310 } 311 312 RoutingContext end(); 313 314 RoutingContext end(byte[] b) { 315 return write(b).end(); 316 } 317 318 void flush(); 319 320 bool isCommitted(); 321 322 void redirect(string url) { 323 setStatus(HttpStatus.FOUND_302); 324 getResponseHeaders().put(HttpHeader.LOCATION, url); 325 DefaultErrorResponseHandler.Default().render(this, HttpStatus.FOUND_302, null); 326 } 327 328 329 // HTTP session API 330 HttpSession getSessionById(string id); 331 332 HttpSession getSession(); 333 334 HttpSession getSession(bool create); 335 336 HttpSession getAndCreateSession(int maxAge); 337 338 int getSessionSize(); 339 340 bool removeSessionById(string id); 341 342 bool removeSession(); 343 344 bool updateSession(HttpSession httpSession); 345 346 bool isRequestedSessionIdFromURL(); 347 348 bool isRequestedSessionIdFromCookie(); 349 350 string getRequestedSessionId(); 351 352 string getSessionIdParameterName(); 353 354 string groupName(); 355 356 void groupName(string name); 357 358 // Template API 359 // void renderTemplate(string resourceName, Object scope); 360 361 // void renderTemplate(string resourceName, Object[] scopes); 362 363 // void renderTemplate(string resourceName, List!Object scopes); 364 365 // void renderTemplate(string resourceName) { 366 // renderTemplate(resourceName, Collections.emptyList()); 367 // } 368 369 }