Senden Sie eine x-www-form-urlencodierte Anfrage von React Native

102

Ich habe einige Parameter, die ich formularcodiert auf meinen Server POSTEN möchte:

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

Ich sende meine Anfrage (derzeit ohne Parameter) so

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
  }); 

Wie kann ich die formularcodierten Parameter in die Anfrage aufnehmen?

texas697
quelle
2
Bitte aktualisieren Sie Ihre ausgewählte Antwort auf die tatsächlich richtige Antwort.
Albert Renshaw

Antworten:

-46

Zum Hochladen formularcodierter POST-Anforderungen empfehle ich die Verwendung des FormData- Objekts.

Beispielcode:

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
quelle
77
Dies ist nicht application / x-www-form-urlencoded, sondern multipart / form-data
Haha TTpro
Ich stimme zu, diese Anfrage hat nicht "application / x-www-form-urlencoded" als Inhaltstyp, sondern "multipart / form-data".
b4stien
2
@Mzn - Wenn Sie beispielsweise einen Dienst wie die Closure Compiler-API von Google verwenden , akzeptiert der Server nur application/x-www-form-urlencoded, nicht multipart/form-data.
Sphinxxx
12
Wie kann dies die akzeptierte Antwort sein? Es ist einfach falsch in Bezug auf die eigentliche Frage ...
oabojad
1
Sie müssen zusätzliche Verarbeitung auf dem Server durchführen, wenn Sie FormData-Objekte senden. Verarbeiten Sie ein reguläres Formular grundsätzlich so, als wäre es ein Datei-Upload. Was ist der Vorteil von FormData-Objekten für reguläre Formulare?
MarsAndBack
249

Sie müssen die x-www-form-urlencodierte Nutzlast selbst wie folgt zusammenstellen:

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
})

Beachten Sie, dass , wenn Sie mit waren fetchin einem (ausreichend modern) Browser, anstelle von nativem Reagieren Sie stattdessen ein schaffen könnten URLSearchParamsObjekt und verwenden , die als der Körper, da die Standard - Fetch besagt , dass , wenn die bodya - URLSearchParamsObjekt dann sollte es als serialisiert werden application/x-www-form-urlencoded. In React Native ist dies jedoch nicht möglich,URLSearchParams da React Native nicht implementiert ist .

Narongdej Sarnsuwan
quelle
50
Der ES6-Weg:const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
Eric Burel
Diese Polyfüllung für URLSearchParams github.com/WebReflection/url-search-params funktioniert möglicherweise für React Native-Browser oder ältere Browser.
Bucabay
7
Ein anderer ähnlicher Weg:const formBody = Object.entries(details).map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value)).join('&')
Flynn Hou
1
Es konvertiert den Parameter json array in string
atulkhatri
47

Verwenden 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
quelle
Das macht das, was ich beabsichtigt habe, da PHP7 die FormData-Codierung nicht richtig analysiert hat. Ich hoffe, es bekommt mehr Stimmen für die Jungs und Mädels von PHP
cav_dan
6
-1; URLSearchParamsexistiert nicht in React Native. (Siehe github.com/facebook/react-native/issues/9596. )
Mark Amery
3
Es ist jetzt Teil von React Native. Rufen Sie toString()die Daten unbedingt auf, bevor Sie die Anforderung weiterleiten body.
Phatmann
Selbst nachdem RN gesagt hat, dass sie implementiert wurden URLSearchParams, habe ich immer noch Probleme. Ich denke nicht, dass es in Übereinstimmung mit der Spezifikation implementiert ist und es ist nicht nur ein Drop-in-Lösung. Bitte lesen Sie URLSearchParams 'Fehler: nicht implementiert', wenn Sie versuchen, vorbeizuschauenURLSearchParams und weiterhin Probleme haben.
Null298
14

Hab das gerade gemacht und UrlSearchParams hat den Trick gemacht Hier ist mein Code, wenn er jemandem hilft

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;
};
PA
quelle
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))
    })

Nach der Verwendung von npm frage ich ab - speichern Sie es funktioniert gut.

