Skip to content

Instantly share code, notes, and snippets.

@dyokomizo
Created February 27, 2012 12:54
Show Gist options
  • Save dyokomizo/1923530 to your computer and use it in GitHub Desktop.
Save dyokomizo/1923530 to your computer and use it in GitHub Desktop.
RestAgent
RestAgent agent = new HttpClientRestAgent();
String text = agent.goTo(someUri)
.get()
.post(someEntity)
.redirect()
.get()
.read(plainTextHandler);
import java.net.URI;
import org.apache.http.HttpEntity;
import org.apache.http.client.ResponseHandler;
// Inspired by http://www.bizcoder.com/index.php/2010/08/28/agent-fielding-is-on-a-mission/
public interface RestAgent {
// set the current URI
RestAgent goTo(URI uri);
// execute the request on the current URI and save the response
RestAgent get();
RestAgent post(HttpEntity entity);
RestAgent put(HttpEntity entity);
RestAgent delete();
// clears the last saved response
RestAgent clear();
// set the current URI to the Location Header of last response
RestAgent redirect();
// Applies the handler to the last response
// With the appropriate ResponseHandlers you can get the status code, headers, body parsed, etc.
<T> T read(ResponseHandler<T> handler);
}
@dyokomizo
Copy link
Author

Of course a couple of additional methods may be necessary:
1. To modify the request (e.g. set headers)
2. To do some arbitrary action on the response (e.g. check the status code and throw an exception if it's client or server error).

For both my current design is based on:

interface Action<T> {
    void invoke(T input);
}

And many small actions.

So we need to add a couple of methods to RestAgent:

// to modify the request
RestAgent with(Action<? super HttpMessage> action);
// to do something with the response
RestAgent then(Action<? super HttpResponse> action);

I didn't include those because I'm not 100% sure about their design yet, because I don't use this kind of feature a lot and it may not be sufficient, but they are theoretically enough.

With the appropriate actions it becomes:

Action<HttpMessage> header(String name, String value);
Action<HttpResponse> check(Predicate<? super HttpResponse> predicate);
Predicate<HttpResponse> statusCodeIs(int... values);


agent.goTo(someUri)
        .with(header("Accept", "application/json"))
        .get()
        .then(check(statusCodeIs(200,201,202)))
        .read(jsonHandler)

@dyokomizo
Copy link
Author

Instead of using HttpClient one can replace it with Restlet, etc., with no loss of expressivity. If one wants to use another language, no problem at all. Actually languages supporting lightweight closure definition the usage is much, much improved on the the higher-order methods (i.e. anything using Action or ResponseHandler).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment