Был заблокирован политикой CORS: Ответ на предполетный запрос не проходит проверку контроля доступа

Я создал сервер путешествий. Он работает нормально, и мы можем сделать POST запрос от Insomnia, но когда мы делаем POST запрос по axios на нашем интерфейсе, он отправляет ошибку:

has been blocked by CORS policy: Response to preflight request doesnt pass access control check: It does not have HTTP ok status.

Наш запрос на axios:

let config = {
headers: {
  "Content-Type": "application/json",
  'Access-Control-Allow-Origin': '*',
  }
}

let data = {
  "id": 4
 }

 axios.post('http://196.121.147.69:9777/twirp/route.FRoute/GetLists', data, config)
   .then((res) => {
      console.log(res)
     })
    .catch((err) => {
      console.log(err)
   });
} 

Мой файл go:

func setupResponse(w *http.ResponseWriter, req *http.Request) {
    (*w).Header().Set("Access-Control-Allow-Origin", "*")
    (*w).Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS, PUT, DELETE")

    (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}


func WithUserAgent(base http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

    ctx := r.Context()
    ua := r.Header.Get("Jwt")
    ctx = context.WithValue(ctx, "jwt", ua)

    r = r.WithContext(ctx)

    setupResponse(&w, r)
     base.ServeHTTP(w, r)
  })
}

const (
    host     = "localhost"
    port     = 5432
    user     = "postgres"
    password = "postgres"
    dbname   = "postgres"
)

func main() {

    psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
           "password=%s dbname=%s sslmode=disable",
               host, port, user, password, dbname)

    server := &s.Server{psqlInfo}

    twirpHandler := p.NewFinanceServiceServer(server, nil)

    wrap := WithUserAgent(twirpHandler)
      log.Fatalln(http.ListenAndServe(":9707", wrap))
}

Как я уже говорил в Insomnia, он прекрасно работает, но когда мы делаем POST запрос axios, в консоли браузера появляется следующее:

был заблокирован политикой CORS: Ответ на предпечатный запрос не прошел проверку контроля доступа: не имеет статуса HTTP ok.

Ответы

Ответ 1

Я считаю, что это самый простой пример:

header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")
header.Add("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS")
header.Add("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")

Вы также можете добавить заголовок для Access-Control-Max-Age и, конечно, вы можете разрешить любые заголовки и методы, которые вы пожелаете.

Наконец, вы хотите ответить на первоначальный запрос:

if r.Method == "OPTIONS" {
    w.WriteHeader(http.StatusOK)
    return
}

Изменить (июнь 2019): теперь мы используем гориллу для этого. Их вещи поддерживаются более активно, и они занимаются этим очень долго. Оставив ссылку на старую, на всякий случай.

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

Ответ 2

Включите перекрестные запросы в ASP.NET Web API, нажмите для получения дополнительной информации

Включите CORS в приложении WebService. Сначала добавьте пакет CORS NuGet. В Visual Studio в меню Сервис выберите Диспетчер пакетов NuGet, затем выберите Консоль диспетчера пакетов. В окне консоли диспетчера пакетов введите следующую команду:

Install-Package Microsoft.AspNet.WebApi.Cors

Эта команда устанавливает последний пакет и обновляет все зависимости, включая основные библиотеки Web API. Используйте флаг -Version для указания конкретной версии. Для пакета CORS требуется Web API 2.0 или более поздней версии.

Откройте файл App_Start/WebApiConfig.cs. Добавьте следующий код в метод WebApiConfig.Register:

using System.Web.Http;
namespace WebService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // New code
            config.EnableCors();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

Затем добавьте атрибут [EnableCors] в ваши методы контроллера/контроллера

using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WebService.Controllers
{
    [EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
    public class TestController : ApiController
    {
        // Controller methods not shown...
    }
}

Включить перекрестные запросы (CORS) в ASP.NET Core

Ответ 3

Этот ответ объясняет, что происходит за кулисами, и основы того, как решить эту проблему на любом языке. Для справки см. документы MDN по этой теме.

Вы делаете запрос на URL-адрес от JavaScript, работающего на одном домене (скажем, domain-a.com), к API, работающему на другом домене (domain-b.com). Когда вы делаете это, браузер должен спросить domain-b.com, можно ли разрешить запросы от domain-a.com. Это делается с помощью HTTP-запроса OPTIONS. Затем в ответе сервер на domain-b.com должен предоставить (как минимум) следующие HTTP-заголовки с надписью "Да, все в порядке":

HTTP/1.1 204 No Content                            // or 200 OK
Access-Control-Allow-Origin: https://domain-a.com  // or * for allowing anybody
Access-Control-Allow-Methods: POST, GET, OPTIONS   // What kind of methods are allowed
...                                                // other headers

Если вы находитесь в Chrome, вы можете увидеть, как выглядит ответ, нажав клавишу F12 и перейдя на вкладку "Сеть", чтобы увидеть ответ, который дает сервер на domain-b.com.

Итак, вернемся к минимуму первоначального ответа @threeve:

header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")

if r.Method == "OPTIONS" {
    w.WriteHeader(http.StatusOK)
    return
}

Это позволит любому человеку из любого места получить доступ к этим данным. Другие заголовки, которые он включил, необходимы по другим причинам, но эти заголовки - необходимый минимум для выполнения требований CORS (Cross Origin Resource Sharing).

Ответ 4

Представленное решение здесь является правильным. Однако та же самая ошибка может также произойти из-за ошибки пользователя, когда ваш метод запроса конечной точки совпадает с методом, который вы используете при выполнении запроса.

Например, конечная точка сервера определяется с помощью "RequestMethod.PUT", пока вы запрашиваете метод как POST.