Добавить заголовок в запрос AJAX с помощью jQuery

Я хотел бы добавить пользовательский заголовок в запрос AJAX POST от jQuery.

Я попробовал это:

$.ajax({
    type: 'POST',
    url: url,
    headers: {
        "My-First-Header":"first value",
        "My-Second-Header":"second value"
    }
    //OR
    //beforeSend: function(xhr) { 
    //  xhr.setRequestHeader("My-First-Header", "first value"); 
    //  xhr.setRequestHeader("My-Second-Header", "second value"); 
    //}
}).done(function(data) { 
    alert(data);
});

Когда я отправляю этот запрос и смотрю с FireBug, я вижу этот заголовок:

ОПЦИИ хххх / гггг HTTP / 1.1
Host: 127.0.0.1:6666
Пользователь-агент: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
Принять: текст / html, приложение /xhtml+xml, приложение /xml;q=0,9,/; q = 0,8
Accept-Language: fr, fr-fr; q = 0,8,en-us;q=0,5,en;q=0,3
Accept-Encoding: gzip, выкачать
Подключение: keep-alive
Происхождение: ноль
Access-Control-Request-Method: POST
Access-Control-Request-Headers: my-first-header, my-second-header
Прагма: без кеша
Cache-Control: без кеша

Почему мои пользовательские заголовки идут в Access-Control-Request-Headers:

Access-Control-Request-Headers: my-first-header, my-second-header

Я ожидал значения заголовка, как это:

My-First-Header: первое значение
My-Second-Header: второе значение

Является ли это возможным?

8 ответов

Решение

То, что вы видели в Firefox, не было настоящей просьбой; обратите внимание, что HTTP-метод - это OPTIONS, а не POST. На самом деле это был предварительный запрос, который браузер делает, чтобы определить, следует ли разрешить междоменный запрос AJAX:

http://www.w3.org/TR/cors/

Заголовок Access-Control-Request-Headers в предполетном запросе включает в себя список заголовков в реальном запросе. Затем ожидается, что сервер сообщит, поддерживаются ли эти заголовки в этом контексте или нет, прежде чем браузер отправит фактический запрос.

Вот пример того, как установить заголовок запроса в вызове JQuery Ajax:

$.ajax({
  type: "POST",
  beforeSend: function(request) {
    request.setRequestHeader("Authority", authorizationToken);
  },
  url: "entities",
  data: "json=" + escape(JSON.stringify(createRequestObject)),
  processData: false,
  success: function(msg) {
    $("#results").append("The result =" + StringifyPretty(msg));
  }
});

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

$.ajax({
    url: 'YourRestEndPoint',
    headers: {
        'Authorization':'Basic xxxxxxxxxxxxx',
        'X_CSRF_TOKEN':'xxxxxxxxxxxxxxxxxxxx',
        'Content-Type':'application/json'
    },
    method: 'POST',
    dataType: 'json',
    data: YourData,
    success: function(data){
      console.log('succes: '+data);
    }
  });

Надеюсь, что это ответ на ваш вопрос...

ОБНОВЛЕНИЕ для Laravel 5.6+:

В последней версии Laravel (по крайней мере, от Laravel 5.6 и выше) это НЕ X_CSRF_TOKEN, а X-CSRF-TOKEN.

Надеюсь, это проясняет.

Поскольку вы отправляете пользовательские заголовки, поэтому ваш запрос CORS НЕ ПРОСТО ЗАПРОС, поэтому браузер сначала отправляет запрос ОПЦИИ предварительного просмотра, чтобы проверить, что сервер разрешает ваш запрос.

Если вы включите CORS на сервере, то ваш код будет работать. Вы также можете использовать js fetch ( здесь)

let url='https://server.test-cors.org/server?enable=true&status=200&methods=POST&headers=My-First-Header,My-Second-Header';


