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¶m2=value2¶m3=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.
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.
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!
David Schach Said,
February 16, 2010 @ 5:27 pm
VERY NICE, Scott! Definitely adding this to my toolbox. Thanks!
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.
Sven Delporte Said,
February 24, 2010 @ 2:24 am
Nice! never thought of doing such thing actually thanks for sharing this.
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/ […]