Akshita Agarwal
quelle
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 ist so hilfreich für mich und funktioniert ohne Fehler

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

mahsa k
quelle
3

Benutz einfach

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
quelle
1
Dies sollte als die richtige Antwort darauf markiert werden. Es ist so einfach zu bedienen und ohne seltsame Dinge zu machen.
Augusto Gonzalez
1

Im ursprünglichen Beispiel haben Sie eine transformRequestFunktion, die ein Objekt in formularcodierte Daten konvertiert.

Im überarbeiteten Beispiel haben Sie das ersetzt, durch JSON.stringifydas ein Objekt in JSON konvertiert wird.

In beiden Fällen haben Sie 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'so dass Sie behaupten , in beiden Fällen Formulare codierte Daten zu senden.

Verwenden Sie stattdessen Ihre Formularcodierungsfunktion JSON.stringify.


Neu aktualisieren:

In Ihrem ersten fetchBeispiel legen Sie bodyden Wert als JSON fest.

Jetzt haben Sie eine formularcodierte Version erstellt, aber anstatt bodydiesen Wert festzulegen, haben Sie ein neues Objekt erstellt und die formularcodierten Daten als Eigenschaft dieses Objekts festgelegt.

Erstellen Sie dieses zusätzliche Objekt nicht. Weisen Sie einfach Ihren Wert zu body.

QUentin
quelle
Hallo @Quentin. Ich habe die Frage nur radikal verkleinert, um sie zu einer nützlicheren Referenz für zukünftige Leser zu machen. Dabei habe ich Ihre Antwort, die sich auf die Details und Fehler des Originalcodes des Fragestellers bezieht, vollständig ungültig gemacht. Ich nehme an, Sie haben das Recht, meine Bearbeitung zurückzusetzen, wenn Sie möchten - theoretisch sind wir nicht dazu gedacht, Änderungen vorzunehmen, die die Antwort ungültig machen, was ich getan habe -, aber wenn Sie dazu bereit wären, denke ich Es wäre besser, stattdessen nur diese Antwort zu löschen. IMO ist die Frage ohne den Angular-Code oder den vorherigen fehlgeschlagenen Versuch viel schöner.
Mark Amery
1

Wenn Sie JQuery verwenden, funktioniert dies auch.

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

Sie müssen jQuery nicht verwenden querystringoder die Nutzdaten manuell zusammenstellen. URLSearchParamsist ein langer Weg und hier ist eine der prägnantesten Antworten mit dem vollständigen Anforderungsbeispiel:

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
  });

Ja, Sie können stattdessen Axios oder was auch immer Sie wollen verwenden fetch.

PS URLSearchParamswird im IE nicht unterstützt.

Neurotransmitter
quelle
0

Gemäß der Spezifikation erhalten Sie bei Verwendung encodeURIComponentkeine konforme Abfragezeichenfolge. Es sagt aus:

  1. Kontrollnamen und -werte werden maskiert. Leerzeichen werden ersetzt durch+ und dann werden reservierte Zeichen maskiert, wie in [RFC1738], Abschnitt 2.2 beschrieben: Nicht alphanumerische Zeichen werden durch %HHein Prozentzeichen und zwei hexadezimale Ziffern ersetzt, die den ASCII-Code des Zeichens darstellen. Zeilenumbrüche werden als "CR LF" -Paare (dh %0D%0A) dargestellt.
  2. Die Kontrollnamen / -werte werden in der Reihenfolge aufgelistet, in der sie im Dokument angezeigt werden. Der Name wird vom Wert durch getrennt =und Name / Wert-Paare werden durch voneinander getrennt &.

Das Problem ist, encodeURIComponentcodiert Leerzeichen %20nicht +.

Der Formkörper sollte unter Verwendung einer Variation der encodeURIComponentin den anderen Antworten gezeigten Methoden codiert werden .

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
quelle
0

Sie können die React-Native-Easy-App verwenden , mit der sich HTTP-Anfragen einfacher senden und Abfanganfragen formulieren lassen.

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
quelle