简体   繁体   English

HTTP POST 与 Json 在身体上 - 颤振/飞镖

[英]HTTP POST with Json on Body - Flutter/Dart

This is my code to make a request to an API:这是我向 API 发出请求的代码:

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

Future<http.Response> postRequest () async {
  var url ='https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  var body = jsonEncode({ 'data': { 'apikey': '12345678901234567890' } });

  print("Body: " + body);

  http.post(url,
      headers: {"Content-Type": "application/json"},
      body: body
  ).then((http.Response response) {
    print("Response status: ${response.statusCode}");
    print("Response body: ${response.contentLength}");
    print(response.headers);
    print(response.request);

  });
  }

I have a problem with the response from the request, where its suppose to have a body with json, but something went wrong and i think is with the json that i send on the body request, because it is a nested json object, and the value of the key is a json object. I have a problem with the response from the request, where its suppose to have a body with json, but something went wrong and i think is with the json that i send on the body request, because it is a nested json object, and the密钥的值为 json object。 i would love to know how i can parse the json right and insert into body of the request.我很想知道如何正确解析 json 并插入到请求正文中。

this is the header response:这是 header 响应:

 {set-cookie: JSESSIONID=DA65FBCBA2796D173F8C8D78AD87F9AD;path=/testes2/;HttpOnly, last-modified: Thu, 10 May 2018 17:15:13 GMT, cache-control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0, date: Thu, 10 May 2018 17:15:13 GMT, content-length: 0, pragma: no-cache, content-type: text/html, server: Apache-Coyote/1.1, expires: Tue, 03 Jul 2001 06:00:00 GMT}

and this is how is suppose to be:这就是假设的方式:

Server: Apache-Coyote/1.1
Expires: Tue, 03 Jul 2001 06:00:00 GMT
Last-Modified: Thu, 10 May 2018 17:17:07 GMT
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Vary: Accept-Encoding
Set-Cookie: JSESSIONID=84813CC68E0E8EA6021CB0B4C2F245BC;path=/testes2/;HttpOnly
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked

the body response came empty and i think its because the body i sent on the request, can anyone help me with the nested json object in value??正文响应为空,我认为这是因为我根据请求发送的正文,任何人都可以帮助我处理嵌套的 json object 的价值吗?

SCREENSHOT OF POSTMAN: POSTMAN 的屏幕截图:

This works!这行得通!

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

Future<http.Response> postRequest () async {
  var url ='https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';

  Map data = {
    'apikey': '12345678901234567890'
  }
  //encode Map to JSON
  var body = json.encode(data);

  var response = await http.post(url,
      headers: {"Content-Type": "application/json"},
      body: body
  );
  print("${response.statusCode}");
  print("${response.body}");
  return response;
}

OK, finally we have an answer...好吧,终于有答案了……

You are correctly specifying headers: {"Content-Type": "application/json"}, to set your content type.您正确指定headers: {"Content-Type": "application/json"},以设置您的内容类型。 Under the hood either the package http or the lower level dart:io HttpClient is changing this to application/json; charset=utf-8在引擎盖下,包http或较低级别的dart:io HttpClient正在将其更改为application/json; charset=utf-8 application/json; charset=utf-8 . application/json; charset=utf-8 However, your server web application obviously isn't expecting the suffix.但是,您的服务器 Web 应用程序显然不需要后缀。

To prove this I tried it in Java, with the two versions为了证明这一点,我在 Java 中尝试了它,有两个版本

conn.setRequestProperty("content-type", "application/json; charset=utf-8"); // fails
conn.setRequestProperty("content-type", "application/json"); // works

Are you able to contact the web application owner to explain their bug?您是否可以联系 Web 应用程序所有者来解释他们的错误? I can't see where Dart is adding the suffix, but I'll look later.我看不到 Dart 在哪里添加后缀,但我稍后再看。

EDIT Later investigation shows that it's the http package that, while doing a lot of the grunt work for you, is adding the suffix that your server dislikes.编辑后来的调查表明,它是http包,虽然为你做了很多繁重的工作,但它正在添加你的服务器不喜欢的后缀。 If you can't get them to fix the server then you can by-pass http and use the dart:io HttpClient directly.如果你不能让他们修复服务器,那么你可以绕过http并直接使用dart:io HttpClient You end up with a bit of boilerplate which is normally handled for you by http .您最终会得到一些样板文件,这些样板文件通常由http为您处理。

Working example below:下面的工作示例:

import 'dart:convert';
import 'dart:io';
import 'dart:async';

main() async {
  String url =
      'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  Map map = {
    'data': {'apikey': '12345678901234567890'},
  };

  print(await apiRequest(url, map));
}

Future<String> apiRequest(String url, Map jsonMap) async {
  HttpClient httpClient = new HttpClient();
  HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
  request.headers.set('content-type', 'application/json');
  request.add(utf8.encode(json.encode(jsonMap)));
  HttpClientResponse response = await request.close();
  // todo - you should check the response.statusCode
  String reply = await response.transform(utf8.decoder).join();
  httpClient.close();
  return reply;
}

