Bagaimana cara memposting permintaan x-www-form-urlencoded menggunakan Ambil?

111

Saya memiliki beberapa parameter yang saya ingin POST dikodekan ke server saya:

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

Saya mengirimkan permintaan saya (saat ini tanpa parameter) seperti ini

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

Bagaimana cara menyertakan parameter yang dikodekan formulir dalam permintaan?

texas697
sumber
3
Harap perbarui jawaban yang Anda pilih menjadi jawaban yang benar.
Albert Renshaw

Jawaban:

-58

Untuk mengunggah permintaan POST Berenkode Formulir, saya merekomendasikan menggunakan objek FormData .

Kode contoh:

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
sumber
86
Ini bukan application / x-www-form-urlencoded, tetapi multipart / form-data
Haha TTpro
Saya setuju, permintaan ini tidak akan memiliki "application / x-www-form-urlencoded" sebagai Content-Type tetapi "multipart / form-data".
b4stien
2
@Mzn - Misalnya jika Anda menggunakan layanan seperti Closure Compiler API Google , server hanya akan menerima application/x-www-form-urlencoded, tidak multipart/form-data.
Sphinxxx
12
Bagaimana ini bisa menjadi jawaban yang diterima? Ini jelas salah tentang pertanyaan yang sebenarnya ...
Żabojad
1
Anda harus melakukan pemrosesan ekstra di server, saat mengirimkan objek FormData. Pada dasarnya proses formulir biasa seolah-olah itu adalah unggahan file. Apa keuntungan dari objek FormData untuk bentuk biasa?
MarsAndBack
266

Anda harus mengumpulkan sendiri muatan x-www-form-urlencoded, seperti ini:

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

Perhatikan bahwa jika Anda menggunakan fetchbrowser (cukup modern), alih-alih React Native, Anda dapat membuat URLSearchParamsobjek dan menggunakannya sebagai badan, karena Standar Pengambilan menyatakan bahwa jika bodyadalah URLSearchParamsobjek maka itu harus diserialkan sebagai application/x-www-form-urlencoded. Namun, Anda tidak dapat melakukan ini di React Native karena React Native tidak diimplementasikanURLSearchParams .

Narongdej Sarnsuwan
sumber
51
Cara ES6:const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
Eric Burel
Polyfill untuk URLSearchParams github.com/WebReflection/url-search-params ini dapat bekerja untuk React Native atau browser lama.
bucabay
7
Cara lain yang serupa:const formBody = Object.entries(details).map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value)).join('&')
Flynn Hou
1
Ini mengubah parameter array json menjadi string
atulkhatri
Saya telah mencoba semua metode yang disarankan. Tidak peduli apa yang saya lakukan, fetch menyuntikkan kutipan yang tidak diinginkan ke seluruh tubuh, langsung ke dalam string - kutipan pembuka dan penutup. Hal ini menyebabkan parameter diurai, misalnya seperti ini: '"mykey': 'myvalue"'. Yang membuat pemanggilan API tidak mungkin, karena ini tentu saja hanya menghasilkan 400 kesalahan (server mengenali mykey, bukan "mykey). Ada orang lain yang mengalami masalah ini? Mengherankan.
Dave Munger
49

Menggunakan 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
sumber
ini membuat apa yang saya inginkan, karena php7 tidak mengurai encoding FormData dengan benar. Saya berharap ini mendapat lebih banyak suara untuk anak laki-laki dan
perempuan
6
-1; URLSearchParamstidak ada di React Native. (Lihat github.com/facebook/react-native/issues/9596. )
Mark Amery
3
Ini adalah bagian dari React Native sekarang. Pastikan untuk memanggil toString()data sebelum meneruskan permintaannya body.
phatmann
Bahkan setelah RN mengatakan bahwa mereka menerapkan URLSearchParams, saya masih mengalami masalah. Saya tidak berpikir itu diterapkan sesuai dengan spesifikasi dan itu bukan hanya solusi setetes. Harap pertimbangkan untuk membaca URLSearchParams 'Error: not implement' jika Anda mencoba untuk mampir URLSearchParamsdan masih mengalami masalah.
nol298
14

Baru saja melakukan ini dan UrlSearchParams melakukan trik. Ini kode saya jika membantu seseorang

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

Setelah menggunakan npm i querystring - simpan itu berfungsi dengan baik.

Akshita Agarwal
sumber
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
})

