use crate::app_error;
use crate::tina::data::app_error::AppError;
use crate::tina::data::http::request_ext::{ErrorMsg, SuccessFlag};
use crate::tina::data::json::ToJson;
use crate::tina::data::no_data::NoData;
use crate::tina::data::response_data::ResData;
use crate::tina::data::response_page::ResPage;
use crate::tina::data::AppResult;
use crate::tina::server::http::request::RequestExt;
use crate::tina::server::http::response::{HttpResponseExt, ResponseAttribute};
use crate::tina::server::session::Session;
use crate::tina::util::json::JsonUtil;
use futures_util::future::LocalBoxFuture;
use futures_util::FutureExt;
use http::header::HeaderName;
use http::{HeaderValue, StatusCode};
use ntex::http::body::Body;
use ntex::web::{HttpRequest, Responder, WebRequest, WebResponse};
use serde::{Serialize, Serializer};
use std::borrow::Cow;
use std::fmt::Debug;
use std::sync::Arc;
pub struct ResRaw {
inner: ntex::http::Response<Body>,
}
pub type Response = ntex::http::Response<Body>;
impl ResponseAttribute for Response {
fn success(&self) -> bool {
let ext = self.extensions();
match ext.get::<SuccessFlag>() {
None => false,
Some(_) => true,
}
}
fn set_success(&mut self, flag: bool) {
let mut ext = self.extensions_mut();
match flag {
true => {
ext.insert(SuccessFlag);
}
false => {
ext.remove::<SuccessFlag>();
}
}
}
fn get_error_message(&self) -> Option<Cow<str>> {
let ext = self.extensions();
match ext.get::<SuccessFlag>() {
None => match ext.get::<ErrorMsg>() {
None => None,
Some(s) => Some(Cow::Owned(s.0.to_string())),
},
Some(_) => None,
}
}
}
impl ResponseAttribute for WebResponse {
fn success(&self) -> bool {
self.response().success()
}
fn set_success(&mut self, flag: bool) {
self.response_mut().set_success(flag)
}
fn get_error_message(&self) -> Option<Cow<str>> {
let res = self.response();
let ext = res.extensions();
match ext.get::<SuccessFlag>() {
None => match ext.get::<ErrorMsg>() {
None => None,
Some(s) => Some(Cow::Owned(s.0.to_string())),
},
Some(_) => None,
}
}
}
impl ResponseAttribute for ResRaw {
fn success(&self) -> bool {
self.inner.success()
}
fn set_success(&mut self, flag: bool) {
self.inner.set_success(flag)
}
fn get_error_message(&self) -> Option<Cow<str>> {
self.inner.get_error_message()
}
}
impl ResRaw {
pub fn new(res: ntex::http::Response<Body>) -> Self {
Self {
inner: res,
}
}
pub fn into_inner(self) -> ntex::http::Response<Body> {
self.inner
}
}
pub trait IntoResRaw {
fn into_ajax_response(self) -> ResRaw;
}
impl IntoResRaw for Response {
fn into_ajax_response(self) -> ResRaw {
ResRaw::new(self)
}
}
impl Serialize for ResRaw {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str("[Response]")
}
}
impl Responder<AppError> for ResRaw {
type Future = LocalBoxFuture<'static, ntex::http::Response<Body>>;
#[inline]
fn respond_to(mut self, _: &HttpRequest) -> Self::Future {
self.inner.set_success(self.success());
async move { self.inner }.boxed_local()
}
}
fn set_log_param_result<T: Serialize>(value: &T, req: &HttpRequest) {
if let Ok(Some(request_param_log)) = req.get_request_log_param() {
request_param_log.set_result(Arc::new(value.to_json_value()));
}
}
fn set_log_param_result2<T: Serialize, E>(value: &T, req: &WebRequest<E>) {
if let Ok(Some(request_param_log)) = req.get_request_log_param() {
request_param_log.set_result(Arc::new(value.to_json_value()));
}
}
fn set_log_param_error(err: &AppError, req: &HttpRequest) {
if let Ok(Some(request_param_log)) = req.get_request_log_param() {
request_param_log.set_err(err);
}
}
fn set_log_param_error2<E>(err: &AppError, req: &WebRequest<E>) {
if let Ok(Some(request_param_log)) = req.get_request_log_param() {
request_param_log.set_err(err);
}
}
pub trait IntoToResponse {
fn into_response(self, req: &HttpRequest, print_err_log: bool) -> Response;
fn into_response2<E>(self, req: &WebRequest<E>, print_err_log: bool) -> Response;
}
impl<D, Ext> IntoToResponse for ResData<D, Ext>
where
D: Serialize + Debug,
Ext: Serialize + Debug,
{
fn into_response(self, req: &HttpRequest, print_err_log: bool) -> Response {
set_log_param_result(&self, req);
let body = JsonUtil::to_json_string(&self);
if print_err_log {
match self.is_success() {
true => {}
false => {
tracing::error!("{}", body);
set_log_param_error(&app_error!(self.code.clone(), self.code.clone().get_code_description()), req);
}
}
}
Response::build(StatusCode::OK).content_type("application/json").body(body)
}
fn into_response2<E>(self, req: &WebRequest<E>, print_err_log: bool) -> Response {
set_log_param_result2(&self, req);
let body = JsonUtil::to_json_string(&self);
if print_err_log {
match self.is_success() {
true => {}
false => {
tracing::error!("{}", body);
set_log_param_error2(&app_error!(self.code.clone(), self.code.clone().get_code_description()), req);
}
}
}
Response::build(StatusCode::OK).content_type("application/json").body(body)
}
}
impl<D> IntoToResponse for ResPage<D>
where
D: Serialize + Debug,
{
fn into_response(self, req: &HttpRequest, print_err_log: bool) -> Response {
set_log_param_result(&self, req);
let body = JsonUtil::to_json_string(&self);
if print_err_log {
match self.is_success() {
true => {}
false => {
tracing::error!("{}", body);
set_log_param_error(&app_error!(self.code.clone(), self.code.clone().get_code_description()), req);
}
}
}
Response::build(StatusCode::OK).content_type("application/json").body(body)
}
fn into_response2<E>(self, req: &WebRequest<E>, print_err_log: bool) -> Response {
set_log_param_result2(&self, req);
let body = JsonUtil::to_json_string(&self);
if print_err_log {
match self.is_success() {
true => {}
false => {
tracing::error!("{}", body);
set_log_param_error2(&app_error!(self.code.clone(), self.code.clone().get_code_description()), req);
}
}
}
Response::build(StatusCode::OK).content_type("application/json").body(body)
}
}
impl IntoToResponse for AppError {
fn into_response(self, req: &HttpRequest, print_err_log: bool) -> Response {
let locale = req.get_locale();
let msg = format!("{:?}", self);
set_log_param_error(&self, req);
let vo: ResData<NoData> = ResData {
code: self.get_return_code(),
msg: Some(self.get_return_msg().get_string(&locale)),
data: None,
extension: Default::default(),
session: Session::default(),
};
set_log_param_result(&vo, req);
let body = vo.to_json_string();
if print_err_log {
match vo.is_success() {
true => {}
false => {
tracing::error!("{}, 异常信息: {}", body, msg);
}
}
}
Response::build(StatusCode::OK).content_type("application/json").body(body)
}
fn into_response2<E>(self, req: &WebRequest<E>, print_err_log: bool) -> Response {
let locale = req.get_locale();
let msg = format!("{:?}", self);
set_log_param_error2(&self, req);
let vo: ResData<NoData> = ResData {
code: self.get_return_code(),
msg: Some(self.get_return_msg().get_string(&locale)),
data: None,
extension: Default::default(),
session: Session::default(),
};
set_log_param_result2(&vo, req);
let body = vo.to_json_string();
if print_err_log {
match vo.is_success() {
true => {}
false => {
tracing::error!("{}, 异常信息: {}", body, msg);
}
}
}
Response::build(StatusCode::OK).content_type("application/json").body(body)
}
}
impl HttpResponseExt for WebResponse {
fn add_response_header(&mut self, header_name: HeaderName, header_value: HeaderValue) -> AppResult<()> {
let headers = self.headers_mut();
headers.insert(header_name, header_value.into());
Ok(())
}
}