Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Merge commit '93dd6f644e59ba03ccd63211e68170bf03d7d4b1' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
Zanata Build Server committed Mar 4, 2016
2 parents 4651b86 + 93dd6f6 commit 9b67013
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
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 javax.ws.rs.core.Response;

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;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;

/**
* @author Patrick Huang <a href="mailto:[email protected]">[email protected]</a>
*/
public class InvalidContentTypeFilter extends ClientFilter {
private static final Logger log =
LoggerFactory.getLogger(InvalidContentTypeFilter.class);
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 (resp.getClientResponseStatus().getFamily().equals(
Response.Status.Family.SUCCESSFUL) &&
!isContentTypeCompatible(resp.getType())) {
log.error(ERROR_MSG);
String title = findPageTitle(resp);
String snippet = String.format(
"Wrong content type received: [%s]. Content page title: [%s]",
resp.getType(), title);

log.error(snippet);
throw new IllegalStateException(snippet);
} else {
return resp;
}
}

@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(".*<title>(.*)</title>.*");
Matcher matcher = pattern.matcher(body);
if (matcher.matches()) {
return matcher.group(1);
}
return "";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.zanata.rest.client;

import java.net.URI;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jersey.api.client.ClientHandler;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;

/**
* @author Patrick Huang <a href="mailto:[email protected]">[email protected]</a>
*/
public class RedirectFilter extends ClientFilter {
private static final Logger log =
LoggerFactory.getLogger(RedirectFilter.class);

@Override
public ClientResponse handle(ClientRequest clientRequest)
throws ClientHandlerException {
ClientHandler ch = getNext();
ClientResponse resp = ch.handle(clientRequest);

if (resp.getClientResponseStatus().getFamily() !=
Response.Status.Family.REDIRECTION) {
return resp;
} else {
// 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)");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@ public RestClientFactory(URI base, String username, String apiKey,
clientConfig.getClasses().add(JacksonJsonProvider.class);

client = Client.create(clientConfig);
client.addFilter(new RedirectFilter());
client.addFilter(
new ApiKeyHeaderFilter(username, apiKey, clientVersion));
client.addFilter(new AcceptTypeFilter());
client.addFilter(new TraceDebugFilter(logHttp));
client.addFilter(new InvalidContentTypeFilter());
}

private static void sslConfiguration(boolean sslCertDisabled,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.zanata.rest.client;

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 {

private String sampleText =
"<!DOCTYPE composition PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
"\n" +
" <html class=\"new-zanata-html\"><head>\n" +
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
" <title>Zanata: Home</title>\n" +
" <link rel=\"shortcut icon\" href=\"/javax.faces.resource/jars/assets/img/logo/logo.ico\" type=\"image/x-icon\" />\n" +
" <link type=\"text/css\" rel=\"stylesheet\" href=\"/resources/fontello/css/fontello.css\" />\n" +
" <link type=\"text/css\" rel=\"stylesheet\" class=\"user\" href=\"/javax.faces.resource/jars/assets/css/zanata.css\" />\n" +
" <link type=\"text/css\" rel=\"stylesheet\" href=\"/javax.faces.resource/jars/assets/css/style.min.css\" />";

private String text = " <title>Zanata: Home</title> \n";

@Test
public void testPatternMatch() {
Pattern pattern = Pattern.compile(".*<title>(.*)</title>.*",
Pattern.CASE_INSENSITIVE);

Matcher matcher = pattern.matcher(sampleText.replaceAll("\\n", " "));

MatcherAssert.assertThat(matcher.matches(), equalTo(true));
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));
}
}

0 comments on commit 9b67013

Please sign in to comment.