Как сделать упреждающий вызов REST с ajax?

Я прошу помощи и объяснений, потому что я просто запутался.

У меня есть функция jQuery, которая с ajax выполняет POST-вызов на некоторый сервер.

var login = $("#email1").val();
var password = $("#password1").val();
var summary = $("#summary").val();
var details = $("#details").val();
var address = $("#address").val();
var str = login + ':' + password;
var credentials = utf8_to_b64(str);
function utf8_to_b64( str ) {
       return window.btoa(unescape(encodeURIComponent( str )));
       }
$.ajax({
        beforeSend: function (xhr) {
                   xhr.setRequestHeader("Authorization", "Basic " + credentials);
                   },
        crossDomain: true,
        //fails with or without next two arguments
        username: login,
        password:password,
        url: "https://blablablasomethingrelevant",
        type: "POST",
        dataType: "json",
        contentType: "application/json",
        data: JSON.stringify({"fields":{properdatahere}}),
        async: false,
        success: function (data) {
                         alert(data);
                      },
        error: function (xhr, ajaxOptions, thrownError) {
             alert(xhr.status);
             alert(thrownError);
             alert(xhr.responseText);
             alert(xhr);
             },

             });

Я получаю сообщение об ошибке: "На запрашиваемом ресурсе отсутствует заголовок" Access-Control-Allow-Origin "". Конечно, я гуглил это, и я всегда отвечал, что это "самообъясняющая" ошибка блабла, и ошибка на стороне сервера, и мне нужно сделать там некоторые хитрости. Эти ответы будут иметь смысл, если я не смогу выполнить тот же POST-вызов со всеми другими технологиями.

Когда я делал то же самое с java, используя jersey client, он работал нормально, то же самое, используя rest client с wiztools.org (пришлось поставить опцию preemptive)

Client client = Client.create();
client.addFilter(new com.sun.jersey.api.client.filter.HTTPBasicAuthFilter(login, password));
WebResource webResource = client.resource("https://blablablasomethingrelevant");
String input = "{"fields":{properdatahere}";
ClientResponse response = webResource.type("application/json").post(ClientResponse.class, input);

Так может кто-нибудь сказать мне, почему это работает с Java и Джерси, а не с JQuery и AJAX? Как заставить это наконец работать с ajax?

2 ответа

Решение

Причина, по которой он работает с Java, заключается в том, что Java не запускается в браузере клиента. По соображениям безопасности браузеры не разрешают запросы Javascript AJAX к доменам, отличным от домена, с которого была загружена страница. Например, если вы загружаете страницу из http://www.example.com/, JavaScript с этой страницы не сможет делать запросы AJAX для http://api.othersite.com/ или даже http://api.example.com/,

Есть несколько обходных путей. Одним из них является JSONP ( http://en.wikipedia.org/wiki/JSONP), а другим - установка заголовков CORS ( http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). И то, и другое требует изменения API, который вы вызываете, поэтому вы не можете решить его только на своей стороне.

Что вы можете сделать, это добавить ресурс на вашем сервере, такой как http://www.example.com/api/resource который затем в вашем бэкэнде (Java в вашем случае?) делает запрос http://api.othersite.com/ используя код, подобный тому, что вы написали в вопросе. Ваш Javascript может тогда позвонить http://www.example.com/api/resource без проблем. Короче говоря, вы передаете запросы через свой бэкэнд стороннему API.

Так что я поступил так, как советовал Йоскарссон, и это, конечно, сработало. Это потребовало дополнительной работы, и я до сих пор не понял, как убедиться, что мой ajax возвращает ошибку, если отправленных данных недостаточно для внешнего сервиса. Тем не менее, это было решением, теперь я отправляю данные в локальный класс ресурсов и делегирую bean-компонент со всеми данными службе, которая выполняет надлежащий пост-вызов нужного мне приложения.

Другие вопросы по тегам