Commit c132c54e authored by Vincent Massol's avatar Vincent Massol
Browse files

XRENDERING-337: Link checker cannot verify URL when XWiki is behind a HTTP proxy

parent 5b28f2d2
......@@ -31,7 +31,7 @@
<name>XWiki Rendering - Transformation - Link Checker</name>
<description>Verifies if external URLs are valid and decorate with parameters if not</description>
......@@ -45,12 +45,26 @@
<!-- Test Dependencies -->
<!-- We are using SLF4J -->
......@@ -22,11 +22,13 @@
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.phase.Initializable;
......@@ -54,17 +56,30 @@ public class DefaultHTTPChecker implements HTTPChecker, Initializable
* Note: If one day we wish to configure timeouts, here's some good documentation about it:
private HttpClient httpClient;
private CloseableHttpClient httpClient;
public void initialize() throws InitializationException
this.httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// Make the Http Client reusable by several threads
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// Pre-configure with everything configured at JVM level (e.g. proxy setup).
// Set our user agent to be a good citizen.
this.httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT, "XWikiLinkChecker");
// Ignore cookies since this can cause errors in logs and we don't need cookies when checking sites.
RequestConfig config = RequestConfig.custom()
this.httpClient =;
......@@ -72,13 +87,11 @@ public int check(String url)
int responseCode;
GetMethod method = null;
CloseableHttpResponse httpResponse = null;
try {
method = new GetMethod(url);
// Execute the method.
responseCode = this.httpClient.executeMethod(method);
HttpGet httpGet = new HttpGet(url);
httpResponse = this.httpClient.execute(httpGet);
responseCode = httpResponse.getStatusLine().getStatusCode();
this.logger.debug("Result of pinging [{}]: code = [{}]", url, responseCode);
} catch (Exception e) {
// Some error in the transport or in the passed URL, use a special response code (0) which isn't in the
......@@ -86,8 +99,13 @@ public int check(String url)
responseCode = 0;
this.logger.debug("Error while checking [{}]", url, e);
} finally {
if (method != null) {
if (httpResponse != null) {
try {
} catch (Exception ee) {
// Failed to close, ignore but log the error.
this.logger.error("Failed to close HTTP connection for [{}]", url, ee);
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* 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
* 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:
package org.xwiki.rendering.internal.transformation.linkchecker;
import org.junit.Rule;
import org.junit.Test;
import org.xwiki.test.mockito.MockitoComponentMockingRule;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import static com.github.tomakehurst.wiremock.client.RequestPatternBuilder.allRequests;
import static com.github.tomakehurst.wiremock.client.WireMock.findAll;
import static org.junit.Assert.*;
* Integration tests for {@link org.xwiki.rendering.internal.transformation.linkchecker.DefaultHTTPChecker}.
* @version $Id$
* @since 6.1M2
public class DefaultHTTPCheckerTest
public WireMockRule proxyWireMockRule = new WireMockRule(8888);
public MockitoComponentMockingRule<DefaultHTTPChecker> mocker =
new MockitoComponentMockingRule<>(DefaultHTTPChecker.class);
public void testProxy() throws Exception
// First call the link checker but since we haven't set up any proxy our Mock HTTP Server is not going to be
// called (since http://host will lead to nowhere...
assertEquals(0, this.mocker.getComponentUnderTest().check("http://host"));
assertTrue("The HTTP server was not called by the link checker", findAll(allRequests()).isEmpty());
// Second, setup a proxy by using System Properties, then call again the checker and this time it should
// succeed since http://host will go to the proxy which is pointing to our Mock HTTP Server!
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "8888");
assertEquals(404, this.mocker.getComponentUnderTest().check("http://host"));
assertFalse("The HTTP server was called by the link checker", findAll(allRequests()).isEmpty());
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment