Endpoint for Debugging HTTP Callouts

When I use Apex to make HTTP callouts to other web services (e.g. Google Checkout, PayPal, Shopify, MapQuest, etc), it is often a game of trial and error to get things right. Oftentimes, I get errors from the recipient that my request is invalid and, for the life of me, I cannot see the problem.

To help me debug, I keep a test endpoint in my DE orgs that I make callouts to in order to get a good look at what I am sending. It’s a simple Visualforce page that I expose over Sites to act as a fake endpoint while I do development. When developing a callout, I will often use this endpoint in the beginning to organize the parameters and then periodically throughout development to debug.

The page is simple.

<apex:page controller="Endpoint_Controller" cache="false" showHeader="false" sidebar="false" action="{!init}">
<pre>
<apex:outputText escape="false" value="{!debugInfo}"></apex:outputText>
</pre>
</apex:page>

Depending upon my need, I will add/remove the action=”{!init}” parameter from the page because I have it in there to write the {!debugInfo} variable to a Task for later review (kind of like using a task as a mini-debug log). I don’t always need it turned on, so that parameter comes and goes.

My controller, with test method, is:

public without sharing class Endpoint_Controller {

public String debugInfo {get; set;}{

debugInfo = '';

if (ApexPages.currentPage() != null){
// Incoming Headers
debugInfo += '\n***ALL INCOMING HEADERS ***\n';
for (string key: ApexPages.currentPage().getHeaders().keySet()){
if (ApexPages.currentPage().getHeaders().get(key) != null){
debugInfo += key + ' = ' + ApexPages.currentPage().getHeaders().get(key) + '\n';
}
}

// Incoming Parameters
debugInfo += '\n***ALL INCOMING PARAMETERS ***\n';
for (string key: ApexPages.currentPage().getParameters().keySet()){
if (ApexPages.currentPage().getParameters().get(key) != null){
debugInfo += key + ' = ' + ApexPages.currentPage().getParameters().get(key) + '\n';
}
}

// Other Page Reference Stuff
debugInfo += '\n***OTHER PAGE REFERENCE INFO ***\n';
debugInfo += 'Anchor: ' + ApexPages.currentPage().getAnchor() + '\n';
debugInfo += 'URL: ' + ApexPages.currentPage().getUrl() + '\n';
}

}

public Endpoint_Controller(){}

public PageReference init() {

Task t = new Task();
t.Subject = 'Endpoint Invoked';
t.Description = debugInfo;
t.ActivityDate = Date.Today();
insert t;

return null;

}

static testMethod void Endpoint_Controller_test() {

// Set the page reference and pass through some parameters
PageReference thePage = Page.Endpoint;
thePage.getParameters().put('param1','1');
thePage.getParameters().put('param2','2');
Test.setCurrentPage(thePage);

// Run the init function to have it handle the web to lead submission
Endpoint_Controller ep = new Endpoint_Controller();
ep.init();
}
}

What does it do? Well, it simply gathers up all the headers, page parameters and other useful info and outputs it in a readable way. I sent a test request to one of my pages and this is what the page produced (and logged to a task in that org):

***ALL INCOMING HEADERS ***
Accept = application/xml;charset=UTF-8
Cache-Control = no-cache, max-age=0
CipherSuite = RC4-MD5 TLSv1 128-bits
Content-Type = application/xml;charset=UTF-8
Host = testorg.secure.force.com
Pragma = no-cache
SFDC_STACK_DEPTH = 1
User-Agent = SFDC-Callout/18.0
X-Forwarded-For = 10.226.8.134
X-Salesforce-Forwarded-To = na7.salesforce.com
X-Salesforce-SIP = 204.14.234.8

***ALL INCOMING PARAMETERS ***
param1 = value1
param2 = value2
param3 = value3

***OTHER PAGE REFERENCE INFO ***
Anchor: null
URL: /apex/Endpoint?param1=value1&param2=value2&param3=value3

I also construct debugInfo variables in my Production system to capture the receipt of incoming calls to Sites pages I have exposed (e.g. Google Checkout talks to my Salesforce org via a Sites page). I will usually have a custom setting that I can turn on/off so I have an easy way to turn off the creation of those activities.

6 Comments

  1. Wes Said,

    February 16, 2010 @ 9:48 am

    Smart! I’m doing some RESTFUL stuff as we speak, and I will definitely be using this.

  2. Tfox Said,

    February 16, 2010 @ 10:53 am

    Very inventive. I have a great appreciation for creative uses of SFDC and this is definitely a “Platform as a Service” application of the product. It’s also a great way for young coders (like myself) to gain experience with SF’s webservice methods.

    thank you for sharing!

  3. David Schach Said,

    February 16, 2010 @ 5:27 pm

    VERY NICE, Scott! Definitely adding this to my toolbox. Thanks!

  4. Michael Smith Said,

    February 18, 2010 @ 10:24 am

    Brilliant! I’m in the middle of rewriting some integration code to support an updated API. This will be a huge help.

  5. Sven Delporte Said,

    February 24, 2010 @ 2:24 am

    Nice! never thought of doing such thing actually thanks for sharing this.

  6. Debugging Salesforce Callout | Rey's Blog Said,

    January 31, 2013 @ 9:48 pm

    […] checkout this link if you’re interested with viewing the http raw data when executing the callouthttp://sfdc.arrowpointe.com/2010/02/16/endpoint-for-debugging-http-callouts/ […]

RSS feed for comments on this post