Publique una solicitud x-www-form-urlencoded de React Native

103

Tengo algunos parámetros que quiero POST codificados en forma en mi servidor:

{
    'userName': '[email protected]',
    'password': 'Password!',
    'grant_type': 'password'
}

Estoy enviando mi solicitud (actualmente sin parámetros) así

var obj = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  },
};
fetch('https://example.com/login', obj)
  .then(function(res) {
    // Do stuff with result
  }); 

¿Cómo puedo incluir los parámetros codificados por formulario en la solicitud?

texas697
fuente
2
Actualice su respuesta seleccionada a la respuesta correcta real.
Albert Renshaw

Respuestas:

-47

Para cargar solicitudes POST codificadas en formulario, recomiendo usar el objeto FormData .

Código de ejemplo:

var params = {
    userName: '[email protected]',
    password: 'Password!',
    grant_type: 'password'
};

var formData = new FormData();

for (var k in params) {
    formData.append(k, params[k]);
}

var request = {
    method: 'POST',
    headers: headers,
    body: formData
};

fetch(url, request);
David Kay
fuente
78
Esto no es application / x-www-form-urlencoded, sino multipart / form-data
Haha TTpro
Estoy de acuerdo, esta solicitud no tendrá "application / x-www-form-urlencoded" como Content-Type sino "multipart / form-data".
b4stien
2
@Mzn: por ejemplo, si está utilizando un servicio como la API del compilador de cierre de Google , el servidor solo aceptará application/x-www-form-urlencoded, no multipart/form-data.
Sphinxxx
12
¿Cómo puede ser esta la respuesta aceptada? Es simplemente incorrecto con respecto a la pregunta real ...
Żabojad
1
Tendrá que realizar un procesamiento adicional en el servidor al enviar objetos FormData. Básicamente, procese un formulario regular como si fuera una carga de archivo. ¿Cuál es la ventaja de los objetos FormData para formularios regulares?
MarsAndBack
250

Tienes que armar tú mismo la carga útil x-www-form-urlencoded, así:

var details = {
    'userName': '[email protected]',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('https://example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: formBody
})

Tenga en cuenta que si estuviera usando fetchun navegador (suficientemente moderno), en lugar de React Native, podría crear un URLSearchParamsobjeto y usarlo como cuerpo, ya que el Fetch Standard establece que si bodyes un URLSearchParamsobjeto, entonces debe serializarse como application/x-www-form-urlencoded. Sin embargo, no puede hacer esto en React Native porque React Native no se implementaURLSearchParams .

Narongdej Sarnsuwan
fuente
50
El camino ES6:const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
Eric Burel
Este polyfill para URLSearchParams github.com/WebReflection/url-search-params puede funcionar para React Native o navegadores más antiguos.
bucabay
7
Otra forma similar:const formBody = Object.entries(details).map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value)).join('&')
Flynn Hou
1
Convierte el parámetro de matriz json en una cadena
atulkhatri
47

Utilizar URLSearchParams

https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams

var data = new URLSearchParams();
data.append('userName', '[email protected]');
data.append('password', 'Password');
data.append('grant_type', 'password');
Nicu Criste
fuente
esto hace lo que pretendía, ya que php7 no estaba analizando correctamente la codificación FormData. Espero que obtenga más votos para los chicos y chicas de PHP
cav_dan
6
-1; URLSearchParamsno existe en React Native. (Ver github.com/facebook/react-native/issues/9596. )
Mark Amery
3
Ahora es parte de React Native. Asegúrese de consultar toString()los datos antes de pasar su solicitud body.
phatmann
Incluso después de que RN dijo que implementaron URLSearchParams, sigo teniendo problemas. No creo que esté implementado de acuerdo con las especificaciones y no es solo una solución inmediata. Considere leer URLSearchParams 'Error: no implementado' si intenta ingresarURLSearchParams y aún tiene problemas.
zero298
14

Acabo de hacer esto y UrlSearchParams hizo el truco Aquí está mi código si ayuda a alguien

import 'url-search-params-polyfill';
const userLogsInOptions = (username, password) => {



// const formData = new FormData();
  const formData = new URLSearchParams();
  formData.append('grant_type', 'password');
  formData.append('client_id', 'entrance-app');
  formData.append('username', username);
  formData.append('password', password);
  return (
    {
      method: 'POST',
      headers: {
        // "Content-Type": "application/json; charset=utf-8",
        "Content-Type": "application/x-www-form-urlencoded",
    },
      body: formData.toString(),
    json: true,
  }
  );
};


const getUserUnlockToken = async (username, password) => {
  const userLoginUri = `${scheme}://${host}/auth/realms/${realm}/protocol/openid-connect/token`;
  const response = await fetch(
    userLoginUri,
    userLogsInOptions(username, password),
  );
  const responseJson = await response.json();
  console.log('acces_token ', responseJson.access_token);
  if (responseJson.error) {
    console.error('error ', responseJson.error);
  }
  console.log('json ', responseJson);
  return responseJson.access_token;
};
Pensilvania
fuente
5
*/ import this statement */
import qs from 'querystring'