Depending on your use case, it may be more efficient to re-use the HttpClient, rather than keep creating a new one for each request.根据您的用例,重用 HttpClient 可能更有效,而不是为每个请求创建一个新的。 Todo - add some error handling ;-) Todo - 添加一些错误处理;-)

This would also work :这也可以:

import 'package:http/http.dart' as http;

  sendRequest() async {

    Map data = {
       'apikey': '12345678901234567890'
    };

    var url = 'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
    http.post(url, body: data)
        .then((response) {
      print("Response status: ${response.statusCode}");
      print("Response body: ${response.body}");
    });  
  }

I think many people have problems with Post 'Content-type': 'application / json' The problem here is parse data Map <String, dynamic> to json :我认为很多人对 Post 'Content-type': 'application / json'有问题 这里的问题是解析数据Map <String, dynamic>json

Hope the code below can help someone希望下面的代码可以帮助某人

Model:模型:

class ConversationReq {
  String name = '';
  String description = '';
  String privacy = '';
  String type = '';
  String status = '';

  String role;
  List<String> members;
  String conversationType = '';

  ConversationReq({this.type, this.name, this.status, this.description, this.privacy, this.conversationType, this.role, this.members});

  Map<String, dynamic> toJson() {

    final Map<String, dynamic> data = new Map<String, dynamic>();

    data['name'] = this.name;
    data['description'] = this.description;
    data['privacy'] = this.privacy;
    data['type'] = this.type;

    data['conversations'] = [
      {
        "members": members,
        "conversationType": conversationType,
      }
    ];

    return data;
  }
}

Request:要求:

createNewConversation(ConversationReq param) async {
    HeaderRequestAuth headerAuth = await getAuthHeader();
    var headerRequest = headerAuth.toJson();
/*
{
            'Content-type': 'application/json',
            'x-credential-session-token': xSectionToken,
            'x-user-org-uuid': xOrg,
          }
*/

    var bodyValue = param.toJson();

    var bodydata = json.encode(bodyValue);// important
    print(bodydata);

    final response = await http.post(env.BASE_API_URL + "xxx", headers: headerRequest, body: bodydata);

    print(json.decode(response.body));
    if (response.statusCode == 200) {
      // TODO
    } else {
      // If that response was not OK, throw an error.
      throw Exception('Failed to load ConversationRepo');
    }
  }

this works for me这对我有用

String body = json.encode(parameters);

http.Response response = await http.post(
  url: 'https://example.com',
  headers: {"Content-Type": "application/json"},
  body: body,
);

I implement like this:我是这样实现的:

static createUserWithEmail(String username, String email, String password) async{
    var url = 'http://www.yourbackend.com/'+ "users";
    var body = {
        'user' : {
          'username': username,
          'address': email,
          'password': password
       }
    };

    return http.post(
      url, 
      body: json.encode(body),
      headers: {
        "Content-Type": "application/json"
      },
      encoding: Encoding.getByName("utf-8")
    );
  }

This one is for using HTTPClient class这是一个用于使用 HTTPClient 类

 request.headers.add("body", json.encode(map));

I attached the encoded json body data to the header and added to it.我将编码的 json 正文数据附加到标头并添加到其中。 It works for me.这个对我有用。

In my case POST in the Flutter App is working on the Web, but not on Android devices or the emulator.在我的情况下,Flutter App 中的 POST 可以在 Web 上运行,但不能在 Android 设备或模拟器上运行。

Flutter->Server->API Flutter->服务器->API

To fix it, I:为了解决它,我:

  1. changed HTTP HEADER on server with:将服务器上的 HTTP HEADER 更改为:

     $curlArr[CURLOPT_HTTPHEADER] = str_replace("application/x-www-form-urlencoded; charset=utf-8", "application/x-www-form-urlencoded",$curlArr[CURLOPT_HTTPHEADER]);
  2. copied most of the Headers to my App from postman.将大部分标题从邮递员复制到我的应用程序。

String body = json.encode(parameters);

http.Response response = await http.post(
  url: Uri.parse('https://example.com'),
  headers: {"Content-Type": "application/json"},
  body: body,
);

This worked for me!这对我有用!

This code works for me:这段代码对我有用:

static Future<LoginAPI> connectToAPI(String email, String password) async {
    String apiURL = "domain/login";

    Map<String, String> headers = {
      "Content-Type": "application/json",
      "Accept": "application/json",
    };

    var body = json.encode({"email": email, "password": password});

    var apiResult = await http.post(
      Uri.parse(apiURL),
      headers: headers,
      body: body,
    );

    var jsonObject = json.decode(apiResult.body);
    if (apiResult.statusCode >= 300) {
      return jsonObject // you can mapping json object also here
    } else {
      return jsonObject // you can mapping json object also here
    }
  }

If your using freeze dont forget to encode it first.如果您使用冻结,请不要忘记先对其进行编码。 Which is probably easy to forget.这可能很容易忘记。

String body = json.encode(parameters.toJson()); //dont skip this one
http.Response response = await http.post(
  Uri.parse(apiURL),
  headers: {"Content-Type": "application/json"},
  body: body,
);

In my case I forgot to enable就我而言,我忘记启用

app.use(express.json());

in my NodeJs server.在我的 NodeJs 服务器中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM