You actually have several choices here. A first, simplistic approach would be to store the data in a string variable and render it as part of the view state. This method certainly works, but it invokes a lot of view state being passed back and forth, plus overhead for the HTML rendering, and is still subject to other limits, like the View State limit of 135kb of data.
I'd recommend a @RemoteAction to simply call the service as a proxy, and then allow the client to render the values. That looks like this:
// Some JavaScript
function doCallback() {
myController.doCallback(handleCallbackResult);
}
function handleCallbackResult(data, event) {
// render the new data
}
And on the controller:
@RemoteAction global static String doCallback() {
Http binding = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(yourEndpoint);
request.setMethod('GET'); // POST, etc.
HttpResponse response = binding.send(request);
return response.body();
}
You can also return complex types, like classes, and apply appropriate error handling, if your request can fail, and also supply parameters to the callout function, such as an ID for a record, some user-provided text, etc. Everything is transparently converted between JavaScript objects and Apex Code objects for you by the RemoteAction library.
You can even wire this whole thing up in your favorite JS library, like jQuery, AngularJS, etc, depending on your familiarity with those libraries.