diff --git a/zanata-cli/src/test/java/org/zanata/client/HTTPMockContainer.java b/zanata-cli/src/test/java/org/zanata/client/HTTPMockContainer.java index a30ecad7..0c680447 100644 --- a/zanata-cli/src/test/java/org/zanata/client/HTTPMockContainer.java +++ b/zanata-cli/src/test/java/org/zanata/client/HTTPMockContainer.java @@ -38,9 +38,8 @@ public void handle(Request request, Response response) { PrintStream body = response.getPrintStream(); long time = System.currentTimeMillis(); - response.setValue("Content-Type", "text/plain"); response.setStatus(status); - response.setContentType("text/xml;charset=utf-8"); + response.setContentType("text/plain"); response.setDate("Date", time); response.setDate("Last-Modified", time); diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java index 1110d78f..2545a002 100644 --- a/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java +++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2015, Red Hat, Inc. and individual contributors + * Copyright 2016, Red Hat, Inc. and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * @@ -20,12 +20,17 @@ */ package org.zanata.rest.client; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.ws.rs.core.MediaType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.sun.jersey.api.client.ClientHandler; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; @@ -38,21 +43,27 @@ public class InvalidContentTypeFilter extends ClientFilter { private static final Logger log = LoggerFactory.getLogger(InvalidContentTypeFilter.class); - private static final String ERROR_MSG = "Receiving HTML from the server. " + - "Most likely hitting a redirect or server returning error page. " + - "Please check the server URL is correct (in zanata.ini and in zanata.xml) and make sure you use the non-redirected address."; + private static final String ERROR_MSG = + "Received invalid content type from the server. " + + "Most likely you're hitting an error page or being redirected. " + + "Please check the server URL is correct (in zanata.ini and in zanata.xml) and make sure you use the correct address."; + // we assume only xml or json are the valid types (wildcard type is also considered compatible) + private static final Pattern VALID_TYPES_REGEX = + Pattern.compile("application/.*\\+?(\\*|xml|json)"); + @Override public ClientResponse handle(ClientRequest clientRequest) throws ClientHandlerException { ClientHandler ch = getNext(); ClientResponse resp = ch.handle(clientRequest); - if (MediaType.TEXT_HTML_TYPE.isCompatible(resp.getType())) { + if (!isContentTypeCompatible(resp.getType())) { log.error(ERROR_MSG); String title = findPageTitle(resp); - String snippet = String.format("Wrong content type received: [%s]. Content page title: [%s]", + String snippet = String.format( + "Wrong content type received: [%s]. Content page title: [%s]", resp.getType(), title); log.error(snippet); @@ -62,6 +73,23 @@ public ClientResponse handle(ClientRequest clientRequest) } } + @VisibleForTesting + protected static boolean isContentTypeCompatible( + final MediaType responseContentType) { + if (responseContentType == null || + responseContentType.isWildcardType() || + responseContentType.isWildcardSubtype()) { + return true; + } + // a few end points will return text/plain + if (MediaType.TEXT_PLAIN_TYPE.isCompatible(responseContentType)) { + return true; + } + Matcher matcher = + VALID_TYPES_REGEX.matcher(responseContentType.toString()); + return matcher.matches(); + } + private String findPageTitle(ClientResponse resp) { String body = resp.getEntity(String.class).replaceAll("\\n", " "); Pattern pattern = Pattern.compile(".*(.*).*"); diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java index f0445577..8bd5c8e1 100644 --- a/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java +++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2015, Red Hat, Inc. and individual contributors + * Copyright 2016, Red Hat, Inc. and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * @@ -48,14 +48,22 @@ public ClientResponse handle(ClientRequest clientRequest) Response.Status.Family.REDIRECTION) { return resp; } else { - // try location - log.debug("Server returns redirection status: {}. Try to follow it", - resp.getClientResponseStatus()); - URI redirectTarget = resp.getLocation(); - if (redirectTarget != null) { - clientRequest.setURI(redirectTarget); + // try location only if for GET and HEAD + String method = clientRequest.getMethod(); + if ("HEAD".equals(method) || "GET".equals(method)) { + log.debug( + "Server returns redirection status: {}. Try to follow it", + resp.getClientResponseStatus()); + URI redirectTarget = resp.getLocation(); + if (redirectTarget != null) { + clientRequest.setURI(redirectTarget); + } + return ch.handle(clientRequest); + } else { + throw new IllegalStateException( + "Received status " + resp.getClientResponseStatus() + + ". Check your server URL (e.g. used http instead of https)"); } - return ch.handle(clientRequest); } } } diff --git a/zanata-rest-client/src/test/java/org/zanata/rest/client/InvalidContentTypeFilterTest.java b/zanata-rest-client/src/test/java/org/zanata/rest/client/InvalidContentTypeFilterTest.java index 8b28d51e..63095d5d 100644 --- a/zanata-rest-client/src/test/java/org/zanata/rest/client/InvalidContentTypeFilterTest.java +++ b/zanata-rest-client/src/test/java/org/zanata/rest/client/InvalidContentTypeFilterTest.java @@ -3,11 +3,14 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.ws.rs.core.MediaType; + import org.hamcrest.MatcherAssert; import org.junit.Test; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.*; +import static org.zanata.rest.client.InvalidContentTypeFilter.isContentTypeCompatible; public class InvalidContentTypeFilterTest { @@ -26,7 +29,8 @@ public class InvalidContentTypeFilterTest { @Test public void testPatternMatch() { - Pattern pattern = Pattern.compile(".*(.*).*", Pattern.CASE_INSENSITIVE); + Pattern pattern = Pattern.compile(".*(.*).*", + Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(sampleText.replaceAll("\\n", " ")); @@ -34,4 +38,36 @@ public void testPatternMatch() { MatcherAssert.assertThat(matcher.group(1), equalTo("Zanata: Home")); } + @Test + public void testValidateContentTypes() { + + MatcherAssert.assertThat( + isContentTypeCompatible(MediaType.TEXT_HTML_TYPE), + equalTo(false)); + MatcherAssert.assertThat( + isContentTypeCompatible( + MediaType.APPLICATION_FORM_URLENCODED_TYPE), + equalTo(false)); + MatcherAssert.assertThat( + isContentTypeCompatible(MediaType.MULTIPART_FORM_DATA_TYPE), + equalTo(false)); + + MatcherAssert.assertThat( + isContentTypeCompatible(MediaType.APPLICATION_XML_TYPE), + equalTo(true)); + MatcherAssert.assertThat( + isContentTypeCompatible(MediaType.APPLICATION_JSON_TYPE), + equalTo(true)); + MatcherAssert.assertThat( + isContentTypeCompatible(MediaType.WILDCARD_TYPE), + equalTo(true)); + MatcherAssert.assertThat(isContentTypeCompatible( + new MediaType("application", "vnd.zanata+xml")), equalTo(true)); + MatcherAssert.assertThat( + isContentTypeCompatible(MediaType.TEXT_PLAIN_TYPE), + equalTo(true)); + MatcherAssert.assertThat( + isContentTypeCompatible(null), + equalTo(true)); + } }