[SalesForce] Cannot call apex rest service from jquery on Visualforce page

I'm new to rest services in Salesforce. I've defined the following rest service in Apex:

@RestResource(urlMapping='/mediaPlanDetail')
global with sharing class MediaPlanDetailService {

    @HttpGet
    global static String doGet() {

        RestResponse response = RestContext.response;    
        response.addHeader('Access-Control-Allow-Origin', '*');
        response.addHeader('content-Type', 'application/json');

        String URL = 'http://services.somecompany.com/services/loadByMediaPlanId';

        String payloadStr = '';
        System.debug(RestContext.request.requestBody);

        String rows = RestContext.request.params.get('rows');  System.debug('rows = ' + rows);
        String page = RestContext.request.params.get('page');  System.debug('page = ' + page);
        String sidx = RestContext.request.params.get('sidx');  System.debug('sidx = ' + sidx);
        String sord = RestContext.request.params.get('sord');  System.debug('sord = ' + sord);
        String mediaPlanId = RestContext.request.params.get('mediaPlanId');
        String pageSize = RestContext.request.params.get('pageSize');

        String finalUrl = URL + 
                '?rows=' + rows +
                '&page=' + page + 
                '&sidx=' + sidx + 
                '&sord=' + sord + 
                '&mediaPlanId=' + mediaPlanId +
                '&pageSize=' + pageSize +
                ''
                ;

        Http objhttp = new Http();
        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        req.setMethod('GET');

        req.setEndpoint(finalUrl);

        req.setHeader('Accept','application/json');
        req.setHeader('Content-type','application/json; charset=UTF-8');
        req.setHeader('Accept-Language', 'en-US');
        req.setTimeout(120000);

        try {
            res = objhttp.send(req);

            if(res.getStatus().equalsIgnoreCase('OK') && res.getStatusCode() == 200) {
                // Logic to parse the response
                String body = res.getBody();
                system.debug('-------- HttpResponse received: ' + body);

                final String PAYLOAD_ELEMENT = '\"payload\":';
                final String EXCEPTION_ELEMENT = '\"exception\":';

                integer payloadPos = body.indexOf(PAYLOAD_ELEMENT); System.debug('payloadPos = ' + payloadPos);
                integer exceptionPos = body.indexOf(EXCEPTION_ELEMENT); System.debug('exceptionPos = ' + exceptionPos);

                payloadStr = body.substring(payloadPos + PAYLOAD_ELEMENT.length(), exceptionPos - 1);

            }

        }
        catch(System.CalloutException e) {
            System.debug('Callout error: '+ e);
        }

        return payloadStr;
    }

}

I'm calling this service using a jQuery plugin call jqGrid. Here's a snippet of the code:

$(document).ready(function () {

    var mpId = $.urlParam('mediaPlanId');

    $("#jqGrid").jqGrid({
    url: '/services/apexrest/mediaPlanDetail',  // this fails with 302 Found
    //url: 'https://somecompany--cpq.cs7.my.salesforce.com/services/apexrest/mediaPlanDetail',  // this fails with 401 not authorized
    postData: {
        mediaPlanId: mpId,
        pageSize: 10
    },
    loadBeforeSend: function(jqXHR) {
        //jqXHR.setRequestHeader("Authorization", 'OAuth ' + __sfdcSessionId);
        jqXHR.setRequestHeader("Authorization", 'Bearer {!$Api.Session_ID}');
        //jqXHR.setRequestHeader("Authorization", 'OAuth {!$Api.Session_ID}');
    },

The VF page where I'm calling the service has this location:

https://somecompany--cpq--c.cs7.visual.force.com/apex/jqgrid_test_page?mediaPlanId=2271

When I call the service using

/services/apexrest/mediaPlanDetail

the service returns a 302 with an alternative Location in the header:

https://somecompany--cpq.cs7.my.salesforce.com/services/apexrest/mediaPlanDetail?mediaPlanId=2271&pageSize
=10&_search=false&nd=1437743215834&rows=10&page=1&sidx=&sord=asc

When I use the redirected location as the URL, I get a 401 Unauthorized response with Cross-Origin Request Blocked messages in my browser.

In either case, my Apex rest service is never called. I see nothing in the Debug Logs indicating that my browser is actually calling it.

This looks like a classic cross domain scripting issue between the Salesforce VP page domain and the domain used for Apex rest services. I spent a lot of time yesterday reading various posts on both calling SF rest services and cross domain issues, but wasn't able to find a solution. Can anyone help me with this?

Best Answer

A quick google search return pretty helpful results:

Code:

function CallRestAPI()
{
var weblink = "http://URL";

$.ajax(
{
url : weblink,
type : 'GET',
dataType: 'json',
beforeSend: function (request)
{
request.setRequestHeader("HeaderName", "HeaderValue");
},
crossDomain: true,
success : function(result)
{
    //process the result
},
error : function(jqXHR, textStatus, errorThrown) {
alert('Error: '+jqXHR.status);
alert('ErrorThrown: '+errorThrown)
} 
}); 
}

LINK

https://developer.salesforce.com/forums/?id=906F00000009AtOIAU

I would think the JS removing would be a MUCH better case, call the remote method and have that method call the web service directly.

Related Topic