client.rs 3,1 КБ
Newer Older
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
1
2
3
4

use std::error::Error;
use prost::Message;

Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
5
use tonic::codegen::{InterceptedService, http};
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
6
7
use tonic::service::Interceptor;
use tonic::transport::{Endpoint, Channel, Uri};
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
8
9
10

use crate::generated::ydb::discovery::v1::DiscoveryServiceClient;
use crate::generated::ydb::discovery::{ListEndpointsResult, ListEndpointsRequest};
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
11
use crate::generated::ydb::table::v1::table_service_client::TableServiceClient;
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
12
//use ydb_grpc::ydb_proto::discovery::{v1::discovery_service_client::DiscoveryServiceClient, WhoAmIRequest, WhoAmIResponse, ListEndpointsRequest, WhoAmIResult, ListEndpointsResult};
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

pub type AsciiValue = tonic::metadata::MetadataValue<tonic::metadata::Ascii>;


pub fn create_endpoint(uri: Uri) -> Endpoint {
    let mut res = Endpoint::from(uri);
    if matches!(res.uri().scheme_str(), Some("grpcs")) {
        res = res.tls_config(tonic::transport::ClientTlsConfig::new()).unwrap()
    };
    res.tcp_keepalive(Some(std::time::Duration::from_secs(15)))
}


pub trait Credentials: Clone {
    fn token(&self) -> AsciiValue;
}

impl Credentials for String {
    fn token(&self) -> AsciiValue {
        self.clone().try_into().unwrap()
    }
}

#[ctor::ctor]
static BUILD_INFO: AsciiValue = concat!("ydb-unofficial/", env!("CARGO_PKG_VERSION")).try_into().unwrap();

#[derive(Clone, Debug)]
pub struct DBInterceptor<C: Clone> {
    db_name: AsciiValue,
    creds: C
}

impl<C: Credentials> Interceptor for DBInterceptor<C> {
    fn call(&mut self, mut request: tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status> {
        let headers = request.metadata_mut();
        headers.insert("x-ydb-database", self.db_name.clone());
        headers.insert("x-ydb-sdk-build-info", BUILD_INFO.clone());
        headers.insert("x-ydb-auth-ticket", self.creds.token());
Баринов Сергей Владимирович's avatar
test    
Баринов Сергей Владимирович включено в состав коммита
51
        println!("headers added");
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
52
53
        Ok(request)    
    }
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
}

#[derive(Clone)]
pub struct YdbService<C: Credentials>(InterceptedService<Channel, DBInterceptor<C>>);

use tonic::client::GrpcService as Service;
use tonic::body::BoxBody as Body;

impl<C: Credentials> Service<Body> for YdbService<C> {
    type ResponseBody = Body;

    type Error = tonic::transport::Error;

    type Future = tonic::service::interceptor::ResponseFuture<tonic::transport::channel::ResponseFuture>;

    fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
        self.0.poll_ready(cx)
    }

    fn call(&mut self, request: tonic::codegen::http::Request<tonic::body::BoxBody>) -> Self::Future {
        self.0.call(request)
    }
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
}

impl<C: Credentials> YdbService<C> {
    pub fn new(channel: Channel, db_name: AsciiValue, creds: C) -> Self {
        let interceptor = DBInterceptor {db_name, creds};
        let service = tower::ServiceBuilder::new()
            .layer(tonic::service::interceptor(interceptor))
            .layer_fn(|x|x)
            .service(channel);
        YdbService(service)
    }
    pub fn discovery(self) -> DiscoveryServiceClient<Self> {
        DiscoveryServiceClient::new(self)
    }
    pub fn table(self) -> TableServiceClient<Self> {
        TableServiceClient::new(self)
    }
Баринов Сергей Владимирович's avatar
Баринов Сергей Владимирович включено в состав коммита
93
}