7

I'm trying to perform a PURGE with HttpUrlConnection like this:

private void callVarnish(URL url) {
    HttpURLConnection conn = null;

    try {
        conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(PURGE_METHOD);
        conn.setDoOutput(true);
        conn.setInstanceFollowRedirects(true);
        conn.setRequestProperty("Host", "www.somehost.com");
        conn.connect();
        System.out.print(conn.getResponseCode() + " " + conn.getResponseMessage());
     }
     catch (Exception e) {
         log.error("Could not call varnish: " + e);
     } finally {
         if (conn != null) {
             conn.disconnect();
         }
     }
}

But I'm getting:

08:56:31,813 ERROR [VarnishHandler] Could not call varnish: java.net.ProtocolException: Invalid HTTP method: PURGE

With curl there is no problem:

curl -I -X PURGE -H "Host: www.somehost.com" someurl

HTTP/1.1 404 Not in cache.
Server: Varnish
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 401
Accept-Ranges: bytes
Date: Thu, 18 Oct 2012 06:40:19 GMT
X-Varnish: 1611365598
Age: 0
Via: 1.1 varnish
Connection: close
X-Cache: MISS

So how do I do this? Do I need to curl from Java or is there some other library that I can use?

jakob
  • 5,897
  • 7
  • 61
  • 101

3 Answers3

7

You can use Apache's HttpClient library: http://hc.apache.org/httpcomponents-client-ga/

You can either use BasicHttpRequest or implement your own HttpPurge class extending HttpRequestBase.

You can find a quick-start guide here: http://hc.apache.org/httpcomponents-client-ga/quickstart.html

Example:

DefaultHttpClient httpclient = new DefaultHttpClient();
BasicHttpRequest httpPurge = new BasicHttpRequest("PURGE", "www.somehost.com") 
HttpResponse response = httpclient.execute(httpPurge);
uldall
  • 2,289
  • 1
  • 14
  • 29
  • Thank you! I ended up extending HttpMethodBase in apache.commons.httpclient – jakob Oct 18 '12 at 07:53
  • HttpMethodBase is part of the Commons HttpClient project, which is actually marked as "end of life". See more here http://hc.apache.org/httpclient-3.x/ . if you want to be up-to-date you should use HttpComponents HttpClient: http://hc.apache.org/httpcomponents-client-ga/index.html – uldall Oct 18 '12 at 07:55
  • Ok I understand! I have implemented httpcomponents instead. – jakob Oct 18 '12 at 11:29
  • Any way to extend the native HttpUrlConnection, etc. to support PURGE request? We went down the route of wrapping the native HTTP support in Java for a custom "HTTP client" rather than go with 3rd party library like Apache. It would be preferable to stay that way than to have to port over, though we could do that as a last resort. – David Nov 21 '13 at 01:00
4

With org.apache.httpcomponents 4.2.1:

class:

import org.apache.http.client.methods.HttpRequestBase;

import java.net.URI;

public class HttpPurge extends HttpRequestBase {

    public final static String METHOD_NAME = "PURGE";

    public HttpPurge() {
        super();
    }

    @Override
    public String getMethod() {
        return METHOD_NAME;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public HttpPurge(final String uri) {
        super();
        setURI(URI.create(uri));
    }

    public String getName() {
        return "PURGE";
    }
}

The call:

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import test.HttpPurge

private void callVarnish(URL url) {

        DefaultHttpClient httpclient = new DefaultHttpClient();
        HttpPurge httpPurge = new HttpPurge(url.toString());
        Header header = new BasicHeader("Host", "www.somewhere.se");
        httpPurge.setHeader(header);
        try {
            HttpResponse response = httpclient.execute(httpPurge);
            System.out.print("-------------------------------------");
            System.out.println(response.getStatusLine());
            System.out.print("-------------------------------------");
            HttpEntity entity = response.getEntity();
            // If the response does not enclose an entity, there is no need
            // to worry about connection release
            if (entity != null) {
                // do something useful with the response body
                // and ensure it is fully consumed
                EntityUtils.consume(entity);
            }
        } catch (IOException ex) {

            // In case of an IOException the connection will be released
            // back to the connection manager automatically
        } catch (RuntimeException ex) {

            // In case of an unexpected exception you may want to abort
            // the HTTP request in order to shut down the underlying
            // connection and release it back to the connection manager.
            httpPurge.abort();
        }
}

With deprecated org.apache.commons.httpclient.HttpMethodBase:

class:

import org.apache.commons.httpclient.HttpMethodBase;

public class PurgeMethod extends HttpMethodBase {

    public PurgeMethod() {
        super();
        setFollowRedirects(true);
    }

    public PurgeMethod(String url) {
        super(url);
        setFollowRedirects(true);
    }

    public String getName() {
        return "PURGE";
    }
}

The call:

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;

private void callVarnish(URL url) {
    HttpClient client = new HttpClient();
    HttpMethod method = new PurgeMethod(url.toString());

try {
    int status = 0;
    status = client.executeMethod(method);

    log.debug(status);
} catch (Exception e) {
    // something
} finally {
    method.releaseConnection();
}

}

jakob
  • 5,897
  • 7
  • 61
  • 101
3

With HttpComponents the API has changed. Current version of uldall's answer is like:

HttpHost host = new HttpHost(hostname, port);
HttpClient httpclient = HttpClientBuilder.create().build();
BasicHttpRequest purgeRequest = new BasicHttpRequest("PURGE", "/some/url");
HttpResponse response = httpclient.execute(host, purgeRequest);
PetrS
  • 31
  • 1