В запрошенном ресурсе нет заголовка "Access-Control-Allow-Origin" - при попытке получить данные из REST API

Я пытаюсь получить некоторые данные из REST API HP Alm. Он работает очень хорошо с небольшим завитком script - я получаю свои данные.

Теперь, используя JavaScript, выборка и ES6 (более или менее) кажутся более серьезной проблемой. Я продолжаю получать это сообщение об ошибке:

API-интерфейс Fetch не может загружаться. Ответ на предполетный запрос не проверка контроля доступа: нет заголовка "Access-Control-Allow-Origin" присутствовать на запрошенном ресурсе. Origin 'http://127.0.0.1:3000' является поэтому не допускается доступ. В ответе был код статуса 501. Если непрозрачный ответ отвечает вашим потребностям, установите режим запроса на "no-cors" для извлечения ресурса с отключенным CORS.

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

Итак, есть ли проблема с реализацией? Я делаю это неправильно? К сожалению, я не могу проверить журналы сервера. Я действительно немного застрял здесь.

function performSignIn() {

  let headers = new Headers();

  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');

  headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
  headers.append('Access-Control-Allow-Credentials', 'true');

  headers.append('GET', 'POST', 'OPTIONS');

  headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(sign_in, {
      //mode: 'no-cors',
      credentials: 'include',
      method: 'POST',
      headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

Я использую Chrome. Я также пробовал использовать этот плагин Chrome CORS, но потом я получаю еще одно сообщение об ошибке:

Значение заголовка "Access-Control-Allow-Origin" в ответе не должен быть подстановочным знаком '*', когда режим учетных данных запроса 'включают'. Origin 'http://127.0.0.1:3000' поэтому не допускается доступ. Режим учетных данных запросов, инициированных XMLHttpRequest контролируется атрибутом withCredentials.

Ответ 1

Этот ответ охватывает много вопросов, поэтому он разделен на три части:

  • Как использовать прокси-сервер CORS для решения проблемы "Нет заголовка Access-Control-Allow-Origin"
  • Как избежать предполетной проверки CORS
  • Как исправить проблему "заголовок Access-Control-Allow-Origin не должен быть подстановочным знаком"

Как использовать прокси-сервер CORS для решения проблемы "Нет заголовка Access-Control-Allow-Origin"

Если вы не контролируете сервер, на который отправляет запрос ваш код JavaScript, и проблема с ответом с этого сервера заключается просто в отсутствии необходимого заголовка Access-Control-Allow-Origin, вы все равно можете заставить вещи работать: сделать запрос через прокси-сервер CORS. Чтобы показать, как это работает, сначала рассмотрим код, который не использует прокси-сервер CORS:

const url = "https://example.com"; // site that doesnt send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Cant access " + url + " response. Blocked by browser?"))

Ответ 2

Эта ошибка возникает, когда URL-адрес клиента и URL-адрес сервера не совпадают, включая номер порта. В этом случае вам необходимо включить службу для CORS, которая является совместным использованием ресурсов из разных источников.

Если у вас есть служба Spring REST, вы можете найти ее в блоге поддержки CORS в Spring Framework.

Если вы размещаете сервис на сервере Node.js, то

  1. Остановите сервер Node.js.
  2. npm install cors --save
  3. Добавьте следующие строки в ваш server.js

    var cors = require('cors')
    
    app.use(cors()) // Use this after the variable declaration
    

Ответ 3

Проблема возникла потому, что вы добавили следующий код в качестве заголовка запроса в ваш интерфейс:

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

Эти заголовки принадлежат ответу, а не запросу. Поэтому удалите их, включая строку:

headers.append('GET', 'POST', 'OPTIONS');

Ваш запрос содержал "Content-Type: application/json", следовательно, вызвал то, что называется предварительным просмотром CORS. Это привело к тому, что браузер отправил запрос методом OPTIONS. Смотрите предварительную проверку CORS для получения подробной информации.
Поэтому в вашем бэкэнде вы должны обработать этот предварительно выданный запрос, возвращая заголовки ответа, которые включают:

Access-Control-Allow-Origin : http://localhost:3000
Access-Control-Allow-Credentials : true
Access-Control-Allow-Methods : GET, POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, Accept

Конечно, фактический синтаксис зависит от языка программирования, который вы используете для своей серверной части.

В вашем интерфейсе это должно быть так:

function performSignIn() {
    let headers = new Headers();

    headers.append('Content-Type', 'application/json');
    headers.append('Accept', 'application/json');
    headers.append('Authorization', 'Basic ' + base64.encode(username + ":" +  password));
    headers.append('Origin','http://localhost:3000');

    fetch(sign_in, {
        mode: 'cors',
        credentials: 'include',
        method: 'POST',
        headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

Ответ 4

Удали это:

credentials: 'include',

Ответ 5

Использование dataType: 'jsonp' работал для меня.

   async function get_ajax_data(){
       var _reprojected_lat_lng = await $.ajax({
                                type: 'GET',
                                dataType: 'jsonp',
                                data: {},
                                url: _reprojection_url,
                                error: function (jqXHR, textStatus, errorThrown) {
                                    console.log(jqXHR)
                                },
                                success: function (data) {
                                    console.log(data);

                                    // note: data is already json type, you
                                    //       just specify dataType: jsonp
                                    return data;
                                }
                            });


 } // function               

Ответ 6

Я работал с Spring REST и решил, добавив AllowedMethods в WebMvcConfigurer.

@Value( "${app.allow.origins}" )
    private String allowOrigins;    
@Bean
public WebMvcConfigurer corsConfigurer() {
            System.out.println("allow origin: "+allowOrigins);
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                    //.allowedOrigins("http://localhost")
                    .allowedOrigins(allowOrigins)
                    .allowedMethods("PUT", "DELETE","GET", "POST");
                }
            };
        }

Ответ 7

Только мои два цента... относительно того, как использовать прокси-сервер CORS, чтобы обойти проблемы "Нет заголовка Access-Control-Allow-Origin "

Для тех из вас, кто работает с php на сервере, развертывание "прокси-сервера CORS" так же просто, как:

  1. создайте файл с именем "no-cors.php" со следующим содержимым:

    $URL = $_GET['url']; echo json_encode(file_get_contents($URL)); die();

  2. на вашем интерфейсе сделайте что-то вроде:

    fetch('https://example.com/no-cors.php' + '?url=' + url).then(response=>{*/Handle Response/*})

Ответ 8

В моем случае веб-сервер запретил метод "ОПЦИИ"

Проверьте свой веб-сервер на наличие метода опций

I'm using "webtier"

/www/webtier/domains/[domainname]/config/fmwconfig/components/OHS/VCWeb1/httpd.conf

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{REQUEST_METHOD} ^OPTIONS
  RewriteRule .* . [F]
</IfModule>

изменить на

<IfModule mod_rewrite.c>
  RewriteEngine off
  RewriteCond %{REQUEST_METHOD} ^OPTIONS
  RewriteRule .* . [F]
</IfModule>

Ответ 9

В моем случае я использую приведенное ниже решение

Передний или angular

post(
    this.serverUrl, dataObjToPost,
    {
      headers: new HttpHeaders({
           'Content-Type':  'application/json',
         })
    }
)

серверная часть (я использую php)

header("Access-Control-Allow-Origin: http://localhost:4200");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header("Access-Control-Allow-Headers: Content-Type, Authorization");

$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
print_r($request);

Ответ 10

Я получал эту ошибку на моем местном. Я запустил Visual Studio в качестве администратора, и это решило.