4

For a personal project, I'm trying to retrieve Validation Rules from objects to display them inside a Visualforce page.

For this I'm using the excellent Tooling API wrapper from Andrew Fawcett, but when making calls to it I get errors about the call being made from an unauthorized endpoint.

IO Exception: Unauthorized endpoint, please check Setup->Security->Remote site settings. endpoint = https://c.na40.visual.force.com/services/Soap/T/32.0

If I add the endpoint to the security settings the calls run without issues.

Two questions here:

  • If I wanted to distribute something using this through the AppExchange, should I have to include instructions to add the endpoint in the remote site settings? Or is there a way to automate this setting during installation?
  • To my understanding, several tools (Like Mavensmate and Atom, Sublime and VSCode extensions) make use of the Tooling API and they never ask for security settings in the target instance, how can they achieve that?

I'm fairly sure I'm missing something though.

Here's some sample code that triggers this, I'm using a dev instance for my tests.

TApi = new ToolingApi();
ToolingAPIWSDL.QueryResult qrVRs = TApi.query('select Name, TableEnumOrId from ValidationRule');
5

If I wanted to distribute something using this through the AppExchange, should I have to include instructions to add the endpoint in the remote site settings? Or is there a way to automate this setting during installation?

You can set them up from Javascript using a welcome page. Fawcett's own open source code base has a few examples of such behavior, including in the Apex Wrapper for the Metadata API. There's some additional markup, but here's the script involved:

function createRemoteSite()
{ 
    // Disable button 
    document.getElementById('createremotesitebtn').disabled = true;
    // Calls the Metdata API from JavaScript to create the Remote Site Setting to permit Apex callouts
    var binding = new XMLHttpRequest();
    var request = 
        '<?xml version="1.0" encoding="utf-8"?>' + 
        '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+
            '<env:Header>' + 
                '<urn:SessionHeader xmlns:urn="http://soap.sforce.com/2006/04/metadata">' + 
                    '<urn:sessionId>{!$Api.Session_ID}</urn:sessionId>' + 
                '</urn:SessionHeader>' + 
            '</env:Header>' + 
            '<env:Body>' +
                '<createMetadata xmlns="http://soap.sforce.com/2006/04/metadata">' + 
                    '<metadata xsi:type="RemoteSiteSetting">' + 
                        '<fullName>{!RemoteSiteName}</fullName>' +
                        '<description>Metadata API Remote Site Setting for Declarative Rollup Tool (DLRS)</description>' + 
                        '<disableProtocolSecurity>false</disableProtocolSecurity>' + 
                        '<isActive>true</isActive>' + 
                        '<url>https://{!Host}</url>' +
                    '</metadata>' +
                '</createMetadata>' +
            '</env:Body>' + 
        '</env:Envelope>';
    binding.open('POST', 'https://{!Host}/services/Soap/m/31.0');
    binding.setRequestHeader('SOAPAction','""');
    binding.setRequestHeader('Content-Type', 'text/xml');
    binding.onreadystatechange = 
        function() { 
            if(this.readyState==4) {
                var parser = new DOMParser();
                var doc  = parser.parseFromString(this.response, 'application/xml');
                var errors = doc.getElementsByTagName('errors');
                var messageText = '';
                for(var errorIdx = 0; errorIdx < errors.length; errorIdx++)
                    messageText+= errors.item(errorIdx).getElementsByTagName('message').item(0).innerHTML + '\n';
                displayMetadataResponse(messageText);
            } 
        }
    binding.send(request);
}

To my understanding, several tools (Like Mavensmate and Atom, Sublime and VSCode extensions) make use of the Tooling API and they never ask for security settings in the target instance, how can they achieve that?

The issue here is you have to whitelist endpoints to which you can make outbound calls, specifically using Apex. Any IDE will be making the outbound call using its own stack, and hence there is no mechanism enforcing that calls only be made to endpoints which are whitelisted in Salesforce.

  • Thanks for the answer Adrian, outbound call was the keyword for sure. Also, do you know if there's some limitation for using Andrew's code in a commercial App? – FuuRe Apr 11 '17 at 14:09
  • You can check out the licenses for yourself and should probably consult a lawyer. MDAPI uses BSD 3-clause, which looks like it would allow commercial re-distribution as long as you don't remove his copyright protections. I have not looked at the license for the Tooling API, nor am I a lawyer. – Adrian Larson Apr 11 '17 at 14:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.