postgresql - Rust:如何将SocketAddr转换为IpNetwork?

标签 postgresql rust rust-diesel rust-rocket

我希望使用Diesel和Rocket来记录请求来自的IP。 Here是类似的讨论,但没有结论。 Diesel将Postgres的inet类型映射为IpNetwork,但是Rocket从请求数据中返回SocketAddr。怎么把SocketAddr转换成IpNetwork

models.rs :

#![allow(proc_macro_derive_resolution_fallback)]
use crate::schema::bs_date_forecast;

use chrono::{NaiveDate, NaiveDateTime};
use ipnetwork::IpNetwork;
use diesel::prelude::*;

#[derive(Queryable, Insertable, Serialize, Deserialize)]
#[table_name="bs_date_forecast"]
pub struct BsDateForecast {
    pub id: Option<i32>,
    pub predicted_date: NaiveDate,
    pub seer_ip: IpNetwork,
    pub created_timestamp: NaiveDateTime,  // Defined automatically at the database level
}

impl BsDateForecast {
    pub fn create(forecast: BsDateForecast,
                  conn: &PgConnection) -> Vec<BsDateForecast> {
        diesel::insert_into(bs_date_forecast::table)
            .values(&forecast)
            .get_results(conn)
            .expect("Error creating record")
    }
}

routes.rs :
#[post("/predictions", format = "application/json", data = "<prediction>")]
pub fn create(prediction: Json<BsDateForecast>,
              conn: DbConn,
              user_ip: SocketAddr) -> Json<Vec<BsDateForecast>> {
    let insert = BsDateForecast{
        id: None,
        seer_ip: user_ip.to_string(),  // How to get IpNetwork here???
        ..prediction.into_inner()
    };
    Json(BsDateForecast::create(insert, &conn))
}

最佳答案

INET类型可以存储一个子网(包括子网掩码)或一个主机。 IpNetwork类型用于存储子网,但是可以通过指定全长前缀以Postgres方式存储单个主机。

SocketAddr是IpAddr加上端口号。

因此,转换为:获取SocketAddr的IP部分,通过指定正确的前缀从中创建一个IpNetwork。

这里的复杂之处在于,对于IP4和IP6,前缀是不同的。

fn socket_addr_to_ip_network(socket_addr: &SocketAddr) -> IpNetwork {
  let ip = socket_addr.ip();
  IpNetwork::new(ip, single_host_prefix(ip))
    .expect("single_host_prefix created invalid prefix")
}
fn single_host_prefix(ip_addr: &IpAddr) -> u8 {
  match ip_addr { &IpAddr::V4(_) => 32, &IpAddr::V6(_) => 128 }
}

关于postgresql - Rust:如何将SocketAddr转换为IpNetwork?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60026567/

相关文章:

sql - PostgreSQL 或 Rails 中的部分透视

loops - 如何以函数式风格迭代二维向量?

types - 强类型枚举作为 rust 中的联合 : How to determine type of value and retrieve it; How to do "constructors"

sql - 统计 PostgreSQL 中枚举的所有值

postgresql - 错误 : duplicate key value violates unique constraint in postgreSQL

rust - 无法在 Rust/Actix 应用程序中使用柴油计时功能

rust - 如何使用 `into_boxed()` 构建过滤表达式来针对带有联接的查询进行操作?

database - 如何将 Diesel 与 SQLite 连接一起使用并避免 `database is locked` 类型的错误

postgresql - 执行相同的查询会在 postgresql 中产生时间差异

rust - future - 预期 (),找到 struct futures::Map