[SalesForce] jQuery AJAX request responses with 401 Unauthorized

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

Best Answer

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;           
    }
}
Related Topic