1

I have problem getting result from the custom REST service with my AJAX request. The call to REST service is responded with "Unauthorized". I am using static jQuery resource (jQuery version 1.7.2) and generated sessionId for authorization. Also, I added domains to CORS but this seems not enough. Am I missing anything?

Here is my jQuery code:

<apex:page sidebar="false" standardController="Warehouse__c" extensions="WarehouseUtils" docType="html-5.0">
<apex:includeScript value="{!URLFOR($Resource.jquery_and_css, '/js/jquery-1.7.2.min.js')}"  />
    <div>
        <input name="getList" value="Get warehouse list" type="button" onclick="getWarehouseList()" />
    </div>
    <div id="warehouseList">
    </div>
    <script type="text/javascript">
        var $j = jQuery.noConflict();
        $j(document).ready(function() {
            console.log($j().jquery);
        });
        var sessionId = '{!$Api.Session_ID}';
        function getWarehouseList() {
           console.log(sessionId);
            $j.ajax({
                type: "GET",
                url: "https://eu5.salesforce.com/services/apexrest/warehouseservice/meaninglessstringpatternalreadymatched",
                headers: {"Authorization" : "Bearer "+sessionId},
                crossDomain : true,
                dataType: 'jsonp',
                success: function (responseData) {
                    console.log(responseData);
                },
                error: function (request, status, error) {
                    console.log(request.responseText);
                }
            });
        }
    </script>
</apex:page>

Apex backend:

@RestResource(urlMapping='/warehouseservice/*')
global with sharing class WarehouseUtils {

    public WarehouseUtils(ApexPages.StandardController controller) {
    }

    public WarehouseUtils(ApexPages.StandardSetController controller) {

    }

    @RemoteAction
    global static List<Warehouse__c> findNearbyWarehouses(String lat, String lon) {
        String query = 'SELECT Id, Name, Location__Longitude__s, Location__Latitude__s, Street_Address__c, Phone__c, City__c ' + 
                       'FROM Warehouse__c ' +
                       'WHERE DISTANCE(Location__c, GEOLOCATION(' + lat + ', ' + lon + '), \'km\') < 50 ' +
                       'ORDER BY DISTANCE(Location__c, GEOLOCATION(' + lat + ', ' + lon + '), \'km\') ' + 
                       'LIMIT 10';
        List<Warehouse__c> warehouses = database.Query(query);
        return warehouses;           
    }

    @RemoteAction
    global static List<Warehouse__c> findAllWarehouses() {
        String query = 'SELECT Id, Name, Location__Longitude__s, Location__Latitude__s, Street_Address__c, Phone__c, City__c ' + 
                       'FROM Warehouse__c ';
        List<Warehouse__c> warehouses = database.Query(query);
        return warehouses;           
    }

    global static Warehouse__c createTestWarehouse(String name, Decimal lat, Decimal lon) {
        Warehouse__c w = new Warehouse__c(Name = name, Location__Latitude__s = lat, Location__Longitude__s = lon);
        insert w;
        return w;
    }

    @HttpGet
    global static List<Warehouse__c> getAllWarehouses() {
        String query = 'SELECT Id, Name, Location__Longitude__s, Location__Latitude__s, Street_Address__c, Phone__c, City__c ' + 
                       'FROM Warehouse__c ';
        List<Warehouse__c> warehouses = database.Query(query);
        return warehouses;           
    }
}

CORS settings:

enter image description here

The Apex code is OK (unfortunately, cannot post more than 2 links)

But response in the browser is "Unauthorized"

enter image description here

  • 1
    Just wanted to know if there is a specific reason that you are using JSONP instead of GET because by default JSONP will not send authentication headers, check it from Request headers. I understand CORS will restrict you if you call via JS to other domain. However you can try issuing simple GET request instead of JSONP and give a relative URL like "/services/apexrest/warehouseservice/meaninglessstringpatternalreadymatched" instead of full URL. You can also use AJAX toolkit remoteFunction but I believe that above implementation should work fine – manjit5190 Sep 22 '15 at 8:34
  • You might also want to check this stackoverflow.com/questions/7433556/… – manjit5190 Sep 22 '15 at 8:40
  • Are you able to call the service from WorkBench? – Saroj Bera Sep 22 '15 at 8:43
  • "using JSONP instead of GET" without dataType: 'jsonp' browser is sending OPTIONS request for some reason and I get "Access-Control-Allowed-Origin" error (the initial problem) link Request to relative URL produces the same result."Are you able to call the service from WorkBench?" I don't have access to workbench, I have only developer account (no sandboxes, etc). – Nikita Zogas Sep 22 '15 at 9:53
1

Well, I didn't manage to use cross-domain AJAX request, but for AJAX request to Apex class I used call to RemoteAction. Here is frontend code:

<apex:page sidebar="false" standardController="Warehouse__c" extensions="WarehouseUtils">
<apex:includeScript value="{!URLFOR($Resource.jquery_and_css, '/js/jquery-1.7.2.min.js')}"  />
    <div>
        <input name="getList" value="Get warehouse list" type="button" onclick="getWarehouseList('Vilnius','54.68','25.28')" />
    </div>
    <div id="warehouseList">
    </div>
    <script type="text/javascript">
        var $j = jQuery.noConflict();
        $j(document).ready(function() {
            console.log($j().jquery);
        });
        function getWarehouseList(title, lat, lon) {
            WarehouseUtils.getAllWarehousesAndAdd(title, lat, lon, function(responseData, event){
                if(event.status) {
                    console.log(responseData);
                    var sTable = "<table>";
                    $j.each(responseData, function(index, item) {
                        sTable += "<tr>" + 
                                      "<td>" + item.Name + "</td>" + 
                                      "<td>" + item.Location__Latitude__s + "</td>" + 
                                      "<td>" + item.Location__Longitude__s + "</td>" + 
                                  "</tr>";
                    });
                    sTable += "</table>";
                    $j('#warehouseList').html(sTable);
                }
            });
        }
    </script>
</apex:page>

And backend:

global with sharing class WarehouseUtils {

    public WarehouseUtils(ApexPages.StandardController controller) {
    }

    @RemoteAction
    global static List<Warehouse__c> getAllWarehousesAndAdd(String pname, Decimal lat, Decimal lon) {
        String query = 'SELECT Id, Name, Location__Longitude__s, Location__Latitude__s, Street_Address__c, Phone__c, City__c ' + 
                       'FROM Warehouse__c ';
        List<Warehouse__c> warehouses = database.Query(query);
        Warehouse__c warehouse = new Warehouse__c(Name = pname, Location__Latitude__s = lat, Location__Longitude__s = lon);
        warehouses.add(warehouse);
        return warehouses;           
    }
}
| improve this answer | |
  • +1 for taking the time to post your solution. I think you should be able to accept your answer to close your question. – Rob Sep 28 '15 at 8:28

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.