fetch("*your url*", {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
            body: qs.stringify({ 
                username: "akshita",
                password: "123456",
            })
    }).then((response) => response.json())
      .then((responseData) => {
         alert(JSON.stringify(responseData))
    })

Después de usar npm i querystring --save , funciona bien.

Akshita Agarwal
fuente
5
var details = {
    'userName': '[email protected]',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('http://identity.azurewebsites.net' + '/token', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: formBody
})

es muy útil para mí y funciona sin ningún error

referencia: https://gist.github.com/milon87/f391e54e64e32e1626235d4dc4d16dc8

mahsa k
fuente
3

Solo usa

import  qs from "qs";
 let data = {
        'profileId': this.props.screenProps[0],
        'accountId': this.props.screenProps[1],
        'accessToken': this.props.screenProps[2],
        'itemId': this.itemId
    };
    return axios.post(METHOD_WALL_GET, qs.stringify(data))
mojTaba Shayegh
fuente
1
Esto debe marcarse como la respuesta correcta. Es muy fácil de usar y sin cosas raras que hacer.
Augusto González
1

En el ejemplo original, tiene una transformRequestfunción que convierte un objeto en datos codificados por formulario.

En el ejemplo revisado, ha reemplazado el JSON.stringifyque convierte un objeto en JSON.

En ambos casos lo ha hecho, 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'por lo que afirma estar enviando datos codificados en formulario en ambos casos.

Utilice su función de codificación de formulario en lugar de JSON.stringify.


Volver a actualizar:

En su primer fetchejemplo, establece el bodyvalor JSON.

Ahora ha creado una versión de Form Encoded, pero en lugar de establecer bodyque sea ese valor, ha creado un nuevo objeto y ha establecido los datos de Form Encoded como una propiedad de ese objeto.

No cree ese objeto extra. Simplemente asigne su valor a body.

Quentin
fuente
Hola @Quentin. Simplemente reduje radicalmente la pregunta para intentar convertirla en una referencia más útil para futuros lectores; al hacerlo, he invalidado por completo su respuesta, que se refiere a los detalles y errores del código original del autor de la pregunta. Supongo que tiene derecho a revertir mi edición si lo desea; en teoría, no estamos destinados a realizar ediciones que invaliden la respuesta, que es lo que he hecho, pero si está dispuesto a hacerlo, creo que Sería mejor eliminar esta respuesta en su lugar; En mi opinión, la pregunta es mucho mejor sin el código angular o el intento fallido anterior.
Mark Amery
1

Si está utilizando JQuery, esto también funciona.

fetch(url, {
      method: 'POST', 
      body: $.param(data),
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
      }
})
deseoso
fuente
1

No es necesario usar jQuery querystringo ensamblar manualmente la carga útil. URLSearchParamses un camino a seguir y aquí está una de las respuestas más concisas con el ejemplo de solicitud completo:

fetch('https://example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    'param': 'Some value',
    'another_param': 'Another value'
  })
})
  .then(res => {
    // Do stuff with the result
  });

Sí, puedes usar Axios o lo que quieras en lugar de fetch.

PS URLSearchParamsno es compatible con IE.

Neurotransmisor
fuente
0

De acuerdo con la especificación , el uso encodeURIComponentno le dará una cadena de consulta conforme. Afirma:

  1. Los nombres y valores de los controles se escapan. Los caracteres de espacio se reemplazan+ y luego los caracteres reservados se escapan como se describe en [RFC1738], sección 2.2: Los caracteres no alfanuméricos se reemplazan por %HHun signo de porcentaje y dos dígitos hexadecimales que representan el código ASCII del carácter. Los saltos de línea se representan como pares "CR LF" (es decir, %0D%0A).
  2. Los nombres / valores de control se enumeran en el orden en que aparecen en el documento. El nombre está separado del valor por =y los pares de nombre / valor están separados entre sí por& .

El problema es, encodeURIComponent codifica espacios para ser %20, no +.

El cuerpo del formulario debe codificarse utilizando una variación de los encodeURIComponentmétodos que se muestran en las otras respuestas.

const formUrlEncode = str => {
  return str.replace(/[^\d\w]/g, char => {
    return char === " " 
      ? "+" 
      : encodeURIComponent(char);
  })
}

const data = {foo: "bar߃©˙∑  baz", boom: "pow"};

const dataPairs = Object.keys(data).map( key => {
  const val = data[key];
  return (formUrlEncode(key) + "=" + formUrlEncode(val));
}).join("&");

// dataPairs is "foo=bar%C3%9F%C6%92%C2%A9%CB%99%E2%88%91++baz&boom=pow"
papiro
fuente
0

Puede usar react-native-easy-app que es más fácil para enviar solicitudes http y formular solicitudes de interceptación.

import { XHttp } from 'react-native-easy-app';

* Synchronous request
const params = {name:'rufeng',age:20}
const response = await XHttp().url(url).param(params).formEncoded().execute('GET');
const {success, json, message, status} = response;


* Asynchronous requests
XHttp().url(url).param(params).formEncoded().get((success, json, message, status)=>{
    if (success){
       this.setState({content: JSON.stringify(json)});
    } else {
       showToast(msg);
    }
});
rufeng
fuente