Проблема с CORS при попытке сделать сообщение JQuery с данными json, но не с обычным текстом или x-www-form-urlencoded - PullRequest
0 голосов
/ 23 марта 2019

Выпуск / Резюме:

Проблема: я получаю сообщение об ошибке CORS при выполнении сообщения jQuery с данными приложения json. Но я не получаю эту ошибку с сообщениями jQuery с обычными / текстовыми или x-www-urlencoded-form данными.

Issue / Детали:

У меня есть два приложения, работающие на моей виртуальной машине Ubuntu, приложение React, работающее на http://localhost:3000, и веб-служба Java, работающая с сервера Payara из моей среды IDE Netbeans 10, по этому URL-адресу http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall. Я пытаюсь проверить работу разных постов jQuery с разными типами контента от приложения React до веб-службы.

Чтобы избежать получения сообщения об ошибке CORS, я добавил его на объект HttpServletRequest веб-сервера java response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");

Однако я получаю эту ошибку, когда выполняю сообщение jQuery с данными Json:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Но у меня есть два других метода тестирования, которые делают сообщения jQuery (один, где content-type равен text/plain, а другой - application/x-www-form-urlencoded, у которых нет этой проблемы. То есть я успешно могу отправить сообщение jQuery Post на веб-сервис и получить ответ обратно.

Вот код jQuery Post с данными json, где У меня проблема с ответом CORS :

  var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

  $.ajax({
     type: "POST",
     dataType: "json",
     contentType: 'application/json; charset=utf-8',
     //crossDomain: true,
     url: urlToPost,
     async:true,
     data: JSON.stringify({ Object: 'CD', Quantity: '4' }),
     success: function(response) {
        console.log("json response: " + response);
    },
    failure: function(errMsg) {
        alert(errMsg);
    }
 }); 

Вот сообщение jQuery с простым текстом, который работает (то есть без ответа CORS, я могу видеть, что достигается код веб-службы, и я могу видеть ответ назад на это приложение React, которое инициировало сообщение jQuery):

var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

   $.ajax({
       type: "POST",
       //dataType: "text",
       contentType: 'text/plain',
       url: urlToPost,
       data: "Hello from CommunicationForm (plain text)",
       success: function(response) {
         console.log("plain text response: " + response);
       }
   });   

Вот мой пост jQuery с x-www-urlencoded-form, который также работает:

  var myObject = {
      var1: 'Hello from CommunicationForm'  
   };
   var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

   $.ajax({
       type: "POST",
       //dataType: "text",
       contentType: 'application/x-www-form-urlencoded; charset=utf-8',
       url: urlToPost,
       data: myObject,
       success: function(response) {
           console.log("application/x-www-form-urlencoded response: " + response);
       }
   });

В качестве еще одного доказательства, вот снимок экрана моего приложения React, вы можете игнорировать поле ввода текста, так как оно ничего не делает. Но у меня есть 3 кнопки ввода ввода. Как можно понять из названий кнопок, один из них отправляет сообщение jQuery выше с типом содержимого x-www-urlencoded-form, другой - text / plain, а другой json.

enter image description here

После нажатия кнопки x-www .. этот оператор журнала (как показано на скриншоте) получен обратно от веб-службы (что указывает на его нормальную работу).

application / x-www-form-urlencoded response: Здравствуйте, возвращение из сервлета - полученный тип содержимого x-www-form-urlencoded

После нажатия на кнопку с открытым текстом на экране появляется этот лог-отчет, который еще раз подтверждает, что jQuery Post работает нормально:

простой текстовый ответ: Здравствуйте, от сервлета - получен тип контента простой текст

Последние два сообщения журнала консоли - это сообщение об ошибке CORS после нажатия кнопки Submit_json.

РЕДАКТИРОВАТЬ / ОБНОВИТЬ 2:

Дополнительные примечания - Используя приложение Post Man, я могу отправить HTTP Post с application / json в качестве типа контента в приложение веб-службы Java и увидеть ответ.

Я создал обычное Java-приложение Maven (не веб-приложение), и я также могу отправить HTTP-сообщение с application / json в качестве типа контента для моего приложения веб-службы Java, и в нем хорошо виден ответ.

Когда я отправил JQuery POST с application / json из своего веб-приложения REACT, на сетевой странице инструментов разработчика в веб-браузере я увидел, что POST отправляется как ОПЦИЯ (это происходило как в браузерах Firefox, так и в Chrome). .

Комментарий в этой ссылке https://github.com/angular/angular/issues/22492 упоминает об отправке простых запросов и перечисляет типы контента, которые не включают application/json.

Это делает вещи более запутанными.

РЕДАКТИРОВАТЬ / ОБНОВИТЬ 1:

Вот код моего внутреннего сервера. Ничего особенного, он просто проверяет поле заголовка типа содержимого, а затем анализирует объект и отправляет другой ответ обратно в приложение React.

public class FirstServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String contentType = request.getHeader("content-type");
        response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");

        if (contentType.equals("text/plain")) {
            InputStream is = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line = "";
            while((line = br.readLine()) != null) {
                System.out.println("Plain/Text data received: " + line);
            }
            response.getWriter().print("Hello back from Servlet - content type received plain text");
        } else if (contentType.equals("application/x-www-form-urlencoded; charset=utf-8")) {
            String msgReceived = request.getParameter("var1");
            System.out.println("Message Received: " + msgReceived);            
            response.getWriter().print("Hello back from Servlet - content type received x-www-form-urlencoded");
        } else if (contentType.toLowerCase().contains("json")) {
           JSONObject json = new JSONObject(request.getParameterMap());
           System.out.println("json data received: " + json.toString());
                       response.getWriter().print("Hello back from Servlet - content type received application/json");
        } else {
            response.getWriter().print("Hello back from Servlet - content type undefined");
        }
    }    
}

