¿Cómo puedo publicar datos como datos de formulario en lugar de una carga útil de solicitud?


En el siguiente código, el método AngularJS $http llama a la URL y envía el objeto xsrf como una "Carga útil de solicitud" (como se describe en la pestaña red del depurador de Chrome). El método jQuery $.ajax hace la misma llamada, pero envía xsrf como "Datos de formulario".

¿Cómo puedo hacer que AngularJS envíe xsrf como datos de formulario en lugar de una carga útil de solicitud?

var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};

$http({
    method: 'POST',
    url: url,
    data: xsrf
}).success(function () {});

$.ajax({
    type: 'POST',
    url: url,
    data: xsrf,
    dataType: 'json',
    success: function() {}
});
Author: Damjan Pavlica, 2012-07-12

22 answers

Se debe agregar la siguiente línea al objeto http http que se pasa:

headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}

Y los datos pasados deben convertirse en una cadena codificada en URL:

> $.param({fkey: "key"})
'fkey=key'

Así que tienes algo como:

$http({
    method: 'POST',
    url: url,
    data: $.param({fkey: "key"}),
    headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})

De: https://groups.google.com/forum/#! msg/angular / 5nAedJ1LyO0 / 4Vj_72EZcDsJ

ACTUALIZAR

Para usar nuevos servicios agregados con AngularJS V1.4, consulte

 594
Author: mjibson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-29 06:50:09

Si no desea utilizar jQuery en la solución, puede probar esto. Solución atrapó desde aquí https://stackoverflow.com/a/1714899/1784301

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: xsrf
}).success(function () {});
 192
Author: Anthony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:01

La continua confusión en torno a este tema me inspiró a escribir una entrada de blog al respecto. La solución que propongo en este post es mejor que su actual solución top rated porque no le restringe a parametrizar su objeto de datos para llamadas de servicio http http; es decir, con mi solución puede simplemente continuar pasando objetos de datos reales a http http.post (), etc. y aún así lograr el resultado deseado.

Además, la respuesta mejor valorada se basa en la inclusión de jQuery completo en la página para el $.función param (), mientras que mi solución es agnóstica jQuery, AngularJS puro listo.

Http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

Espero que esto ayude.

 91
Author: Ezekiel Victor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-21 12:07:16

Tomé algunas de las otras respuestas e hice algo un poco más limpio, puse esta llamada .config() al final de su angular.módulo en tu app.js:

.config(['$httpProvider', function ($httpProvider) {
  // Intercept POST requests, convert to standard form encoding
  $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
  $httpProvider.defaults.transformRequest.unshift(function (data, headersGetter) {
    var key, result = [];

    if (typeof data === "string")
      return data;

    for (key in data) {
      if (data.hasOwnProperty(key))
        result.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
    }
    return result.join("&");
  });
}]);
 82
Author: kzar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-14 08:52:14

A partir de AngularJS v1.4.0, hay un servicio incorporado $httpParamSerializer que convierte cualquier objeto a una parte de una solicitud HTTP de acuerdo con las reglas que se enumeran en la página docs.

Se puede usar así:

$http.post('http://example.com', $httpParamSerializer(formDataObj)).
    success(function(data){/* response status 200-299 */}).
    error(function(data){/* response status 400-999 */});

Recuerde que para un mensaje de formulario correcto, el encabezado Content-Type debe cambiarse. Para hacer esto globalmente para todas las solicitudes POST, se puede usar este código (tomado de la media respuesta de Albireo):

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

Para hacer esto solo para el post actual, la propiedad headers de la request-object necesita ser modificado:

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'application/x-www-form-urlencoded'
 },
 data: $httpParamSerializer(formDataObj)
};

$http(req);
 57
Author: Mitja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-01 19:57:20

Puede definir el comportamiento globalmente:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

Así que no tienes que redefinirlo cada vez:

$http.post("/handle/post", {
    foo: "FOO",
    bar: "BAR"
}).success(function (data, status, headers, config) {
    // TODO
}).error(function (data, status, headers, config) {
    // TODO
});
 24
Author: Albireo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-02 15:25:52

Como solución alternativa, simplemente puede hacer que el código que recibe el MENSAJE responda a los datos de la aplicación/json. Para PHP he añadido el código a continuación, lo que me permite publicar en él, ya sea en forma codificada o JSON.

//handles JSON posted arguments and stuffs them into $_POST
//angular's $http makes JSON posts (not normal "form encoded")
$content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); //parse content_type string
if ($content_type_args[0] == 'application/json')
  $_POST = json_decode(file_get_contents('php://input'),true);

//now continue to reference $_POST vars as usual
 20
