Решено - CORS, OPTIONS и PreFlight проблемы Использование REST API с Axios в Vue.js - PullRequest
0 голосов
/ 07 июля 2019

TL; DR

У меня были некоторые проблемы с форматированием моего вызова Axios, и я обнаружил, что использование заголовков в качестве const или var в моем вызове не работает, а сброс заголовков непосредственно в вызов работает.

Что касается PHP, в директиве Access-Control-Allow-Headers было несколько дополнительных фигурных скобок, которые приводили к заключению в заголовок ответа заголовка.

В целом, устранение неполадок с помощью вкладки «Сеть» в инструментах Browser Dev помогло нам найти исправление.

Я довольно новичок в программировании в целом и новичок в Vue.js и Axios. Так что я могу упускать части концептуально и синтаксически. Я разрабатываю интерфейс для PHP-приложения, которое запускает пользовательский инструмент управления. Моя цель - использовать Vue.js для создания внешнего интерфейса и, в частности, использовать Axios для выполнения вызовов API.

  • Я использую сервер Lightsail с открытым портом.
  • Код Visual Studio с инструментами удаленного разработчика, установленными и подключенными через SSH, для разработки на этом сервере, а не на моей машине.
  • Vue CLI 3 для настройки моего проекта и выбора пакетов по умолчанию Babel и Linting.
  • Axios устанавливается через npm.

Наша среда PHP изначально позволяла мне передавать такие параметры, как идентификатор пользователя, ключ API и запрос (в то время как метод user = x = get, apikey = x,), и я мог легко использовать данные и выводить их в виде v-for. и все работало довольно хорошо. Но это была не очень хорошо продуманная структура API, поэтому мы изменили идею о передаче параметров, так как мне не нравилась передача ключа API в URL, и мне не нравилась идея передавать SQL-запрос для получения данные. Итак, мой коллега скорректировал API, так что теперь у нас есть URL, который выглядит как https://tunnel.host.com/api/sites/read.php. У нас также будут файлы PHP для остальных операций CRUD позже. Но мне нужно преодолеть мою текущую проблему.

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

Некоторое время я думал, что установка пакета CORS npm поможет, но, похоже, это только для решения проблемы с локально размещенной серверной средой. (например, использование ExpressJS в качестве сервера в среде разработки)

После прочтения документации Mozilla относительно CORS мне интересно, нужно ли мне отправлять предварительные заголовки в HTTP-запросе OPTION.

Пока я пробовал: - Добавление файла vue.config.js с параметрами сервера dev (я приведу код ниже) Использование POSTMAN для создания заголовков и передачи запроса GET - который работает просто отлично - попытка использовать ключ заголовков в объекте Axios (код ниже)

Мой коллега, который работает с PHP, уверяет меня, что все заголовки CORS в файлах верны.

У меня только один компонент загружается в App.vue под названием AxiosTest.

Я отредактировал этот пост, чтобы обновить свои выводы.

Отправляя заголовки как const, запрос делается как GET

const config = {
            headers: {
                    "content-type": "application/vnd.api+json",
                    "Cache-Control": "no-cache",
                    "x-api-key": "9xxxxxxxxxxxxxxxxxxxxxx9"
            }
        }
        axios.get(
            `https://tunnel.xxxxx.com/api/headers.php?`,{ config
            })
            .then(response => {
                this.results = response;
            })
            .catch(error => {
                // eslint-disable-next-line
                console.log(error)
            })

И заголовок ответа

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 08 Jul 2019 19:22:55 GMT
Content-Type: application/json; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: http://54.x.x.155:8080
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 0

и Запрос

Host: tunnel.xxxxxx.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://54.x.x.155:8080/
Origin: http://54.x.x.155:8080
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0

Однако, если я сохраню объект headers внутри функции axios.get, я получу его как OPTIONS

