【问题标题】:Http.post not accepting content type application/query+json in flutter/dartHttp.post 不接受 Flutter/dart 中的内容类型 application/query+json
【发布时间】:2020-08-13 12:56:49
【问题描述】:

我正在使用 Flutter 应用程序与 azure cosmos 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 的正文,我应该如何制定我的请求正文。

【问题讨论】:

    标签: rest http dart


    【解决方案1】:

    尝试使用 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()+"\n"
            +resourceType.toLowerCase()+"\n"
            +resourceLink+"\n"
            +date.toLowerCase()+"\n"
            +""+"\n";
    
        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);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 2017-03-26
      • 2015-04-07
      • 2022-12-22
      • 2015-06-21
      • 2012-08-23
      • 1970-01-01
      相关资源
      最近更新 更多