package org.rapidoid.http; /* * #%L * rapidoid-web * %% * Copyright (C) 2014 - 2017 Nikolche Mihajlovski and contributors * %% * 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% */ import org.junit.After; import org.junit.Before; import org.rapidoid.annotation.Authors; import org.rapidoid.annotation.Since; import org.rapidoid.commons.Arr; import org.rapidoid.config.Conf; import org.rapidoid.crypto.Crypto; import org.rapidoid.io.IO; import org.rapidoid.ioc.IoC; import org.rapidoid.jpa.JPAUtil; import org.rapidoid.scan.ClasspathUtil; import org.rapidoid.setup.Admin; import org.rapidoid.setup.App; import org.rapidoid.setup.On; import org.rapidoid.test.TestCommons; import org.rapidoid.u.U; import org.rapidoid.util.Msc; import java.util.List; import java.util.Map; @Authors("Nikolche Mihajlovski") @Since("2.0.0") public abstract class HttpTestCommons extends TestCommons { // FIXME HEAD private static final List<String> HTTP_VERBS = U.list("GET", "DELETE", "OPTIONS", "TRACE", "POST", "PUT", "PATCH"); public static final int DEFAULT_PORT = 8080; @Before public void openContext() { Msc.reset(); ClasspathUtil.setRootPackage("some.nonexisting.app"); System.out.println("--- STARTING SERVER ---"); JPAUtil.reset(); Conf.ROOT.setPath(getTestNamespace()); IoC.reset(); App.resetGlobalState(); On.changes().ignore(); On.setup().activate(); On.setup().reload(); System.out.println("--- SERVER STARTED ---"); verifyNoRoutes(); } @After public void closeContext() { System.out.println("--- STOPPING SERVER ---"); if (Admin.setup().isRunning()) { if (Admin.setup().port() == On.setup().port()) { Admin.setup().reset(); } else { Admin.setup().shutdown(); } } System.out.println("--- SERVER STOPPED ---"); } protected String localhost(String uri) { return localhost(DEFAULT_PORT, uri); } protected String localhost(int port, String uri) { return Msc.http() + "://localhost:" + port + uri; } protected String get(String uri) { return HTTP.req().get(localhost(uri)).fetch(); } protected byte[] getBytes(String uri) { return HTTP.get(localhost(uri)).execute().bodyBytes(); } protected void onlyGet(String uri) { onlyGet(DEFAULT_PORT, uri); } protected void onlyGet(int port, String uri) { onlyReq(port, "GET", uri, null); } protected void onlyPost(String uri) { onlyPost(DEFAULT_PORT, uri, null); } protected void onlyPost(String uri, Map<String, ?> data) { onlyPost(DEFAULT_PORT, uri, data); } protected void onlyPost(int port, String uri, Map<String, ?> data) { onlyReq(port, "POST", uri, data); } protected void onlyPut(String uri) { onlyPut(DEFAULT_PORT, uri, null); } protected void onlyPut(int port, String uri, Map<String, ?> data) { onlyReq(port, "PUT", uri, data); } protected void onlyPut(String uri, Map<String, ?> data) { onlyPut(DEFAULT_PORT, uri, data); } protected void onlyDelete(String uri) { onlyDelete(DEFAULT_PORT, uri); } protected void onlyDelete(int port, String uri) { onlyReq(port, "DELETE", uri, null); } protected void getAndPost(String uri) { getAndPost(DEFAULT_PORT, uri); } protected void getAndPost(int port, String uri) { testReq(port, "GET", uri, null); testReq(port, "POST", uri, null); notFoundExcept(port, uri, "GET", "POST"); } protected void getReq(String uri) { testReq(DEFAULT_PORT, "GET", uri, null); } protected void postData(String uri, Map<String, ?> data) { testReq(DEFAULT_PORT, "POST", uri, data); } protected void postData(int port, String uri, Map<String, ?> data) { testReq(port, "POST", uri, data); } protected void putData(String uri, Map<String, ?> data) { testReq(DEFAULT_PORT, "PUT", uri, data); } protected void putData(int port, String uri, Map<String, ?> data) { testReq(port, "PUT", uri, data); } protected void patchData(String uri, Map<String, ?> data) { testReq(DEFAULT_PORT, "PATCH", uri, data); } protected void patchData(int port, String uri, Map<String, ?> data) { testReq(port, "PATCH", uri, data); } private void onlyReq(int port, String verb, String uri, Map<String, ?> data) { testReq(port, verb, uri, data); notFoundExcept(port, uri, verb); } protected void deleteReq(String uri) { testReq(DEFAULT_PORT, "DELETE", uri, null); } protected void notFoundExcept(String uri, String... exceptVerbs) { notFoundExcept(DEFAULT_PORT, uri, exceptVerbs); } protected void notFoundExcept(int port, String uri, String... exceptVerbs) { for (String verb : HTTP_VERBS) { if (Arr.indexOf(exceptVerbs, verb) < 0) { notFound(port, verb, uri); } } } protected void notFound(String uri) { notFound(DEFAULT_PORT, uri); } protected void notFound(int port, String uri) { notFoundExcept(port, uri); } protected void notFound(int port, String verb, String uri) { String resp = fetch(port, verb, uri, null); String notFound = IO.load("404-not-found.txt"); U.notNull(notFound, "404-not-found"); check(verb + " " + uri, resp, notFound); } private void testReq(int port, String verb, String uri, Map<String, ?> data) { String resp = fetch(port, verb, uri, data); String reqName = reqName(port, verb, uri); verifyCase(port + " " + verb + " " + uri, resp, reqName); } protected String fetch(int port, String verb, String uri, Map<String, ?> data) { HttpReq req = HTTP.verb(HttpVerb.from(verb)).url(localhost(port, uri)).data(data); String result = exec(req); return result; } protected String fetch(HttpReq client, int port, String verb, String uri, Map<String, ?> data) { client.verb(HttpVerb.from(verb)).url(localhost(port, uri)).data(data); return exec(client); } private String exec(HttpReq client) { client.raw(true); String resp = new String(client.execute().raw()); resp = resp.replaceFirst("Date: .*? GMT", "Date: XXXXX GMT"); client.raw(false); return resp; } protected void raw(byte[] req) { String resp = new String(Msc.writeAndRead("localhost", 8080, req, 1000)); resp = resp.replaceFirst("Date: .*? GMT", "Date: XXXXX GMT"); resp = new String(req) + "--------------------------------------------------------\n" + resp + "<END>"; String hash = Crypto.md5(req); String reqName = reqName(DEFAULT_PORT, "", hash); verifyCase(DEFAULT_PORT + "-" + hash, resp, reqName); } protected void raw(String req) { raw(req.getBytes()); } protected void raw(List<String> requestLines) { raw((U.join("\r\n", requestLines) + "\r\n").getBytes()); raw((U.join("\n", requestLines) + "\n").getBytes()); } protected String fetch(HttpReq client, String verb, String uri, Map<String, ?> data) { return fetch(client, DEFAULT_PORT, verb, uri, data); } protected String fetch(HttpReq client, String verb, String uri) { return fetch(client, DEFAULT_PORT, verb, uri, null); } protected String fetch(String verb, String uri) { return fetch(DEFAULT_PORT, verb, uri, null); } protected String fetch(String verb, String uri, Map<String, ?> data) { return fetch(DEFAULT_PORT, verb, uri, data); } private String reqName(int port, String verb, String uri) { String req = verb + uri.replace("/", "_").replace("?", "-"); if (port != DEFAULT_PORT) { req = port + "__" + req; } return req; } protected static Map<String, Object> reqResp(Req req, Resp resp) { return U.map("verb", req.verb(), "uri", req.uri(), "data", req.data(), "code", resp.code()); } protected String appRoutes() { return U.join("\n", On.routes().all()); } protected void verifyRoutes() { verify("routes", appRoutes()); } protected void verifyRoutes(String name) { verify("routes-" + name, appRoutes()); } protected void verifyNoRoutes() { isTrue(On.routes().all().isEmpty()); } }