Ответы [ 3 ]

1 голос
/ 28 марта 2019

Единственными значениями для заголовка Content-Type в простом запросе являются следующие:

  • application / x-www-form-urlencoded
  • multipart / form-data
  • text / plain

Попробуйте изменить «application / json» на другой тип содержимого, иначе браузер выполнит предварительный запрос.

См. Документацию CORS.: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

0 голосов
/ 30 марта 2019

Я думаю, что, возможно, нашел проблему, еще более убедительно подтверждая то, что Индраджит Бхаскаран ответил выше.

По этой ссылке https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers#Directives

Обратите внимание, что всегда разрешены определенные заголовки: Accept, Accept-Language, Content-Language, Content-Type (но только с его типом MIME проанализированное значение (игнорируя параметры) любого application / x-www-form-urlencoded, multipart / form-data или текст / обычный ). Они называются простыми заголовками, и вам не нужно указать их явно.

Ключевым выводом из вышесказанного является то, что только 3 типа контента разрешены с веб-сайта для бэкэнда для запроса.

0 голосов
/ 23 марта 2019

CORS полностью зависит от значения заголовка Access-Control-Allow-Origin в ответе, и кажется, что ответ на запрос с типом содержимого json не получает этот заголовок.

Я думаю, что запрос с типом содержимого JSON может быть сбой на стороне сервера, а заголовок "Access-Control-Allow-Origin" устанавливается только для успешных запросов.

Вы проверилипоставив точку отладки на response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");, если она попадет под ваш запрос типа контента JSON?

Не могли бы вы поделиться кодом сервера, на котором устанавливается этот заголовок?

Мне жаль, что я задаю свои вопросы в разделе ответов вместо комментариев, так как я не могу комментировать этомомент.

РЕДАКТИРОВАНИЕ: Обновлен код Jquery для POST-запроса типа контента приложения / json.Пожалуйста, поделитесь необработанным форматом запроса, который можно увидеть на вкладке Сеть, если он не работает.Поскольку запрос не в правильном формате, он не затрагивает реализацию на стороне сервера, и поэтому заголовок в ответе не устанавливается.

var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

  $.ajax({
     url: urlToPost,
     type: "POST",
     contentType: 'application/json',
     data: JSON.stringify({ “Object”: “CD”, “Quantity”: “4” }),
     success: function(response) {
        console.log("json response: " + response);
    },
    failure: function(errMsg) {
        alert(errMsg);
    }
 }); 
...