Author: James Bell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-08 22:57:52

Estas respuestas parecen una locura exagerada, a veces, simple es simplemente mejor:

$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
                     "&password=" + encodeURIComponent(password) +
                     "&grant_type=password"
).success(function (data) {
//...
 16
Author: Serj Sagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-24 09:19:28

Puede probar con la siguiente solución

$http({
        method: 'POST',
        url: url-post,
        data: data-post-object-json,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        transformRequest: function(obj) {
            var str = [];
            for (var key in obj) {
                if (obj[key] instanceof Array) {
                    for(var idx in obj[key]){
                        var subObj = obj[key][idx];
                        for(var subKey in subObj){
                            str.push(encodeURIComponent(key) + "[" + idx + "][" + encodeURIComponent(subKey) + "]=" + encodeURIComponent(subObj[subKey]));
                        }
                    }
                }
                else {
                    str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
                }
            }
            return str.join("&");
        }
    }).success(function(response) {
          /* Do something */
        });
 9
Author: tmquang6805,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-09 11:00:31

Crear un servicio adaptador para post:

services.service('Http', function ($http) {

    var self = this

    this.post = function (url, data) {
        return $http({
            method: 'POST',
            url: url,
            data: $.param(data),
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        })
    }

}) 

Úsalo en tus controladores o lo que sea:

ctrls.controller('PersonCtrl', function (Http /* our service */) {
    var self = this
    self.user = {name: "Ozgur", eMail: null}

    self.register = function () {
        Http.post('/user/register', self.user).then(function (r) {
            //response
            console.log(r)
        })
    }

})
 8
Author: Ozgur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-16 23:41:34

Hay un tutorial muy bonito que repasa esto y otras cosas relacionadas - Enviando formularios AJAX: La forma AngularJS.

Básicamente, debe configurar el encabezado de la solicitud POST para indicar que está enviando datos de formulario como una cadena codificada de URL, y establecer los datos que se enviarán en el mismo formato

$http({
  method  : 'POST',
  url     : 'url',
  data    : $.param(xsrf),  // pass in data as strings
  headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
});

Tenga en cuenta que la función auxiliar param() de jQuery se usa aquí para serializar los datos en una cadena, pero también puede hacerlo manualmente si no usa jQuery.

 7
Author: robinmitra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-02 12:33:34
var fd = new FormData();
    fd.append('file', file);
    $http.post(uploadUrl, fd, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined}
    })
    .success(function(){
    })
    .error(function(){
    });

Por favor checkout! https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs

 6
Author: aul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-29 10:14:13

Para los usuarios de Symfony2:

Si no desea cambiar nada en su javascript para que esto funcione, puede hacer estas modificaciones en su aplicación symfony:

Cree una clase que extienda la clase Symfony\Component \ HttpFoundation\Request:

<?php

namespace Acme\Test\MyRequest;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;

class MyRequest extends Request{


/**
* Override and extend the createFromGlobals function.
* 
* 
*
* @return Request A new request
*
* @api
*/
public static function createFromGlobals()
{
  // Get what we would get from the parent
  $request = parent::createFromGlobals();

  // Add the handling for 'application/json' content type.
  if(0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')){

    // The json is in the content
    $cont = $request->getContent();

    $json = json_decode($cont);

    // ParameterBag must be an Array.
    if(is_object($json)) {
      $json = (array) $json;
  }
  $request->request = new ParameterBag($json);

}

return $request;

}

}

Ahora usa tu clase en app_dev.php (o cualquier archivo de índice que utilice)

// web/app_dev.php

$kernel = new AppKernel('dev', true);
// $kernel->loadClassCache();
$request = ForumBundleRequest::createFromGlobals();

// use your class instead
// $request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
 4
Author: carmel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-05 09:37:54

Simplemente establecer el tipo de contenido no es suficiente, la url codifica los datos del formulario antes de enviarlos. $http.post(url, jQuery.param(data))

 3
Author: Merlin Ran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-01 09:12:19

Actualmente estoy usando la siguiente solución que encontré en el grupo de Google AngularJS.

$http
.post('/echo/json/', 'json=' + encodeURIComponent(angular.toJson(data)), {
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    }
}).success(function(data) {
    $scope.data = data;
});

Tenga en cuenta que si está utilizando PHP, necesitará usar algo como el componente HTTP de Symfony 2 Request::createFromGlobals() para leer esto, ya que $_POST no se cargará automáticamente con él.

 3
Author: Aditya M P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-15 23:02:22

AngularJS lo está haciendo bien al hacer el siguiente content-type dentro del encabezado http-request:

Content-Type: application/json

