io.vertx.ext.web.impl.RoutingContextImpl Maven / Gradle / Ivy
/*
* Copyright 2014 Red Hat, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.ext.web.impl;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.vertx.codegen.annotations.Nullable;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.web.*;
import io.vertx.ext.web.Locale;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Tim Fox
*/
public class RoutingContextImpl extends RoutingContextImplBase {
private final RouterImpl router;
private Map data;
private Map pathParams;
private AtomicInteger handlerSeq = new AtomicInteger();
private Map> headersEndHandlers;
private Map> bodyEndHandlers;
private Throwable failure;
private int statusCode = -1;
private String normalisedPath;
private String acceptableContentType;
// We use Cookie as the key too so we can return keySet in cookies() without copying
private Map cookies;
private Buffer body;
private Set fileUploads;
private Session session;
private User user;
public RoutingContextImpl(String mountPoint, RouterImpl router, HttpServerRequest request, Set routes) {
super(mountPoint, request, routes);
this.router = router;
if (request.path().charAt(0) != '/') {
fail(404);
}
}
@Override
public HttpServerRequest request() {
return request;
}
@Override
public HttpServerResponse response() {
return request.response();
}
@Override
public Throwable failure() {
return failure;
}
@Override
public int statusCode() {
return statusCode;
}
@Override
public boolean failed() {
return failure != null || statusCode != -1;
}
@Override
public void next() {
if (!iterateNext()) {
checkHandleNoMatch();
}
}
private void checkHandleNoMatch() {
// Next called but no more matching routes
if (failed()) {
// Send back FAILURE
unhandledFailure(statusCode, failure, router);
} else {
// Send back default 404
response().setStatusCode(404);
if (request().method() == HttpMethod.HEAD) {
// HEAD responses don't have a body
response().end();
} else {
response()
.putHeader(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8")
.end(DEFAULT_404);
}
}
}
@Override
public void fail(int statusCode) {
this.statusCode = statusCode;
doFail();
}
@Override
public void fail(Throwable t) {
this.failure = t == null ? new NullPointerException() : t;
doFail();
}
@Override
public RoutingContext put(String key, Object obj) {
getData().put(key, obj);
return this;
}
@Override
public Vertx vertx() {
return router.vertx();
}
@Override
@SuppressWarnings("unchecked")
public T get(String key) {
Object obj = getData().get(key);
return (T)obj;
}
@Override
public Map data() {
return getData();
}
@Override
public String normalisedPath() {
if (normalisedPath == null) {
normalisedPath = Utils.normalisePath(request.path());
}
return normalisedPath;
}
@Override
public Cookie getCookie(String name) {
return cookiesMap().get(name);
}
@Override
public RoutingContext addCookie(Cookie cookie) {
cookiesMap().put(cookie.getName(), cookie);
return this;
}
@Override
public Cookie removeCookie(String name) {
return cookiesMap().remove(name);
}
@Override
public int cookieCount() {
return cookiesMap().size();
}
@Override
public Set cookies() {
return new HashSet<>(cookiesMap().values());
}
@Override
public String getBodyAsString() {
return body != null ? body.toString() : null;
}
@Override
public String getBodyAsString(String encoding) {
return body != null ? body.toString(encoding) : null;
}
@Override
public JsonObject getBodyAsJson() {
return body != null ? new JsonObject(body.toString()) : null;
}
@Override
public JsonArray getBodyAsJsonArray() {
return body != null ? new JsonArray(body.toString()) : null;
}
@Override
public Buffer getBody() {
return body;
}
@Override
public void setBody(Buffer body) {
this.body = body;
}
@Override
public Set fileUploads() {
return getFileUploads();
}
@Override
public void setSession(Session session) {
this.session = session;
}
@Override
public Session session() {
return session;
}
@Override
public User user() {
return user;
}
@Override
public void setUser(User user) {
this.user = user;
}
@Override
public void clearUser() {
this.user = null;
}
@Override
public String getAcceptableContentType() {
return acceptableContentType;
}
@Override
public void setAcceptableContentType(String contentType) {
this.acceptableContentType = contentType;
}
@Override
public int addHeadersEndHandler(Handler handler) {
int seq = nextHandlerSeq();
getHeadersEndHandlers().put(seq, handler);
return seq;
}
@Override
public boolean removeHeadersEndHandler(int handlerID) {
return getHeadersEndHandlers().remove(handlerID) != null;
}
@Override
public int addBodyEndHandler(Handler handler) {
int seq = nextHandlerSeq();
getBodyEndHandlers().put(seq, handler);
return seq;
}
@Override
public boolean removeBodyEndHandler(int handlerID) {
return getBodyEndHandlers().remove(handlerID) != null;
}
@Override
public void reroute(HttpMethod method, String path) {
((HttpServerRequestWrapper) request).setMethod(method);
((HttpServerRequestWrapper) request).setPath(path);
request.params().clear();
// we need to reset the normalized path
normalisedPath = null;
// we also need to reset any previous status
statusCode = -1;
failure = null;
restart();
}
@Override
public List acceptableLocales() {
String languages = request.getHeader("Accept-Language");
if (languages != null) {
List acceptLanguages = Utils.getSortedAcceptableMimeTypes(languages);
final List locales = new ArrayList<>(acceptLanguages.size());
for (String lang : acceptLanguages) {
int idx = lang.indexOf(';');
if (idx != -1) {
lang = lang.substring(0, idx).trim();
}
String[] parts = lang.split("_|-");
switch (parts.length) {
case 3:
locales.add(Locale.create(parts[0], parts[1], parts[2]));
break;
case 2:
locales.add(Locale.create(parts[0], parts[1]));
break;
case 1:
locales.add(Locale.create(parts[0]));
break;
}
}
return locales;
}
return Collections.emptyList();
}
@Override
public Map pathParams() {
return getPathParams();
}
@Override
public @Nullable String pathParam(String name) {
return getPathParams().get(name);
}
private Map getPathParams() {
if (pathParams == null) {
pathParams = new HashMap<>();
}
return pathParams;
}
private Map> getHeadersEndHandlers() {
if (headersEndHandlers == null) {
// order is important we we should traverse backwards
headersEndHandlers = new TreeMap<>(Collections.reverseOrder());
response().headersEndHandler(v -> headersEndHandlers.values().forEach(handler -> handler.handle(null)));
}
return headersEndHandlers;
}
private Map> getBodyEndHandlers() {
if (bodyEndHandlers == null) {
// order is important we we should traverse backwards
bodyEndHandlers = new TreeMap<>(Collections.reverseOrder());
response().bodyEndHandler(v -> bodyEndHandlers.values().forEach(handler -> handler.handle(null)));
}
return bodyEndHandlers;
}
private Map cookiesMap() {
if (cookies == null) {
cookies = new HashMap<>();
}
return cookies;
}
private Set getFileUploads() {
if (fileUploads == null) {
fileUploads = new HashSet<>();
}
return fileUploads;
}
private void doFail() {
this.iter = router.iterator();
next();
}
private Map getData() {
if (data == null) {
data = new HashMap<>();
}
return data;
}
private int nextHandlerSeq() {
int seq = handlerSeq.incrementAndGet();
if (seq == Integer.MAX_VALUE) {
throw new IllegalStateException("Too many header/body end handlers!");
}
return seq;
}
private static final String DEFAULT_404 =
"Resource not found
";
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy