Flutter 无法正确连接到 Rails API
Flutter can't connect to Rails API only properly
好的,这是我的问题。
我只有标准 Rails 5 API 设置。
我的用户控制器非常标准:
# frozen_string_literal: true
class UsersController < ApplicationController
before_action :set_user, only: %i[show update destroy]
# GET /users
def index
@users = User.all
render json: @users
end
# GET /users/1
def show
render json: @user
end
# POST /users
def create
@user = User.new(user_params)
if @user.save
render json: @user, status: :created, location: @user
UserNotifierMailer.send_signup_email(@user).deliver
else
render json: @user.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /users/1
def update
if @user.update(user_params)
render json: @user
else
render json: @user.errors, status: :unprocessable_entity
end
end
# DELETE /users/1
def destroy
@user.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:username, :password, :email)
end
end
现在,当我 post 从 Postman 向服务器发送数据时,它可以正常工作,并且可以很好地注册用户。
这是我从 Postman 那里得到的:
另一方面,我正在使用 Flutter 应用程序,我正在尝试注册。
这是Flutter模型。
import 'dart:convert';
import 'package:http/http.dart' as http;
class HeadUser {
User _user;
HeadUser({User user}) {
this._user = user;
}
HeadUser.fromJson(Map<String, dynamic> json) {
_user = json['user'] != null ? new User.fromJson(json['user']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this._user != null) {
data['user'] = this._user.toJson();
}
return data;
}
}
class User {
String _username;
String _email;
String _password;
int _id;
DateTime _createdAt;
DateTime _updatedAt;
User({int id, DateTime createdAt, DateTime updatedAt, String username, String email, String password}) {
this._username = username;
this._email = email;
this._password = password;
this._id = id;
this._createdAt = createdAt;
this._updatedAt = updatedAt;
}
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
username: json['username'],
email: json['email'],
createdAt: json['created_at'],
updatedAt: json['updated_at'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['username'] = this._username;
data['email'] = this._email;
data['password'] = this._password;
return data;
}
}
Future<HeadUser> loginUser(String url, {Map body}) async {
return http.post(url, body: body).then((http.Response response) {
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || statusCode == null) {
throw new Exception("Error while posting data");
}
return HeadUser.fromJson(json.decode(response.body));
});
}
我对此的呼吁如下:
onPressed: () async {
if (_formKey.currentState.validate())
{
HeadUser usr = new HeadUser(user: User(
email: this.emailEditingController.text.trim(),
password: this.passwordEditingController.text.trim(),
username: this.usernameEditingController.text.trim()
));
HeadUser response = await loginUser(REGISTRATION_URL, body: usr.toJson());
但是当我这样做时,我的 Flutter 应用程序出现错误,就像我缺少 "user" 参数一样,虽然当我打印出来时它显示了确切的结构,但我明白了。
在这种情况下,请求甚至没有被触发,所以服务器没有被命中。
但是,如果我尝试在 loginUser
方法中执行 json.encode(body)
,那么服务器的响应是:
Flutter 当然会抱怨:
我做错了什么?
好的,我真的找到了一个问题(和一个解决方案)。
出于某些奇怪的原因,Rails 要求将数据显式发布为 "Content-type":"application/json"。
所以还需要设置请求头,传入http.post
方法。
Future<HeadUser> loginUser(String url, {Map body}) async {
Map<String, String> headers = {"Content-type": "application/json"};
return http.post(url, headers: headers, body: json.encode(body)).then((http.Response response) {
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || statusCode == null) {
throw new Exception("Error while posting data");
}
return HeadUser.fromJson(json.decode(response.body));
});
好的,这是我的问题。
我只有标准 Rails 5 API 设置。
我的用户控制器非常标准:
# frozen_string_literal: true
class UsersController < ApplicationController
before_action :set_user, only: %i[show update destroy]
# GET /users
def index
@users = User.all
render json: @users
end
# GET /users/1
def show
render json: @user
end
# POST /users
def create
@user = User.new(user_params)
if @user.save
render json: @user, status: :created, location: @user
UserNotifierMailer.send_signup_email(@user).deliver
else
render json: @user.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /users/1
def update
if @user.update(user_params)
render json: @user
else
render json: @user.errors, status: :unprocessable_entity
end
end
# DELETE /users/1
def destroy
@user.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:username, :password, :email)
end
end
现在,当我 post 从 Postman 向服务器发送数据时,它可以正常工作,并且可以很好地注册用户。
这是我从 Postman 那里得到的:
另一方面,我正在使用 Flutter 应用程序,我正在尝试注册。
这是Flutter模型。
import 'dart:convert';
import 'package:http/http.dart' as http;
class HeadUser {
User _user;
HeadUser({User user}) {
this._user = user;
}
HeadUser.fromJson(Map<String, dynamic> json) {
_user = json['user'] != null ? new User.fromJson(json['user']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this._user != null) {
data['user'] = this._user.toJson();
}
return data;
}
}
class User {
String _username;
String _email;
String _password;
int _id;
DateTime _createdAt;
DateTime _updatedAt;
User({int id, DateTime createdAt, DateTime updatedAt, String username, String email, String password}) {
this._username = username;
this._email = email;
this._password = password;
this._id = id;
this._createdAt = createdAt;
this._updatedAt = updatedAt;
}
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
username: json['username'],
email: json['email'],
createdAt: json['created_at'],
updatedAt: json['updated_at'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['username'] = this._username;
data['email'] = this._email;
data['password'] = this._password;
return data;
}
}
Future<HeadUser> loginUser(String url, {Map body}) async {
return http.post(url, body: body).then((http.Response response) {
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || statusCode == null) {
throw new Exception("Error while posting data");
}
return HeadUser.fromJson(json.decode(response.body));
});
}
我对此的呼吁如下:
onPressed: () async {
if (_formKey.currentState.validate())
{
HeadUser usr = new HeadUser(user: User(
email: this.emailEditingController.text.trim(),
password: this.passwordEditingController.text.trim(),
username: this.usernameEditingController.text.trim()
));
HeadUser response = await loginUser(REGISTRATION_URL, body: usr.toJson());
但是当我这样做时,我的 Flutter 应用程序出现错误,就像我缺少 "user" 参数一样,虽然当我打印出来时它显示了确切的结构,但我明白了。
在这种情况下,请求甚至没有被触发,所以服务器没有被命中。
但是,如果我尝试在 loginUser
方法中执行 json.encode(body)
,那么服务器的响应是:
Flutter 当然会抱怨:
我做错了什么?
好的,我真的找到了一个问题(和一个解决方案)。
出于某些奇怪的原因,Rails 要求将数据显式发布为 "Content-type":"application/json"。
所以还需要设置请求头,传入http.post
方法。
Future<HeadUser> loginUser(String url, {Map body}) async {
Map<String, String> headers = {"Content-type": "application/json"};
return http.post(url, headers: headers, body: json.encode(body)).then((http.Response response) {
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || statusCode == null) {
throw new Exception("Error while posting data");
}
return HeadUser.fromJson(json.decode(response.body));
});