axios.get(
            `https://tunnel.xxxx.com/api/headers.php?`,{
                headers: {
                    "content-type": "application/vnd.api+json",
                    "Cache-Control": "no-cache",
                    "x-api-key": "9xxxxxxxxxxxxxxxxxxxxxx9"
                }
            })
            .then(response => {
                this.results = response;
            })
            .catch(error => {
                // eslint-disable-next-line
                console.log(error)
            })

Ответ

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 08 Jul 2019 19:22:55 GMT
Content-Type: application/json; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: http://54.x.x.155:8080
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 0
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: {cache-control,x-api-key}

Запрос

Host: tunnel.xxxxx.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: cache-control,x-api-key
Referer: http://54.x.x.155:8080/
Origin: http://54.x.x.155:8080
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0

vue.config.js

module.exports = {
    devServer: {
        public: '54.x.x.x:8080',
        proxy: 'https://tunnel.xxxxxxx.com/'
    }
  }

В самом успешном тесте я все еще получаю Неверное происхождение CORS или неверный ключ API.

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

Ответы [ 4 ]

1 голос
/ 08 июля 2019

Посмотрите на документацию для axios :

axios.get(url[, config])

Метод get принимает два аргумента, но вы передаете его three .

Таким образом, данные, которые вы пытаетесь передать, обрабатываются как конфигурация (и игнорируются, поскольку ни одно из значений не является допустимым параметром конфигурации) и данные конфигурации (включая объект заголовков запроса)) игнорируется.

Строка запроса должна быть частью URL.Аксиос не будет использовать второй аргумент для его генерации.

const data = {
    foo: "bar"
};
axios.get(
    `https://example.com/api/headers.php?${new URLSearchParams(data)}`, {
        headers: {
            "Cache-Control": "no-cache",
            "content-type": "application/vnd.api+json",
            "x-api-key": "9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx9"
        }
    }).then(response => {
        console.log(response);
    }).catch(error => {
        console.log(error)
    })
0 голосов
/ 10 июля 2019

У меня были некоторые проблемы с форматированием моего вызова Axios, и я обнаружил, что использование заголовков в качестве const или var в моем вызове не работает, а сброс заголовков непосредственно в вызов действительно работает.

На стороне PHP в директиве Access-Control-Allow-Headers было несколько дополнительных фигурных скобок, которые приводили к заключению в заголовок ответа заголовка.

В целом устранение неполадок с помощью вкладки «Сеть» в инструментах Browser Dev помогло нам найти исправление.

0 голосов
/ 08 июля 2019

У меня также есть другой тестовый скрипт, который возвращает все значения массива $ _SERVER, и я никогда не вижу никаких пользовательских заголовков, когда его Axios вызывает его.Однако, если вы вызываете вещи с помощью curl из командной строки (добавляя заголовки), они наиболее определенно появляются в результирующем выводе.

<?
//---------------------------------------------------------------------------------------------------
include("../dashboard/subs.php");
//---------------------------------------------------------------------------------------------------
if (! IS_SSL()) {
  echo("{\"message\":\"API requires all traffic to be SSL encrypted.\"}\n");
  exit;
}
//---------------------------------------------------------------------------------------------------
InitCors();
//---------------------------------------------------------------------------------------------------
  $JSON  = "{\"data\":[";
  $JSON .= json_encode($_SERVER);
  $JSON .= "]}";
  echo("$JSON\n");
//---------------------------------------------------------------------------------------------------
?>
0 голосов
/ 08 июля 2019

Вот функция, которую я вызываю в верхней части PHP-скриптов, чтобы предоставить запрашивающей стороне 100% полный доступ к CORS.

function InitCors() {
  if (isset($_SERVER["HTTP_ORIGIN"])) {
    header("Access-Control-Allow-Origin: {$_SERVER["HTTP_ORIGIN"]}");
    header("Access-Control-Allow-Credentials: true");
    header("Access-Control-Max-Age: 0");
  }
  if ($_SERVER["REQUEST_METHOD"] == "OPTIONS") {
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])) header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"])) header("Access-Control-Allow-Headers: {" . $_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"] ."}");
  }
  header("Content-Type: application/json; charset=UTF-8");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...