CORS и axios(xhr)

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
villiwalla
Сообщения: 10
Зарегистрирован: 2017.07.05, 11:57

CORS и axios(xhr)

Сообщение villiwalla »

Yii как rest на api.host.loc:8081, фронт на host.loc:8080 использую либу axios, в роли веб-сервера nginx.

Yii настроен так:
urlManager

Код: Выделить всё

        'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                'POST,OPTIONS /url' => 'url/create',
            ],
        ]
Поведение в контроллере для cors

Код: Выделить всё

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        unset($behaviors['authenticator']);

        $behaviors['corsFilter'] = [
            'class' => Cors::class,
            'cors' => [
                'Origin' => YII_ENV_DEV ? ['*'] : ['domain.ru'],
                'Access-Control-Request-Method' => ['POST', 'GET', 'OPTIONS'],
                'Access-Control-Allow-Credentials' => true,
                'Access-Control-Max-Age' => 3600,
            ],
        ];

        unset($behaviors['rateLimiter']);
        return $behaviors;
    }
nginx

Код: Выделить всё

server {
   listen 8081;
   server_name host.loc;
   root /frontend/dist;
   index index.html;

   location / {
       try_files $uri $uri/ /index.html?$args;
   }

   location ~ ^/r {
	proxy_pass http://api.host.loc:8081;
   }

   location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
       try_files $uri =404;
   }

   location ~ /\.(ht|svn|git) {
        deny all;
   }
}

server {
   listen 8081;
   server_name api.host.loc;
   root /api/web;
   index index.php;
   
   location / {
       try_files $uri $uri/ /index.php?$args;
   }

   location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
       try_files $uri =404;
   }

   include ./php74.conf;

   location ~ /\.(ht|svn|git) {
        deny all;
   }

}
Axios на фронте:

Код: Выделить всё

                HTTP.post('/url', {
                        url: this.inputValue
                    }, {
                    mode: 'no-cors',
                    headers: {
                        'Access-Control-Allow-Origin': '*',
                        'Content-Type': 'application/json',
                    },
                    withCredentials: true,
                    credentials: 'same-origin',
                })
Здесь, я уже просто на угад тыкать начал.

В таком раскладе всегда проблема в том что мол XMLHttpRequest запрещён и нет ответа с Access-Control-Allow-Origin
Access to XMLHttpRequest at 'http://api.host.loc:8081/url' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Ладно, херня война, включил insomnia:

Код: Выделить всё

> POST /url HTTP/1.1
> Host: api.host.loc:8081
> User-Agent: insomnia/7.1.1
> Content-Type: application/json
> Accept: */*
> Content-Length: 32

| {
| 	"url": "http://soc2ial.loc"
| }

< HTTP/1.1 200 OK
< Server: nginx/1.16.1
< Date: Thu, 05 Mar 2020 22:10:05 GMT
< Content-Type: application/json; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept
< Access-Control-Allow-Credentials: true
Работает, получаю курл из инсомнии:

Код: Выделить всё

curl --request POST \
>    --url http://api.host.loc:8081/url \
>    --header 'content-type: application/json' \
>    --data '{"url": "http://social.loc"}'
{
    "status": "success",
    "data": {}
}
Работает, копирую курл из девтулза того неудачного реквета который послал с фронта при помоши axios, ииии....

Код: Выделить всё

curl 'http://api.host.loc:8081/url' \
>  -H 'Accept: application/json, text/plain, */*' \
>  -H 'Referer: http://localhost:8080/' \
>  -H 'DNT: 1' \
>  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36' \
>  -H 'Content-Type: application/json' --data-binary '{"url":"http://social.loc"}' --compressed
{
    "status": "success",
    "data": {}
}  
Работает!!! Копирую fetch отваливается. Где моя ошибка, в чём может быть проблема?
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: CORS и axios(xhr)

Сообщение yiiliveext »

Для OPTIONS сделайте отдельную заглушку.
В Cors попробуйте такой конфиг.

Код: Выделить всё

$behaviors['corsFilter'] = [
            'class' => \yii\filters\Cors::className(),
            'cors' => [
                'Origin' => ['*'],
                'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
                'Access-Control-Request-Headers' => ['*'],
            ],
        ];
Правило для REST должно быть соответсвующего класса, пример

Код: Выделить всё

[
                    'class' => 'yii\rest\UrlRule',
                    'controller' => ['contact-phones' => 'v1/contact-phone'],
                    'prefix' => 'api/v1/contacts/<contact_id:\\d+>',
                    'tokens' => [
                        '{id}' => '<id:\\w+>'
                    ],
                    'extraPatterns' => [
                        'OPTIONS {id}' => 'options',
                    ]
                ],
Ответить