/*
* #%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 com.google.common.net.MediaType;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.http.impl.HttpServerRequestImpl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.wisdom.api.http.HeaderNames;
import org.wisdom.api.http.MimeTypes;
import java.lang.reflect.Constructor;
import java.net.InetSocketAddress;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Checks the behavior of the Request implementation.
*/
public class RequestFromVertXTest {
Vertx vertx = Vertx.vertx();
private ContextFromVertx context;
@Before
public void init() {
context = mock(ContextFromVertx.class);
when(context.vertx()).thenReturn(vertx);
}
@After
public void tearDown() {
vertx.close();
}
/**
* This is a hack to create HttpServerRequest. The constructor is not public, no, we call it using reflection.
*
* @param request the Netty request
* @return the Http Server Request
*/
public static HttpServerRequest create(HttpRequest request) {
try {
Class clazz =
RequestFromVertXTest.class.getClassLoader().loadClass("io.vertx.core.http.impl.ServerConnection");
final Constructor<HttpServerRequestImpl> constructor = HttpServerRequestImpl.class
.getDeclaredConstructor(
clazz,
HttpRequest.class,
HttpServerResponse.class
);
constructor.setAccessible(true);
return constructor.newInstance(
Mockito.mock(clazz),
request,
null
);
} catch (Exception e) {
fail("Cannot create the Http Server Request", e);
}
return null;
}
@Test
public void testContentType() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().add(HeaderNames.CONTENT_TYPE, MimeTypes.BINARY);
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.contentType()).isEqualTo(MimeTypes.BINARY);
req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
request = new RequestFromVertx(create(req));
assertThat(request.contentType()).isNull();
}
@Test
public void testEncodingLanguageAndCharset() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().add(HeaderNames.ACCEPT_ENCODING, "gzip, deflate");
req.headers().add(HeaderNames.ACCEPT_LANGUAGE, "en-US");
req.headers().add(HeaderNames.ACCEPT_CHARSET, "utf-8");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.encoding()).isEqualTo("gzip, deflate");
assertThat(request.language()).isEqualTo("en-US");
assertThat(request.charset()).isEqualTo("utf-8");
}
@Test
public void testUri() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.uri()).isEqualTo("/");
assertThat(request.path()).isEqualTo("/");
req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/foo");
request = new RequestFromVertx(create(req));
assertThat(request.uri()).isEqualTo("/foo");
assertThat(request.path()).isEqualTo("/foo");
req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/foo?k=v");
request = new RequestFromVertx(create(req));
assertThat(request.uri()).isEqualTo("/foo?k=v");
assertThat(request.path()).isEqualTo("/foo");
}
@Test
public void testMethod() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.method()).isEqualTo("GET");
req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.PATCH, "/");
request = new RequestFromVertx(create(req));
assertThat(request.method()).isEqualTo("PATCH");
}
@Test
public void testRemoteAddress() throws Exception {
ChannelHandlerContext ctx = mock(ChannelHandlerContext.class);
Channel channel = mock(Channel.class);
when(ctx.channel()).thenReturn(channel);
InetSocketAddress address = new InetSocketAddress("1.2.3.4", 1234);
when(channel.remoteAddress()).thenReturn(address);
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
// The case with the X_FORWARD_HEADER
req.headers().add(HeaderNames.X_FORWARD_FOR, "localhost");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.remoteAddress()).isEqualTo("localhost");
}
@Test
public void testLanguageOrder() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().set(HeaderNames.ACCEPT_LANGUAGE, "da, en-gb;q=0.8, en;q=0.7");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.languages()).containsExactly(
new Locale("da"),
new Locale("en", "gb"),
new Locale("en")
);
req.headers().set(HeaderNames.ACCEPT_LANGUAGE, "da, en-gb;q=0.7, en;q=0.9");
request = new RequestFromVertx(create(req));
assertThat(request.languages()).containsExactly(
new Locale("da"),
new Locale("en"),
new Locale("en", "gb")
);
}
@Test
public void testMediaType() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().set(HeaderNames.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp," +
"*/*;q=0.8");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.mediaType().toString()).isEqualTo("text/html");
req.headers().set(HeaderNames.ACCEPT, "application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
assertThat(request.mediaType().toString()).isEqualTo("application/xhtml+xml");
req.headers().set(HeaderNames.ACCEPT, "application/xhtml+xml;q=0.1,application/xml;q=0.9;charset=utf-8,*/*;q=0.8");
assertThat(request.mediaType().withoutParameters().toString()).isEqualTo("application/xml");
req.headers().clear();
assertThat(request.mediaType()).isEqualTo(MediaType.ANY_TEXT_TYPE);
req.headers().set(HeaderNames.ACCEPT, "*/*");
assertThat(request.mediaType()).isEqualTo(MediaType.ANY_TEXT_TYPE);
req.headers().set(HeaderNames.ACCEPT, "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5");
assertThat(request.mediaTypes()).containsExactly(
MediaType.parse("text/html").withParameter("level", "1"),
MediaType.parse("text/html").withParameter("q", "0.7"),
MediaType.parse("*/*").withParameter("q", "0.5"),
MediaType.parse("text/html").withParameter("level", "2").withParameter("q", "0.4"),
MediaType.parse("text/*").withParameter("q", "0.3")
);
}
@Test
public void testAccepts() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().set(HeaderNames.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp," +
"*/*;q=0.8");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.accepts("text/html")).isTrue();
assertThat(request.accepts("application/xhtml+xml")).isTrue();
assertThat(request.accepts("application/bla")).isFalse();
}
@Test
public void testCookies() throws Exception {
String c = "mediaWiki.user.id=0kn3VaEP7XG7mbxRPNgBOe5DNfOAGaHL; centralnotice_bucket=0-4.2; " +
"uls-previous-languages=%5B%22en%22%5D; mediaWiki.user.sessionId=Mu2OplNdlL98mRoHEwKGlxYsOXbyP1f0; GeoIP=::::v6";
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().set(HeaderNames.COOKIE, c);
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.cookies().get("mediaWiki.user.id").value()).isEqualTo("0kn3VaEP7XG7mbxRPNgBOe5DNfOAGaHL");
assertThat(request.cookies().get("GeoIP").value()).isEqualTo("::::v6");
assertThat(request.cookie("mediaWiki.user.id").value()).isEqualTo("0kn3VaEP7XG7mbxRPNgBOe5DNfOAGaHL");
assertThat(request.cookie("GeoIP").value()).isEqualTo("::::v6");
req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
request = new RequestFromVertx(create(req));
assertThat(request.cookies().get("GeoIP")).isNull();
assertThat(request.cookie("GeoIP")).isNull();
}
@Test
public void testHeaders() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
req.headers().add(HeaderNames.ACCEPT_ENCODING, "gzip, deflate");
req.headers().add(HeaderNames.ACCEPT_LANGUAGE, "en-US");
req.headers().add(HeaderNames.ACCEPT_CHARSET, "utf-8");
req.headers().add("test", "a").add("test", "b");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.headers().containsKey(HeaderNames.ACCEPT_LANGUAGE)).isTrue();
assertThat(request.headers().get("test")).containsExactly("a", "b");
assertThat(request.headers().get("missing")).isNull();
}
@Test
public void testQueryParameter() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/foo?k=v&i=5&b=true");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.parameter("k")).isEqualTo("v");
assertThat(request.parameter("k", "v2")).isEqualTo("v");
assertThat(request.parameter("none")).isNull();
assertThat(request.parameter("none", "v2")).isEqualTo("v2");
assertThat(request.parameterAsInteger("i")).isEqualTo(5);
assertThat(request.parameterAsInteger("j")).isNull();
assertThat(request.parameterAsInteger("i", 1)).isEqualTo(5);
assertThat(request.parameterAsInteger("j", 1)).isEqualTo(1);
assertThat(request.parameterAsBoolean("b")).isTrue();
assertThat(request.parameterAsBoolean("b2")).isFalse();
assertThat(request.parameterAsBoolean("b", false)).isTrue();
assertThat(request.parameterAsBoolean("b2", true)).isTrue();
req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/foo?k=v&i=5&b=true&i=6");
request = new RequestFromVertx(create(req));
assertThat(request.parameterMultipleValues("i")).containsExactly("5", "6");
}
@Test
public void testParameterMultipleValues() throws Exception {
HttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/foo?k=v&k=v2&k=v3");
RequestFromVertx request = new RequestFromVertx(create(req));
assertThat(request.parameterMultipleValues("k")).containsExactly("v", "v2", "v3");
}
}