我如何POST一个x-www-form-urlencoded请求使用Fetch?

我有一些参数,我想POST表单编码到我的服务器:

{
'userName': 'test@gmail.com',
'password': 'Password!',
'grant_type': 'password'
}

我像这样发送我的请求(目前没有参数)

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

如何在请求中包含表单编码的参数?

261802 次浏览

在原来的例子中,你有一个transformRequest函数,它将对象转换为表单编码数据。

在修改后的示例中,您已经将其替换为JSON.stringify,它将对象转换为JSON。

在这两种情况下,你都有'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',所以你是声称来发送表单编码的数据。

使用你的表单编码函数而不是JSON.stringify


重新更新:

在第一个fetch示例中,将body设置为JSON值。

现在你已经创建了一个Form Encoded版本,但是不是将body设置为该值,而是创建了一个新对象,并将Form Encoded数据设置为该对象的属性。

不要创建额外的对象。只需将值赋给body即可。

对于上传Form-Encoded POST请求,我建议使用FormData对象。

示例代码:

var params = {
userName: 'test@gmail.com',
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);

你必须自己把x-www-form-urlencoded有效负载放在一起,就像这样:

var details = {
'userName': 'test@gmail.com',
'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
})

注意,如果你是在一个(足够现代的)浏览器中使用fetch,而不是React Native,你可以创建一个URLSearchParams对象并将其用作主体,因为获取标准状态如果body是一个URLSearchParams对象,那么它应该被序列化为application/x-www-form-urlencoded。然而,你不能在React Native中这样做,因为React Native 没有实现URLSearchParams

使用URLSearchParams

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

var data = new URLSearchParams();
data.append('userName', 'test@gmail.com');
data.append('password', 'Password');
data.append('grant_type', 'password');

只使用

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

如果你正在使用JQuery,这也是有效的。

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

根据规范,使用encodeURIComponent不会给你一个符合要求的查询字符串。州:

  1. 控件名称和值被转义。空格字符替换为+,然后保留字符被转义,如[RFC1738]章节2.2所述:非字母数字字符被%HH、一个百分号和两个表示字符的ASCII码的十六进制数字所取代。换行符表示为“CR LF”对(即%0D%0A)。
  2. 控件名称/值按照它们在文档中出现的顺序列出。名称与值之间用=分隔,名称/值对之间用&分隔。

问题是,encodeURIComponent将空格编码为%20,而不是+

表单主体应该使用其他答案中显示的encodeURIComponent方法的变体进行编码。

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"
只是这样做,UrlSearchParams做的把戏 这是我的代码,如果它有助于某人

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

更简单:

fetch('https://example.com/login', {
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'userName': 'test@gmail.com',
'password': 'Password!',
'grant_type': 'password'
})
});

文档:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

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

使用NPM I querystring—保存后,它的工作很好。

var details = {
'userName': 'test@gmail.com',
'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
})

它对我很有帮助,而且没有任何错误

参考:https://gist.github.com/milon87/f391e54e64e32e1626235d4dc4d16dc8

你可以使用react-native-easy-app更容易发送http请求和制定拦截请求。

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

不需要使用jQuery, querystring或手动组装有效负载。URLSearchParams是一种方法,这里是一个最简洁的答案与完整的请求示例:

fetch('https://example.com/login', {
method: 'POST',
body: new URLSearchParams({
param: 'Some value',
anotherParam: 'Another value'
})
})
.then(response => {
// Do stuff with the response
});

同样的技术使用async / await

const login = async () => {
const response = await fetch('https://example.com/login', {
method: 'POST',
body: new URLSearchParams({
param: 'Some value',
anotherParam: 'Another value'
})
})


// Do stuff with the response
}

是的,您可以使用Axios或任何其他HTTP客户端库来代替本机fetch

只需将主体设置为如下所示

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

然后

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

fetch包装在一个简单的函数中

async function post_www_url_encdoded(url, data) {
const body = new URLSearchParams();
for (let key in data) {
body.append(key, data[key]);
}
return await fetch(url, { method: "POST", body });
}


const response = await post_www_url_encdoded("https://example.com/login", {
"name":"ali",
"password": "1234"});
if (response.ok){ console.log("posted!"); }


你可以在下面的例子中使用FormDataURLSearchParams来发布application/x-www-form-urlencoded:

如果你有一个表格:

<form>
<input name="username" type="text" />
<input name="password" type="password" />
<button type="submit">login</button>
</form>

您可以添加使用下面的JS来提交表单。

const form = document.querySelector("form");


form.addEventListener("submit", async () => {
const formData = new FormData(form);
try {
await fetch("https://example.com/login", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams(formData),
});
} catch (err) {
console.log(err);
}
});

你可以使用UrlSearchParams,然后像这样做一个toString():

这里有一个简单的方法:

fetch('https://example.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: new UrlSearchParams(...{
'userName': 'test@gmail.com',
'password': 'Password!',
'grant_type': 'password'
})
.toString()
})
.then(res => {
//Deal with response:
})