/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.wisdom.framework.vertx;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpVersion;
import org.slf4j.LoggerFactory;
import org.wisdom.api.bodies.NoHttpBody;
import org.wisdom.api.content.ContentSerializer;
import org.wisdom.api.http.*;
import java.io.InputStream;
/**
* A set of utility methods used to handle HTTP requests.
*/
public class HttpUtils {
/**
* The 'CLOSE' connection value.
*/
public static final String CLOSE = "close";
/**
* The 'KEEP-ALIVE' connection value.
*/
public static final String KEEP_ALIVE = "keep-alive";
/**
* Checks whether the given request should be closed or not once completed.
*
* @param request the request
* @return {@code true} if the connection is marked as {@literal keep-alive}, and so must not be closed. {@code
* false} otherwise. Notice that if not set in the request, the default value depends on the HTTP version.
*/
public static boolean isKeepAlive(HttpServerRequest request) {
String connection = request.headers().get(HeaderNames.CONNECTION);
if (connection != null && connection.equalsIgnoreCase(CLOSE)) {
return false;
}
if (request.version() == HttpVersion.HTTP_1_1) {
return !CLOSE.equalsIgnoreCase(connection);
} else {
return KEEP_ALIVE.equalsIgnoreCase(connection);
}
}
/**
* Gets the HTTP Status (code) for the given result and indication on a state of failure.
*
* @param result the result
* @param success whether or not the result was computed correctly.
* @return the HTTP code, {@link Status#BAD_REQUEST} if {@literal success} is {@code false}.
*/
public static int getStatusFromResult(Result result, boolean success) {
if (!success) {
return Status.BAD_REQUEST;
} else {
return result.getStatusCode();
}
}
/**
* Processes the given result. This method returns either the "rendered renderable",
* but also applies required serialization if any.
*
* @param accessor the service accessor
* @param context the current HTTP context
* @param renderable the renderable object
* @param result the computed result
* @return the stream of the result
* @throws Exception if the result cannot be rendered.
*/
public static InputStream processResult(ServiceAccessor accessor, Context context, Renderable renderable,
Result result) throws Exception {
if (renderable.requireSerializer()) {
ContentSerializer serializer = null;
if (result.getContentType() != null) {
serializer = accessor.getContentEngines().getContentSerializerForContentType(result
.getContentType());
}
if (serializer == null) {
// Try with the Accept type
serializer = accessor.getContentEngines().getBestSerializer(context.request().mediaTypes());
if (serializer != null) {
// Set CONTENT_TYPE
result.with(HeaderNames.CONTENT_TYPE, serializer.getContentType());
}
}
if (serializer != null) {
serializer.serialize(renderable);
} else {
LoggerFactory.getLogger(HttpHandler.class)
.error("Cannot find a serializer to handle the request (explicit content type: {}, " +
"accept media types: {}), returning content as String",
result.getContentType(),
context.request().mediaTypes());
if (renderable.content() != null) {
renderable.setSerializedForm(renderable.content().toString());
result.with(HeaderNames.CONTENT_TYPE, "text/plain");
} else {
renderable = NoHttpBody.INSTANCE;
result.with(HeaderNames.CONTENT_TYPE, "text/plain");
}
}
}
return renderable.render(context, result);
}
/**
* A http content type should contain a character set like
* "application/json; charset=utf-8".
* <p>
* If you only want to get "application/json" you can use this method.
* <p>
* See also: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1
*
* @param rawContentType "application/json; charset=utf-8" or "application/json"
* @return only the contentType without charset. Eg "application/json"
*/
public static String getContentTypeFromContentTypeAndCharacterSetting(String rawContentType) {
if (rawContentType.contains(";")) {
return rawContentType.split(";")[0];
} else {
return rawContentType;
}
}
/**
* Checks whether the current request is either using the "POST" or "PUT" HTTP methods. This method let checks if
* the request can except a {@literal multipart} body or not.
*
* @param request the request
* @return {@code true} if the request use either "POST" or "PUT", {@code false} otherwise.
*/
public static boolean isPostOrPut(HttpServerRequest request) {
return request.method().name().equalsIgnoreCase(HttpMethod.POST.name())
|| request.method().name().equalsIgnoreCase(HttpMethod.PUT.name());
}
}