Si va con php como yo, o incluso con Symfony2, simplemente puede extender la compatibilidad de su servidor para el estándar json como se describe aquí: http://silex.sensiolabs.org/doc/cookbook/json_request_body.html

La forma Symfony2 (por ejemplo, dentro de su DefaultController):

$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
    $data = json_decode($request->getContent(), true);
    $request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());

La ventaja sería que no necesita usar jQuery param y usted podría utilizar AngularJS su forma nativa de hacer este tipo de solicitudes.

 2
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-22 10:27:08

Respuesta completa (desde angular 1.4). Necesita incluir de dependency {httpParamSerializer

var res = $resource(serverUrl + 'Token', { }, {
                save: { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
            });

            res.save({ }, $httpParamSerializer({ param1: 'sdsd', param2: 'sdsd' }), function (response) {

            }, function (error) { 

            });
 2
Author: Sebastián Rojas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-20 21:46:28

En la configuración de la aplicación -

$httpProvider.defaults.transformRequest = function (data) {
        if (data === undefined)
            return data;
        var clonedData = $.extend(true, {}, data);
        for (var property in clonedData)
            if (property.substr(0, 1) == '$')
                delete clonedData[property];

        return $.param(clonedData);
    };

Con su solicitud de recursos -

 headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
 1
Author: Vivek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-14 17:46:43

Esta no es una respuesta directa, sino una dirección de diseño ligeramente diferente:

No publique los datos como un formulario, sino como un objeto JSON que se asignará directamente al objeto del lado del servidor, o use la variable de ruta de estilo REST

Ahora sé que ninguna opción podría ser adecuada en su caso ya que está tratando de pasar una clave XSRF. Mapearlo en una variable de ruta como esta es un diseño terrible:

http://www.someexample.com/xsrf/{xsrfKey}

Porque por naturaleza querrías pasar la clave xsrf a otro camino también, /login, /book-appointment etc. y usted no quiere ensuciar su bonita URL

Curiosamente agregarlo como un campo de objeto tampoco es apropiado, porque ahora en cada objeto json que pasa al servidor tiene que agregar el campo

{
  appointmentId : 23,
  name : 'Joe Citizen',
  xsrf : '...'
}

Ciertamente no desea agregar otro campo en su clase del lado del servidor que no tenga una asociación semántica directa con el objeto de dominio.

En mi opinión, la mejor manera de pasar su clave xsrf es a través de un encabezado HTTP. Muchas protecciones xsrf la biblioteca del marco web del lado del servidor admite esto. Por ejemplo, en Java Spring, puede pasarlo usando X-CSRF-TOKEN header.

La excelente capacidad de Angular de unir objetos JS a objetos UI significa que podemos deshacernos de la práctica de publicar formularios todos juntos, y publicar JSON en su lugar. JSON se puede des-serializar fácilmente en objetos del lado del servidor y soportar estructuras de datos complejas como mapas, matrices, objetos anidados, etc.

¿Cómo publicar matriz en un formulario de carga útil? Tal vez como esto:

shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday

O esto:

shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday

Ambos son de diseño pobre..

 0
Author: gerrytan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-26 11:47:42

Esto es lo que estoy haciendo para mi necesidad, donde necesito enviar los datos de inicio de sesión a la API como datos de formulario y el objeto Javascript(userData) se convierte automáticamente a datos codificados en URL

        var deferred = $q.defer();
        $http({
            method: 'POST',
            url: apiserver + '/authenticate',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            transformRequest: function (obj) {
                var str = [];
                for (var p in obj)
                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                return str.join("&");
            },
            data: userData
        }).success(function (response) {
            //logics
            deferred.resolve(response);
        }).error(function (err, status) {
           deferred.reject(err);
        });

Así es mi Userdata

var userData = {
                grant_type: 'password',
                username: loginData.userName,
                password: loginData.password
            }
 0
Author: Shubham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-25 07:56:42

El único thin que tiene que cambiar es usar la propiedad " params "en lugar de" data " cuando cree su objeto http http:

$http({
   method: 'POST',
   url: serviceUrl + '/ClientUpdate',
   params: { LangUserId: userId, clientJSON: clients[i] },
})

En el ejemplo anterior clients[i] es solo un objeto JSON (no serializado de ninguna manera). Si usa "params" en lugar de "data" angular serializará el objeto por usted usando htt httpParamSerializer: https://docs.angularjs.org/api/ng/service / htt httpParamSerializer

 -1
Author: Rafal Zajac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-13 16:05:17

Use el servicio AngularJS $http y use su método post o configure la función $http.

 -3
Author: Shivang Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-30 09:28:41