代码拉取完成,页面将自动刷新
// This file is part of Module Proxy.
// Module Proxy is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Module Proxy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Module Proxy. If not, see <https://www.gnu.org/licenses/>.
// Copyright (C) 2021 - 2030 关中麦客
// All rights reserved
//
// mod_urlmap.rs
// 唯一URL映射
//
// created by 关中麦客 1036038462@qq.com
use bytes::{BufMut, BytesMut};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio::net::TcpStream;
use hyper::{Body, Request, Response, Error};
use serde_json::{Value};
const RSP_OK: &str = "{\"status\":\"ok\"}";
const RSP_ERROR: &str = "{\"status\":\"error\"}";
/// 初始化
pub async fn init()
{
//唯一URL非使能(被注释)
if !super::conf::enable_module_url()
{
return;
}
log::info!("mod_url init...");
//配置文件中有唯一URL的配置(未注释)
if let Some(port) = super::conf::module_url_port()
{
// TCP 侦听------------
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port);
let listener = TcpListener::bind(addr).await.unwrap();
log::info!("mod_url listening port: {}", port);
tokio::spawn(async move {
loop
{
// accept
let (socket, _) = listener.accept().await.unwrap();
process(socket).await;
}
});
}
}
/// 模块名是否对应
pub fn exist(module_name: &str) -> bool
{
if let Some(name) = super::conf::module_url_name()
{
if name == module_name //模块名称一致
{
return true;
}
}
false
}
/// 唯一URL转发
pub async fn forward(request: Request<Body>, mod_name: &str) -> Result<Response<Body>, Error>
{
// http://mysite.com:80/aaa/NMRMI41a 中保留 /aaa/NMRMI41a
let url_path = request.uri().path_and_query().map(|x| x.as_str()).unwrap_or("/");
//url_path去除module部分,只剩下映射key部分
let remove_str = format!("/{}/", mod_name);
let key = &url_path[remove_str.len()..];
if let Some((mtype, val, _timeout)) = super::mod_urlmap::get(key).await
{
if super::mod_urlmap::MapType::Url == mtype //http反向代理
{
if let Ok(uri) = val.parse::<hyper::Uri>()
{
return super::mod_http::client_uri(uri).await;
}
}
else //本地文件
{
return Ok(super::mod_html::read_file(val).await);
}
}
Ok(super::response::rsp_500().await)
}
/// 处理socket
async fn process(mut socket: TcpStream)
{
//如果第一个字符是 '{' 或者 '[',表示是单条请求信息,否则是多条请求信息。
//单条请求信息,消息最大长度小于4096。
//多条请求信息需要冠以12字节长度单元,消息长度不受限制。
//读取第一个字节消息,来判断请求信息类型
let mut isonce: bool = true; //信息类型: 单条
let mut first: [u8; 1] = [0; 1];
match socket.peek(&mut first).await //peek不消费TcpStream中本次读取的数据,即peek后还可以再次读取这部分数据
{
Ok(_) =>
{
let c = first[0] as char;
if c != '{' && c != ']'
{
isonce = false; //信息类型: 多条
}
}
Err(err) =>
{
log::warn!("[mod_url] socket read first byte error: {}", err);
return;
}
}
//-------------------单条请求-------------------------
if isonce
{
let mut buf: [u8; 4096] = [0; 4096]; //缓冲
if let Ok(c_size) = socket.read(&mut buf).await //socket读
{
//[u8]转&str
let req_str: &str;
match std::str::from_utf8(&buf[..c_size])
{
Ok(s) =>
req_str = s,
Err(err) =>
{
log::warn!("[mod_url] socket read msg from [u8] to &str error: {}", err);
return;
}
}
//解析请求报文
let rsp_str = parse_once(req_str).await;
//socket返回
let send_bytes = rsp_str.as_bytes();
if let Err(err) = socket.write_all(&send_bytes).await
{
log::warn!("[mod_url] socket write error: {}", err);
}
}
return;
}
//-------------------多条请求-------------------------
//读取12字节长度单元
let mut len_buf: [u8; 12] = [0; 12];
match socket.read(&mut len_buf).await
{
Ok(c_size) =>
{
if c_size != 12
{
log::warn!("[mod_url] socket read len_buf error: len_buf size not 12");
return;
}
},
Err(err) =>
{
log::warn!("[mod_url] socket read length error: {}", err);
return;
}
}
//解析消息长度
let _msg_len: usize;
match String::from_utf8(len_buf.to_vec())
{
Ok(s) =>
{
let len_str = s.trim();
match len_str.parse::<usize>()
{
Ok(len) =>
_msg_len = len,
Err(err) =>
{
log::warn!("[mod_url] socket read length error: {}", err);
return;
}
}
},
Err(err) =>
{
log::warn!("[mod_url] socket read length error: {}", err);
return;
}
}
//读取缓冲区
let mut buffer = BytesMut::new(); //读取rsp_json缓冲区
let mut read_buf: [u8; 4096] = [0; 4096]; //socket读缓冲
loop
{
//已读取了完整数据
if buffer.len() >= _msg_len
{
let read_bytes = buffer.to_vec(); //BytesMut转Vec<u8>
if let Ok(req_str) = String::from_utf8(read_bytes) //Vec<u8>转String
{
let rsp_str = parse_mut(&req_str).await; //解析请求报文
//socket返回
let send_bytes = rsp_str.as_bytes();
if let Err(err) = socket.write_all(send_bytes).await
{
log::warn!("[mod_url] socket write error: {}", err);
}
}
break; //跳出loop
}
//从socket中分次读取,合并到buffer
if let Ok(c_size) = socket.read(&mut read_buf).await
{
buffer.put(&read_buf[..c_size]);
}
}
}
/// 解析单条数据, 返回json应答
async fn parse_once(req_str: &str) -> String
{
let json = parse_json(req_str);
match json["method"].as_str()
{
Some("set") =>
{
// json示例: {"method":"set","key":"NMRMI41a","type":"url","val":"http://xxxx/xxx/xx","timeout":-1}
let mut mtype = super::mod_urlmap::MapType::File;
if let Some(key) = json["key"].as_str()
{
if let Some(mytpe_str) = json["type"].as_str()
{
if "url" == mytpe_str
{
mtype = super::mod_urlmap::MapType::Url;
}
if let Some(val) = json["val"].as_str()
{
if let Some(timeout) = json["timeout"].as_i64()
{
super::mod_urlmap::set(key.to_string(), mtype, val.to_string(), timeout as i32).await;
return RSP_OK.to_string();
}
}
}
}
log::warn!("[mod_url] error: Json parsing set method format error.");
return RSP_ERROR.to_string();
}
Some("del") =>
{
// json示例: {"method":"del","key":"NMRMI41a"}
if let Some(key) = json["key"].as_str()
{
super::mod_urlmap::del(key.to_string()).await; //从map中删除
return RSP_OK.to_string();
}
log::warn!("[mod_url] error: json parse del method without key.");
return RSP_ERROR.to_string();
}
Some("get") =>
{
// json示例: {"method":"get","key":"NMRMI41a"}
if let Some(key) = json["key"].as_str()
{
if let Some((mtype, val, timeout)) = super::mod_urlmap::get(key).await
{
let rsp: String;
if mtype == super::mod_urlmap::MapType::File
{
rsp = format!("\"key\":\"{}\",\"type\":\"file\",\"val\":\"{}\",\"timeout\":{}",
key, val, timeout);
}
else
{
rsp = format!("\"key\":\"{}\",\"type\":\"url\",\"val\":\"{}\",\"timeout\":{}",
key, val, timeout);
}
let rsp = "{".to_string() + &rsp + "}";
return rsp;
}
}
log::warn!("[mod_url] error: json parse get method without key.");
return RSP_ERROR.to_string();
}
Some(_) =>
{
log::warn!("[mod_url] error: json parse unknown method");
return RSP_ERROR.to_string();
},
None =>
{
log::warn!("[mod_url] error: json parse unknown request");
return RSP_ERROR.to_string();
}
}
}
/// 解析多条数据, 返回json应答
async fn parse_mut(req_str: &str) -> String
{
let mut ok_num: i32 = 0;
let lines = req_str.split("\r\n");
for line in lines
{
let json = parse_json(line); //一行json: {"key":"NMRMI41a","type":"url","val":"http://xxxx/xxx/xx","timeout":-1}
let mut mtype = super::mod_urlmap::MapType::File;
if let Some(key) = json["key"].as_str()
{
if let Some(mytpe_str) = json["type"].as_str()
{
if "url" == mytpe_str
{
mtype = super::mod_urlmap::MapType::Url;
}
if let Some(val) = json["val"].as_str()
{
if let Some(timeout) = json["timeout"].as_i64()
{
super::mod_urlmap::set(key.to_string(), mtype, val.to_string(), timeout as i32).await;
ok_num += 1;
}
}
}
}
}
//返回json
let rsp = format!("\"status\":\"ok\",\"ok_amount\":{}", ok_num);
let rsp = "{".to_string() + &rsp + "}";
rsp
}
/// 解析json
fn parse_json(msg: &str) -> Value
{
match serde_json::from_str(msg)
{
Ok(json) => json,
Err(err) =>
{
log::warn!("parse json error: {}", err);
let json = serde_json::json!({"method":"error"});
json
}
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。