$.ajax({
    type: 'POST',
    url: url,
    headers: {
        "My-First-Header":"first value",
        "My-Second-Header":"second value"
    }
}).done(function(data) { 
    alert(data[0].request.httpMethod + ' was send - open chrome console> network to see it');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Вот пример конфигурации, которая включает CORS на nginx (файл nginx.conf)

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

Вот пример конфигурации, которая включает CORS на apache (файл.htaccess)

# ------------------------------------------------------------------------------
# | Cross-domain AJAX requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin AJAX requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

# <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
# </IfModule>

#Header set Access-Control-Allow-Origin "http://example.com:3000"
#Header always set Access-Control-Allow-Credentials "true"

Header set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

И именно поэтому вы не можете создать бота с Javascript, потому что ваши возможности ограничены тем, что позволяет вам делать браузер. Вы не можете просто заказать браузер, который следует CORS политика, которой придерживается большинство браузеров, отправляет случайные запросы другим источникам и позволяет получить ответ, который просто!

Кроме того, если вы попытались отредактировать некоторые заголовки запроса вручную, например origin-header из инструментов разработчика, которые поставляются с браузерами, браузер откажется от вашего редактирования и может отправить предварительную проверку OPTIONS запрос.

Просто добавь 'Content-Type':'application/json'

       $.ajax({
        type: 'POST',
        url: url,
        headers: {
            'Content-Type':'application/json'
        }
        //OR
        //beforeSend: function(xhr) { 
        //  xhr.setRequestHeader("My-First-Header", "first value"); 
        //  xhr.setRequestHeader("My-Second-Header", "second value"); 
        //}
    }).done(function(data) { 
        alert(data);
    });

Со стороны клиента я не могу решить эту проблему. Со стороны nodejs express вы можете использовать модуль cors для его обработки.

var express       = require('express');
var app           = express();
var bodyParser = require('body-parser');
var cors = require('cors');

var port = 3000; 
var ip = '127.0.0.1';

app.use('*/myapi', 
          cors(), // with this row OPTIONS has handled
          bodyParser.text({type:'text/*'}),
          function( req, res, next ){
    console.log( '\n.----------------' + req.method + '------------------------' );
        console.log( '| prot:'+req.protocol );
        console.log( '| host:'+req.get('host') );
        console.log( '| url:'+req.originalUrl );
        console.log( '| body:',req.body );
        //console.log( '| req:',req );
    console.log( '.----------------' + req.method + '------------------------' );
    next();
    });

app.listen(port, ip, function() {
    console.log('Listening to port:  ' + port );
});
 
console.log(('dir:'+__dirname ));
console.log('The server is up and running at http://'+ip+':'+port+'/');

Без cors() этот OPTIONS появляется перед POST.

.----------------OPTIONS------------------------
| prot:http
| host:localhost:3000
| url:/myapi
| body: {}
.----------------OPTIONS------------------------

.----------------POST------------------------
| prot:http
| host:localhost:3000
| url:/myapi
| body: <SOAP-ENV:Envelope .. P-ENV:Envelope>
.----------------POST------------------------

Вызов ajax:

$.ajax({
    type: 'POST',
    contentType: "text/xml; charset=utf-8",
// these does not works
    //beforeSend: function(request) { 
    //  request.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
    //  request.setRequestHeader('Accept', 'application/vnd.realtime247.sct-giro-v1+cms');
    //  request.setRequestHeader('Access-Control-Allow-Origin', '*');
    //  request.setRequestHeader('Access-Control-Allow-Methods', 'POST, GET');
    //  request.setRequestHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type');
    //},
    //headers: {
    //  'Content-Type': 'text/xml; charset=utf-8',
    //  'Accept': 'application/vnd.realtime247.sct-giro-v1+cms',
    //  'Access-Control-Allow-Origin': '*',
    //  'Access-Control-Allow-Methods': 'POST, GET',
    //  'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type'
    //},
    url: 'http://localhost:3000/myapi',             
    data:       '<SOAP-ENV:Envelope .. P-ENV:Envelope>',                
    success: function( data ) {
      console.log(data.documentElement.innerHTML);
    },
    error: function(jqXHR, textStatus, err) {
      console.log( jqXHR,'\n', textStatus,'\n', err )
    }
  });

Попробуйте использовать драгоценный камень. И добавьте поле заголовка в ваш вызов ajax.

Другие вопросы по тегам