ini sangat membantu saya dan berfungsi tanpa kesalahan

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

mahsa k
sumber
3

Gunakan saja

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
sumber
1
Ini harus ditandai sebagai jawaban yang benar itu. Sangat mudah digunakan dan tidak ada barang aneh untuk dibuat.
Augusto Gonzalez
3

Tidak perlu menggunakan jQuery, querystringatau merakit payload secara manual. URLSearchParamsadalah cara untuk pergi dan inilah salah satu jawaban paling ringkas dengan contoh permintaan lengkap:

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

Ya, Anda dapat menggunakan Axios atau apa pun yang Anda inginkan fetch.

PS URLSearchParamstidak didukung di IE.

Neurotransmitter
sumber
2

Atur saja bodinya sebagai berikut

var reqBody = "username="+username+"&password="+password+"&grant_type=password";

kemudian

fetch('url', {
      method: 'POST',
      headers: {
          //'Authorization': 'Bearer token',
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      },
      body: reqBody
  }).then((response) => response.json())
      .then((responseData) => {
          console.log(JSON.stringify(responseData));
      }).catch(err=>{console.log(err)})
Hazem AbdelHamid
sumber
1

Dalam contoh asli Anda memiliki transformRequestfungsi yang mengonversi objek menjadi data yang dikodekan formulir.

Dalam contoh yang direvisi Anda telah mengganti JSON.stringifyyang mengonversi objek menjadi JSON.

Dalam kedua kasus yang Anda miliki 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'sehingga Anda mengklaim mengirim data yang dikodekan Formulir dalam kedua kasus.

Gunakan fungsi Pengkodean Formulir Anda, bukan JSON.stringify.


Pembaruan ulang:

Dalam fetchcontoh pertama Anda, Anda menyetel bodymenjadi nilai JSON.

Sekarang Anda telah membuat versi yang dikodekan formulir, tetapi alih-alih menyetel bodyke nilai itu, Anda telah membuat objek baru dan menyetel data yang dikodekan formulir sebagai properti objek itu.

Jangan buat objek ekstra itu. Tetapkan saja nilai Anda ke body.

Quentin
sumber
Hai @Quentin. Saya baru saja merampingkan pertanyaan secara radikal untuk mencoba dan menjadikannya referensi yang lebih berguna bagi pembaca di masa mendatang; dalam melakukannya, saya telah sepenuhnya membatalkan jawaban Anda yang mengacu pada detail dan bug dari kode asli penanya. Saya kira Anda memiliki hak untuk mengembalikan suntingan saya jika Anda mau - secara teori, kami tidak dimaksudkan untuk membuat suntingan yang membuat jawaban tidak valid, itulah yang telah saya lakukan - tetapi jika Anda mau, saya pikir itu lebih baik hanya menghapus jawaban ini saja; IMO pertanyaannya jauh lebih bagus tanpa kode Angular atau upaya gagal sebelumnya.
Mark Amery
1

Jika Anda menggunakan JQuery, ini juga berfungsi ..

fetch(url, {
      method: 'POST', 
      body: $.param(data),
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
      }
})
plin-plan
sumber
0

Menurut spesifikasi , menggunakan encodeURIComponenttidak akan memberi Anda string kueri yang sesuai. Ini menyatakan:

  1. Nama dan nilai kontrol di-escape. Karakter spasi diganti oleh+ , dan karakter yang dicadangkan dikeluarkan seperti yang dijelaskan di [RFC1738], bagian 2.2: Karakter non-alfanumerik diganti dengan %HH, tanda persen dan dua digit heksadesimal yang mewakili kode ASCII dari karakter tersebut. Jeda baris direpresentasikan sebagai pasangan "CR LF" (yaitu, %0D%0A).
  2. Nama / nilai kontrol dicantumkan dalam urutan kemunculannya di dokumen. Nama dipisahkan dari nilai oleh =dan pasangan nama / nilai dipisahkan satu sama lain oleh &.

Masalahnya adalah, encodeURIComponentmengkodekan spasi menjadi %20, bukan +.

Formulir-isi harus diberi kode menggunakan variasi encodeURIComponentmetode yang ditunjukkan pada jawaban lain.

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

Anda dapat menggunakan react-native-easy-app yang lebih mudah untuk mengirim permintaan http dan merumuskan permintaan intersepsi.

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
sumber