add: Preliminary support for flutter front-end calling rust back-end http request

This commit is contained in:
yuluo
2024-04-18 01:12:39 +08:00
parent 1176750a4f
commit 9588c3280f
6 changed files with 126 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import '../common.dart';
import '../utils/http_service.dart';
import 'model.dart';
import 'platform_model.dart';
@@ -135,8 +136,8 @@ class UserModel {
/// throw [RequestException]
Future<LoginResponse> login(LoginRequest loginRequest) async {
final url = await bind.mainGetApiServer();
final resp = await http.post(Uri.parse('$url/api/login'),
headers: {'Content-Type': 'application/json'},
final resp = await HttpService().sendRequest(
'$url/api/login', HttpMethod.post,
body: jsonEncode(loginRequest.toJson()));
final Map<String, dynamic> body;

View File

@@ -0,0 +1,48 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/platform_model.dart';
enum HttpMethod { get, post, put, delete }
class HttpService {
Future<http.Response> sendRequest(
String url,
HttpMethod method, {
Map<String, String>? headers,
dynamic body,
}) async {
headers ??= {'Content-Type': 'application/json'};
String headersJson = jsonEncode(headers);
String methodName = method.toString().split('.').last;
await bind.mainHttpRequest(url: url, method: methodName.toLowerCase(), body: body, header: headersJson);
var resJson = await _pollForResponse();
return _parseHttpResponse(resJson);
}
Future<String> _pollForResponse() async {
String responseJson = await bind.mainGetAsyncStatus();
while (responseJson == " ") {
await Future.delayed(const Duration(milliseconds: 100));
responseJson = await bind.mainGetAsyncStatus();
}
return responseJson;
}
http.Response _parseHttpResponse(String responseJson) {
try {
var parsedJson = jsonDecode(responseJson);
String body = parsedJson['body'];
Map<String, String> headers = {};
for (var key in parsedJson['headers'].keys) {
headers[key] = parsedJson['headers'][key];
}
int statusCode = parsedJson['status_code'];
return http.Response(body, statusCode, headers: headers);
} catch (e) {
throw Exception('Failed to parse response: $e');
}
}
}

View File

@@ -1,3 +1,4 @@
use serde_json::Value;
use std::{
borrow::Cow,
future::Future,
@@ -1085,6 +1086,62 @@ pub async fn post_request_sync(url: String, body: String, header: &str) -> Resul
post_request(url, body, header).await
}
#[tokio::main(flavor = "current_thread")]
pub async fn http_request_sync(
url: String,
method: String,
body: String,
header: String,
) -> ResultType<String> {
let http_client = create_http_client_async();
let mut http_client = match method.as_str() {
"get" => http_client.get(url),
"post" => http_client.post(url),
"put" => http_client.put(url),
"delete" => http_client.delete(url),
_ => return Err(anyhow!("The HTTP request method is not supported!")),
};
let v = serde_json::from_str(header.as_str())?;
if let Value::Object(obj) = v {
for (key, value) in obj.iter() {
http_client = http_client.header(key, value.as_str().unwrap_or_default());
println!("Key: {}, Value: {}", key, value);
}
} else {
return Err(anyhow!("HTTP header information parsing failed!"));
}
let response = http_client
.body(body)
.timeout(std::time::Duration::from_secs(12))
.send()
.await?;
// Serialize response headers
let mut response_headers = serde_json::map::Map::new();
for (key, value) in response.headers() {
response_headers.insert(
key.to_string(),
serde_json::json!(value.to_str().unwrap_or("")),
);
}
let status_code = response.status().as_u16();
let response_body = response.text().await?;
// Construct the JSON object
let mut result = serde_json::map::Map::new();
result.insert("status_code".to_string(), serde_json::json!(status_code));
result.insert(
"headers".to_string(),
serde_json::Value::Object(response_headers),
);
result.insert("body".to_string(), serde_json::json!(response_body));
// Convert map to JSON string
serde_json::to_string(&result).map_err(|e| anyhow!("Failed to serialize response: {}", e))
}
#[inline]
pub fn make_privacy_mode_msg_with_details(
state: back_notification::PrivacyModeState,

View File

@@ -874,9 +874,8 @@ pub fn main_get_api_server() -> String {
get_api_server()
}
// This function doesn't seem to be used.
pub fn main_post_request(url: String, body: String, header: String) {
post_request(url, body, header)
pub fn main_http_request(url: String, method: String, body: String, header: String) {
http_request(url,method, body, header)
}
pub fn main_get_local_option(key: String) -> SyncReturn<String> {

View File

@@ -548,6 +548,10 @@ impl UI {
change_id_shared(id, old_id);
}
fn http_request(&self, url: String, method: String, body: String, header: String) {
http_request(url, method, body, header)
}
fn post_request(&self, url: String, body: String, header: String) {
post_request(url, body, header)
}

View File

@@ -708,6 +708,18 @@ pub fn change_id(id: String) {
});
}
#[inline]
pub fn http_request(url: String, method: String, body: String, header: String) {
*ASYNC_JOB_STATUS.lock().unwrap() = " ".to_owned();
std::thread::spawn(move || {
*ASYNC_JOB_STATUS.lock().unwrap() =
match crate::http_request_sync(url, method, body, header) {
Err(err) => err.to_string(),
Ok(text) => text,
};
});
}
#[inline]
pub fn post_request(url: String, body: String, header: String) {
*ASYNC_JOB_STATUS.lock().unwrap() = " ".to_owned();