Http.post不接受flutter / dart中的内容类型application / query + json
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Http.post不接受flutter / dart中的内容类型application / query + json相关的知识,希望对你有一定的参考价值。
我正在使用flutter应用程序与天蓝色的db交谈。 cosmos db具有基于sql查询的rest api。内容类型应为application / query + json。我尝试使用邮递员连接到cosmos db,但效果很好,但是在颤抖中,我得到了例外,原因是
Bad state: Cannot set the body fields of a Request with content-type "application/query+json"
下面是示例http.post代码:
final http.Response response =
await http.post(
url,
headers: {<other headers>, 'Content-Type' : 'application/query+json'},
body: {
"query" : "<SQL Query>",
"parameters" : [<parameter name and value pairs>]
},
);
我已经在邮递员中对此进行了测试,并且可以正常工作。
如果http:dart包支持正文的内容类型application / query + json,那么我应该如何制定我的请求正文。
答案
尝试使用HttpClient:
Future<HttpClientResponse> httpRequest(String url, Map headers, Map body, {bool isQuery = false}) async {
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
headers.forEach((key, value) {
request.headers.set(key,value);
});
if(isQuery) {
request.headers.set('content-type', 'application/query+json');
request.headers.set('x-ms-documentdb-isquery', 'True');
}
if(body != null) {
request.add(utf8.encode(json.encode(body)));
}
HttpClientResponse response = await request.close();
httpClient.close();
return response;
}
注意,您需要将标题设置为1比1。
仅执行SELECT查询的便利功能:
Future<HttpClientResponse> doSELECTQuery(String userAgent, List<String> requiredColHeaders, String azTblName,
{Map<String,String> mapWHERE, String pKey, String pKey_Filter, Map<String, String> moreHeaders, String alternateCollectionUrl = null}) async {
String _collectionUrl;
String _host;
Uri uri = Uri.tryParse(alternateCollectionUrl);
if(uri != null) {
_host = uri.host;
}
_collectionUrl = alternateCollectionUrl;
} else {
_collectionUrl = this.collectionUrl;
_host = this.host;
}
String collectionPath = Uri.parse(_collectionUrl).path.substring(1); // remove leading "/"
Map<String, String> headers = {
"authorization": generateAuthToken(
"POST", "docs", collectionPath, HttpDate.format(DateTime.now()),
masterKey, "master"),
"x-ms-version": "2018-12-31",
"x-ms-date": HttpDate.format(DateTime.now()),
"user-agent": userAgent,
"Cache-Control": "no-cache",
"Accept": "application/json",
"Host": _host,
"x-ms-documentdb-partitionkey": pKey == null ? "" : "["" + pKey_Filter + ""]",
"x-ms-documentdb-query-enablecrosspartition": pKey == null ? "True" : ""
};
if(moreHeaders != null) {
headers.addAll(moreHeaders);
}
String strSELECT = "";
requiredColHeaders.forEach((col) {
strSELECT = strSELECT + "$azTblName["$col"],";
});
strSELECT = strSELECT.substring(0, strSELECT.length - 1); // remove trailing ","
String strWHERE = "";
if(mapWHERE != null) {
mapWHERE.forEach((col, value) {
strWHERE = strWHERE + "($azTblName["$col"] = "$value")AND";
});
strWHERE = strWHERE.substring(0, strWHERE.length - 3); // remove trailing "AND"
}
String strQuery = "SELECT $strSELECT FROM $azTblName";
if(strWHERE != "") {
strQuery = strQuery + " WHERE $strWHERE";
}
Map<String, dynamic> body = {
"query": strQuery,
"parameters": []
};
var response = await httpRequest(_collectionUrl + "/docs", headers, body, isQuery: true);
return response;
}
所有内容,以及生成授权令牌的功能:
import 'dart:convert';
import 'dart:io';
class azureCosmosHelper {
String masterKey = "<your_master_key>";
// Contains url to collection
String collectionUrl = "https://<your_database_account>.documents.azure.com/dbs/<your_database_id>/colls/<your_collection_id>";
String host = "<your_database_account>.documents.azure.com";
String pKey = "<your_partition_key>";
Future<void> getAzureDB() {
HttpClientResponse response = await doSELECTQuery("<userAgent>", List<String> tableColumns, "<tableName>",
pKey: this.pKey,
pKey_Filter: "<pKey_Filter>",
);
// parse response accordingly
}
Future<HttpClientResponse> doSELECTQuery(String userAgent, List<String> requiredColHeaders, String azTblName,
{Map<String,String> mapWHERE, String pKey, String pKey_Filter, Map<String, String> moreHeaders, String alternateCollectionUrl = null}) async {
String _collectionUrl;
String _host;
Uri uri = Uri.tryParse(alternateCollectionUrl);
if(uri != null) {
_host = uri.host;
}
_collectionUrl = alternateCollectionUrl;
} else {
_collectionUrl = this.collectionUrl;
_host = this.host;
}
String collectionPath = Uri.parse(_collectionUrl).path.substring(1); // remove leading "/"
Map<String, String> headers = {
"authorization": generateAuthToken(
"POST", "docs", collectionPath, HttpDate.format(DateTime.now()),
masterKey, "master"),
"x-ms-version": "2018-12-31",
"x-ms-date": HttpDate.format(DateTime.now()),
"user-agent": userAgent,
"Cache-Control": "no-cache",
"Accept": "application/json",
"Host": _host,
"x-ms-documentdb-partitionkey": pKey == null ? "" : "["" + pKey_Filter + ""]",
"x-ms-documentdb-query-enablecrosspartition": pKey == null ? "True" : ""
};
if(moreHeaders != null) {
headers.addAll(moreHeaders);
}
String strSELECT = "";
requiredColHeaders.forEach((col) {
strSELECT = strSELECT + "$azTblName["$col"],";
});
strSELECT = strSELECT.substring(0, strSELECT.length - 1); // remove trailing ","
String strWHERE = "";
if(mapWHERE != null) {
mapWHERE.forEach((col, value) {
strWHERE = strWHERE + "($azTblName["$col"] = "$value")AND";
});
strWHERE = strWHERE.substring(0, strWHERE.length - 3); // remove trailing "AND"
}
String strQuery = "SELECT $strSELECT FROM $azTblName";
if(strWHERE != "") {
strQuery = strQuery + " WHERE $strWHERE";
}
Map<String, dynamic> body = {
"query": strQuery,
"parameters": []
};
var response = await httpRequest(_collectionUrl + "/docs", headers, body, isQuery: true);
return response;
}
Future<HttpClientResponse> httpRequest(String url, Map headers, Map body, {bool isQuery = false}) async {
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
headers.forEach((key, value) {
request.headers.set(key,value);
});
if(isQuery) {
request.headers.set('content-type', 'application/query+json');
request.headers.set('x-ms-documentdb-isquery', 'True');
}
if(body != null) {
request.add(utf8.encode(json.encode(body)));
}
HttpClientResponse response = await request.close();
httpClient.close();
return response;
}
//Generates authorization token
String generateAuthToken(String verb, String resourceType, String resourceLink, String date, String key, String keyType, {String tokenVer="1.0"}) {
String payload=verb.toLowerCase()+"
"
+resourceType.toLowerCase()+"
"
+resourceLink+"
"
+date.toLowerCase()+"
"
+""+"
";
var key_decode = base64.decode(key);
Hmac hmac = new Hmac(sha256, key_decode);
var messageBytes = utf8.encode(payload);
Digest digest = hmac.convert(messageBytes);
String signature = base64.encode(digest.bytes);
return Uri.encodeComponent("type="+keyType+"&ver="+tokenVer+"&sig="+signature);
}
}
以上是关于Http.post不接受flutter / dart中的内容类型application / query + json的主要内容,如果未能解决你的问题,请参考以下文章
为啥我在flutter中更新http包后不能在http.post方法中放一个字符串
Flutter/Dart http POST 重定向通过 GET 发送正文