首页 > 解决方案 > 如何在颤动的http post请求中制作自定义标头

问题描述

我想发出一个简单的发布请求,但有些东西不起作用。

在前端角度中,http 标头是这样制作的:

let header = {
      headers: new HttpHeaders({
        "Content-Type": "application/json",
        user: JSON.stringify(JSON.parse(localStorage.getItem("user")).values)
      })
    };

在应用程序 Flutter 我试图做类似的事情,但我所做的一切都返回错误 500,因为标题不正确

从技术上讲,我需要这样做

final Map< String, String> headers = {
      "Content-Type" : "application/json",
      "user" : { 
                 "token": "BLABLABLA",
                 "user_id" : "1"
               } 
} ;

这必须像角度的前端一样工作,因为后端是这样完成的

登录完成并正常工作,我们正在使用 SharedPreferences 保存登录信息

标签: flutterhttp-headershttp-post

解决方案


This is a good question. Lots of people out there use wrapper libraries for the base http library, but it sounds like you are using just the base library. I think the problem is that you are building a header as if it were Map<String, dynamic> when it actually needs to be Map<String, String>.

Depending on your server setup, you could probably get this to work like so:

final Map< String, String> headers = {
  "Content-Type" : "application/json",
  "user" : jsonEncode({ // add this function call around your object
             "token": "BLABLABLA",
             "user_id" : "1"
           }),
};

Using this above will create two headers:

Content-Type: application/json
user: {"token":"BLABLABLA","user_id":1}

However you may not want that, because some servers do not like the {} or "" characters in the content of the header. Instead you can do two more variations:

= Base 64 method =

try to base64 that json string in your header, then on the server side base64decode it:

final Map< String, String> headers = {
  "Content-Type" : "application/json",
  "user" : stringToBase64.encode( // additionally base64 encode it
             jsonEncode({ // add this function call around your object
               "token": "BLABLABLA",
               "user_id" : "1"
             }),
           ),
};

= URL Encode method =

urlencode that header which should work for most servers:

final Map< String, String> headers = {
  "Content-Type" : "application/json",
  "user" : Uri.encodeQueryComponent( // additionally base64 encode it
             jsonEncode({ // add this function call around your object
               "token": "BLABLABLA",
               "user_id" : "1"
             }),
           ),
};

= Suggestion =

If you are just trying to use a basic JWT though, you may want to just skip that whole user parameter and stick your token into a standard Authorization: Bearer TOKEN format. Here is a working sample that I have pulled and modified from one of my projects that does exactly that:

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

String _getToken() {
  return 'MY_BEARER_TOKEN';
}

class BaseNetworking {
  Future<http.Response> post(
    String url,
    Map<String, dynamic> data, {
    Map<String, String> headers,
  }) async {
    final Uri uri = Uri.parse(url);

    return await http.post(
      uri,
      headers: _buildHeaders(
        requiresAuth: true,
        extra: headers,
      ),
      body: jsonEncode(data),
    );
  }

  /// build the headers for the given request. might include authorization or any number of other headers
  Map<String, String> _buildHeaders({
    bool requiresAuth = true,
    Map<String, String> extra,
  }) {
    final Map<String, String> headers = <String, String>{
      'Accept': 'application/json; charset=utf-8',
      'User-Agent': 'AppName (version: 1.0.0)',
    };

    if (extra is Map<String, String>) {
      headers.addAll(extra);
    }

    if (requiresAuth) {
      headers['Authorization'] = 'Bearer ${_getToken()}';
    }

    return headers;
  }
}

推荐阅读