postgres/
config.rs

1//! Connection configuration.
2
3use crate::connection::Connection;
4use crate::Client;
5use log::info;
6use std::fmt;
7use std::net::IpAddr;
8use std::path::Path;
9use std::str::FromStr;
10use std::sync::Arc;
11use std::time::Duration;
12use tokio::runtime;
13#[doc(inline)]
14pub use tokio_postgres::config::{
15    ChannelBinding, Host, LoadBalanceHosts, SslMode, SslNegotiation, TargetSessionAttrs,
16};
17use tokio_postgres::error::DbError;
18use tokio_postgres::tls::{MakeTlsConnect, TlsConnect};
19use tokio_postgres::{Error, Socket};
20
21/// Connection configuration.
22///
23/// Configuration can be parsed from libpq-style connection strings. These strings come in two formats:
24///
25/// # Key-Value
26///
27/// This format consists of space-separated key-value pairs. Values which are either the empty string or contain
28/// whitespace should be wrapped in `'`. `'` and `\` characters should be backslash-escaped.
29///
30/// ## Keys
31///
32/// * `user` - The username to authenticate with. Defaults to the user executing this process.
33/// * `password` - The password to authenticate with.
34/// * `dbname` - The name of the database to connect to. Defaults to the username.
35/// * `options` - Command line options used to configure the server.
36/// * `application_name` - Sets the `application_name` parameter on the server.
37/// * `sslmode` - Controls usage of TLS. If set to `disable`, TLS will not be used. If set to `prefer`, TLS will be used
38///     if available, but not used otherwise. If set to `require`, TLS will be forced to be used. Defaults to `prefer`.
39/// * `host` - The host to connect to. On Unix platforms, if the host starts with a `/` character it is treated as the
40///     path to the directory containing Unix domain sockets. Otherwise, it is treated as a hostname. Multiple hosts
41///     can be specified, separated by commas. Each host will be tried in turn when connecting. Required if connecting
42///     with the `connect` method.
43/// * `sslnegotiation` - TLS negotiation method. If set to `direct`, the client will perform direct TLS handshake, this only works for PostgreSQL 17 and newer.
44///     Note that you will need to setup ALPN of TLS client configuration to `postgresql` when using direct TLS.
45///     If set to `postgres`, the default value, it follows original postgres wire protocol to perform the negotiation.
46/// * `hostaddr` - Numeric IP address of host to connect to. This should be in the standard IPv4 address format,
47///     e.g., 172.28.40.9. If your machine supports IPv6, you can also use those addresses.
48///     If this parameter is not specified, the value of `host` will be looked up to find the corresponding IP address,
49///     or if host specifies an IP address, that value will be used directly.
50///     Using `hostaddr` allows the application to avoid a host name look-up, which might be important in applications
51///     with time constraints. However, a host name is required for TLS certificate verification.
52///     Specifically:
53///         * If `hostaddr` is specified without `host`, the value for `hostaddr` gives the server network address.
54///             The connection attempt will fail if the authentication method requires a host name;
55///         * If `host` is specified without `hostaddr`, a host name lookup occurs;
56///         * If both `host` and `hostaddr` are specified, the value for `hostaddr` gives the server network address.
57///             The value for `host` is ignored unless the authentication method requires it,
58///             in which case it will be used as the host name.
59/// * `port` - The port to connect to. Multiple ports can be specified, separated by commas. The number of ports must be
60///     either 1, in which case it will be used for all hosts, or the same as the number of hosts. Defaults to 5432 if
61///     omitted or the empty string.
62/// * `connect_timeout` - The time limit in seconds applied to each socket-level connection attempt. Note that hostnames
63///     can resolve to multiple IP addresses, and this limit is applied to each address. Defaults to no timeout.
64/// * `tcp_user_timeout` - The time limit that transmitted data may remain unacknowledged before a connection is forcibly closed.
65///     This is ignored for Unix domain socket connections. It is only supported on systems where TCP_USER_TIMEOUT is available
66///     and will default to the system default if omitted or set to 0; on other systems, it has no effect.
67/// * `keepalives` - Controls the use of TCP keepalive. A value of 0 disables keepalive and nonzero integers enable it.
68///     This option is ignored when connecting with Unix sockets. Defaults to on.
69/// * `keepalives_idle` - The number of seconds of inactivity after which a keepalive message is sent to the server.
70///     This option is ignored when connecting with Unix sockets. Defaults to 2 hours.
71/// * `keepalives_interval` - The time interval between TCP keepalive probes.
72///     This option is ignored when connecting with Unix sockets.
73/// * `keepalives_retries` - The maximum number of TCP keepalive probes that will be sent before dropping a connection.
74///     This option is ignored when connecting with Unix sockets.
75/// * `target_session_attrs` - Specifies requirements of the session. If set to `read-write`, the client will check that
76///     the `transaction_read_write` session parameter is set to `on`. This can be used to connect to the primary server
77///     in a database cluster as opposed to the secondary read-only mirrors. Defaults to `all`.
78/// * `channel_binding` - Controls usage of channel binding in the authentication process. If set to `disable`, channel
79///     binding will not be used. If set to `prefer`, channel binding will be used if available, but not used otherwise.
80///     If set to `require`, the authentication process will fail if channel binding is not used. Defaults to `prefer`.
81/// * `load_balance_hosts` - Controls the order in which the client tries to connect to the available hosts and
82///     addresses. Once a connection attempt is successful no other hosts and addresses will be tried. This parameter
83///     is typically used in combination with multiple host names or a DNS record that returns multiple IPs. If set to
84///     `disable`, hosts and addresses will be tried in the order provided. If set to `random`, hosts will be tried
85///     in a random order, and the IP addresses resolved from a hostname will also be tried in a random order. Defaults
86///     to `disable`.
87///
88/// ## Examples
89///
90/// ```not_rust
91/// host=localhost user=postgres connect_timeout=10 keepalives=0
92/// ```
93///
94/// ```not_rust
95/// host=/var/lib/postgresql,localhost port=1234 user=postgres password='password with spaces'
96/// ```
97///
98/// ```not_rust
99/// host=host1,host2,host3 port=1234,,5678 hostaddr=127.0.0.1,127.0.0.2,127.0.0.3 user=postgres target_session_attrs=read-write
100/// ```
101///
102/// ```not_rust
103/// host=host1,host2,host3 port=1234,,5678 user=postgres target_session_attrs=read-write
104/// ```
105///
106/// # Url
107///
108/// This format resembles a URL with a scheme of either `postgres://` or `postgresql://`. All components are optional,
109/// and the format accepts query parameters for all of the key-value pairs described in the section above. Multiple
110/// host/port pairs can be comma-separated. Unix socket paths in the host section of the URL should be percent-encoded,
111/// as the path component of the URL specifies the database name.
112///
113/// ## Examples
114///
115/// ```not_rust
116/// postgresql://user@localhost
117/// ```
118///
119/// ```not_rust
120/// postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_timeout=10
121/// ```
122///
123/// ```not_rust
124/// postgresql://user@host1:1234,host2,host3:5678?target_session_attrs=read-write
125/// ```
126///
127/// ```not_rust
128/// postgresql:///mydb?user=user&host=/var/lib/postgresql
129/// ```
130#[derive(Clone)]
131pub struct Config {
132    config: tokio_postgres::Config,
133    notice_callback: Arc<dyn Fn(DbError) + Send + Sync>,
134}
135
136impl fmt::Debug for Config {
137    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
138        fmt.debug_struct("Config")
139            .field("config", &self.config)
140            .finish()
141    }
142}
143
144impl Default for Config {
145    fn default() -> Config {
146        Config::new()
147    }
148}
149
150impl Config {
151    /// Creates a new configuration.
152    pub fn new() -> Config {
153        tokio_postgres::Config::new().into()
154    }
155
156    /// Sets the user to authenticate with.
157    ///
158    /// If the user is not set, then this defaults to the user executing this process.
159    pub fn user(&mut self, user: &str) -> &mut Config {
160        self.config.user(user);
161        self
162    }
163
164    /// Gets the user to authenticate with, if one has been configured with
165    /// the `user` method.
166    pub fn get_user(&self) -> Option<&str> {
167        self.config.get_user()
168    }
169
170    /// Sets the password to authenticate with.
171    pub fn password<T>(&mut self, password: T) -> &mut Config
172    where
173        T: AsRef<[u8]>,
174    {
175        self.config.password(password);
176        self
177    }
178
179    /// Gets the password to authenticate with, if one has been configured with
180    /// the `password` method.
181    pub fn get_password(&self) -> Option<&[u8]> {
182        self.config.get_password()
183    }
184
185    /// Sets the name of the database to connect to.
186    ///
187    /// Defaults to the user.
188    pub fn dbname(&mut self, dbname: &str) -> &mut Config {
189        self.config.dbname(dbname);
190        self
191    }
192
193    /// Gets the name of the database to connect to, if one has been configured
194    /// with the `dbname` method.
195    pub fn get_dbname(&self) -> Option<&str> {
196        self.config.get_dbname()
197    }
198
199    /// Sets command line options used to configure the server.
200    pub fn options(&mut self, options: &str) -> &mut Config {
201        self.config.options(options);
202        self
203    }
204
205    /// Gets the command line options used to configure the server, if the
206    /// options have been set with the `options` method.
207    pub fn get_options(&self) -> Option<&str> {
208        self.config.get_options()
209    }
210
211    /// Sets the value of the `application_name` runtime parameter.
212    pub fn application_name(&mut self, application_name: &str) -> &mut Config {
213        self.config.application_name(application_name);
214        self
215    }
216
217    /// Gets the value of the `application_name` runtime parameter, if it has
218    /// been set with the `application_name` method.
219    pub fn get_application_name(&self) -> Option<&str> {
220        self.config.get_application_name()
221    }
222
223    /// Sets the SSL configuration.
224    ///
225    /// Defaults to `prefer`.
226    pub fn ssl_mode(&mut self, ssl_mode: SslMode) -> &mut Config {
227        self.config.ssl_mode(ssl_mode);
228        self
229    }
230
231    /// Gets the SSL configuration.
232    pub fn get_ssl_mode(&self) -> SslMode {
233        self.config.get_ssl_mode()
234    }
235
236    /// Sets the SSL negotiation method
237    pub fn ssl_negotiation(&mut self, ssl_negotiation: SslNegotiation) -> &mut Config {
238        self.config.ssl_negotiation(ssl_negotiation);
239        self
240    }
241
242    /// Gets the SSL negotiation method
243    pub fn get_ssl_negotiation(&self) -> SslNegotiation {
244        self.config.get_ssl_negotiation()
245    }
246
247    /// Adds a host to the configuration.
248    ///
249    /// Multiple hosts can be specified by calling this method multiple times, and each will be tried in order. On Unix
250    /// systems, a host starting with a `/` is interpreted as a path to a directory containing Unix domain sockets.
251    /// There must be either no hosts, or the same number of hosts as hostaddrs.
252    pub fn host(&mut self, host: &str) -> &mut Config {
253        self.config.host(host);
254        self
255    }
256
257    /// Gets the hosts that have been added to the configuration with `host`.
258    pub fn get_hosts(&self) -> &[Host] {
259        self.config.get_hosts()
260    }
261
262    /// Gets the hostaddrs that have been added to the configuration with `hostaddr`.
263    pub fn get_hostaddrs(&self) -> &[IpAddr] {
264        self.config.get_hostaddrs()
265    }
266
267    /// Adds a Unix socket host to the configuration.
268    ///
269    /// Unlike `host`, this method allows non-UTF8 paths.
270    #[cfg(unix)]
271    pub fn host_path<T>(&mut self, host: T) -> &mut Config
272    where
273        T: AsRef<Path>,
274    {
275        self.config.host_path(host);
276        self
277    }
278
279    /// Adds a hostaddr to the configuration.
280    ///
281    /// Multiple hostaddrs can be specified by calling this method multiple times, and each will be tried in order.
282    /// There must be either no hostaddrs, or the same number of hostaddrs as hosts.
283    pub fn hostaddr(&mut self, hostaddr: IpAddr) -> &mut Config {
284        self.config.hostaddr(hostaddr);
285        self
286    }
287
288    /// Adds a port to the configuration.
289    ///
290    /// Multiple ports can be specified by calling this method multiple times. There must either be no ports, in which
291    /// case the default of 5432 is used, a single port, in which it is used for all hosts, or the same number of ports
292    /// as hosts.
293    pub fn port(&mut self, port: u16) -> &mut Config {
294        self.config.port(port);
295        self
296    }
297
298    /// Gets the ports that have been added to the configuration with `port`.
299    pub fn get_ports(&self) -> &[u16] {
300        self.config.get_ports()
301    }
302
303    /// Sets the timeout applied to socket-level connection attempts.
304    ///
305    /// Note that hostnames can resolve to multiple IP addresses, and this timeout will apply to each address of each
306    /// host separately. Defaults to no limit.
307    pub fn connect_timeout(&mut self, connect_timeout: Duration) -> &mut Config {
308        self.config.connect_timeout(connect_timeout);
309        self
310    }
311
312    /// Gets the connection timeout, if one has been set with the
313    /// `connect_timeout` method.
314    pub fn get_connect_timeout(&self) -> Option<&Duration> {
315        self.config.get_connect_timeout()
316    }
317
318    /// Sets the TCP user timeout.
319    ///
320    /// This is ignored for Unix domain socket connections. It is only supported on systems where
321    /// TCP_USER_TIMEOUT is available and will default to the system default if omitted or set to 0;
322    /// on other systems, it has no effect.
323    pub fn tcp_user_timeout(&mut self, tcp_user_timeout: Duration) -> &mut Config {
324        self.config.tcp_user_timeout(tcp_user_timeout);
325        self
326    }
327
328    /// Gets the TCP user timeout, if one has been set with the
329    /// `user_timeout` method.
330    pub fn get_tcp_user_timeout(&self) -> Option<&Duration> {
331        self.config.get_tcp_user_timeout()
332    }
333
334    /// Controls the use of TCP keepalive.
335    ///
336    /// This is ignored for Unix domain socket connections. Defaults to `true`.
337    pub fn keepalives(&mut self, keepalives: bool) -> &mut Config {
338        self.config.keepalives(keepalives);
339        self
340    }
341
342    /// Reports whether TCP keepalives will be used.
343    pub fn get_keepalives(&self) -> bool {
344        self.config.get_keepalives()
345    }
346
347    /// Sets the amount of idle time before a keepalive packet is sent on the connection.
348    ///
349    /// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled. Defaults to 2 hours.
350    pub fn keepalives_idle(&mut self, keepalives_idle: Duration) -> &mut Config {
351        self.config.keepalives_idle(keepalives_idle);
352        self
353    }
354
355    /// Gets the configured amount of idle time before a keepalive packet will
356    /// be sent on the connection.
357    pub fn get_keepalives_idle(&self) -> Duration {
358        self.config.get_keepalives_idle()
359    }
360
361    /// Sets the time interval between TCP keepalive probes.
362    /// On Windows, this sets the value of the tcp_keepalive struct’s keepaliveinterval field.
363    ///
364    /// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
365    pub fn keepalives_interval(&mut self, keepalives_interval: Duration) -> &mut Config {
366        self.config.keepalives_interval(keepalives_interval);
367        self
368    }
369
370    /// Gets the time interval between TCP keepalive probes.
371    pub fn get_keepalives_interval(&self) -> Option<Duration> {
372        self.config.get_keepalives_interval()
373    }
374
375    /// Sets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
376    ///
377    /// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
378    pub fn keepalives_retries(&mut self, keepalives_retries: u32) -> &mut Config {
379        self.config.keepalives_retries(keepalives_retries);
380        self
381    }
382
383    /// Gets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
384    pub fn get_keepalives_retries(&self) -> Option<u32> {
385        self.config.get_keepalives_retries()
386    }
387
388    /// Sets the requirements of the session.
389    ///
390    /// This can be used to connect to the primary server in a clustered database rather than one of the read-only
391    /// secondary servers. Defaults to `Any`.
392    pub fn target_session_attrs(
393        &mut self,
394        target_session_attrs: TargetSessionAttrs,
395    ) -> &mut Config {
396        self.config.target_session_attrs(target_session_attrs);
397        self
398    }
399
400    /// Gets the requirements of the session.
401    pub fn get_target_session_attrs(&self) -> TargetSessionAttrs {
402        self.config.get_target_session_attrs()
403    }
404
405    /// Sets the channel binding behavior.
406    ///
407    /// Defaults to `prefer`.
408    pub fn channel_binding(&mut self, channel_binding: ChannelBinding) -> &mut Config {
409        self.config.channel_binding(channel_binding);
410        self
411    }
412
413    /// Gets the channel binding behavior.
414    pub fn get_channel_binding(&self) -> ChannelBinding {
415        self.config.get_channel_binding()
416    }
417
418    /// Sets the host load balancing behavior.
419    ///
420    /// Defaults to `disable`.
421    pub fn load_balance_hosts(&mut self, load_balance_hosts: LoadBalanceHosts) -> &mut Config {
422        self.config.load_balance_hosts(load_balance_hosts);
423        self
424    }
425
426    /// Gets the host load balancing behavior.
427    pub fn get_load_balance_hosts(&self) -> LoadBalanceHosts {
428        self.config.get_load_balance_hosts()
429    }
430
431    /// Sets the notice callback.
432    ///
433    /// This callback will be invoked with the contents of every
434    /// [`AsyncMessage::Notice`] that is received by the connection. Notices use
435    /// the same structure as errors, but they are not "errors" per-se.
436    ///
437    /// Notices are distinct from notifications, which are instead accessible
438    /// via the [`Notifications`] API.
439    ///
440    /// [`AsyncMessage::Notice`]: tokio_postgres::AsyncMessage::Notice
441    /// [`Notifications`]: crate::Notifications
442    pub fn notice_callback<F>(&mut self, f: F) -> &mut Config
443    where
444        F: Fn(DbError) + Send + Sync + 'static,
445    {
446        self.notice_callback = Arc::new(f);
447        self
448    }
449
450    /// Opens a connection to a PostgreSQL database.
451    pub fn connect<T>(&self, tls: T) -> Result<Client, Error>
452    where
453        T: MakeTlsConnect<Socket> + 'static + Send,
454        T::TlsConnect: Send,
455        T::Stream: Send,
456        <T::TlsConnect as TlsConnect<Socket>>::Future: Send,
457    {
458        let runtime = runtime::Builder::new_current_thread()
459            .enable_all()
460            .build()
461            .unwrap(); // FIXME don't unwrap
462
463        let (client, connection) = runtime.block_on(self.config.connect(tls))?;
464
465        let connection = Connection::new(runtime, connection, self.notice_callback.clone());
466        Ok(Client::new(connection, client))
467    }
468}
469
470impl FromStr for Config {
471    type Err = Error;
472
473    fn from_str(s: &str) -> Result<Config, Error> {
474        s.parse::<tokio_postgres::Config>().map(Config::from)
475    }
476}
477
478impl From<tokio_postgres::Config> for Config {
479    fn from(config: tokio_postgres::Config) -> Config {
480        Config {
481            config,
482            notice_callback: Arc::new(|notice| {
483                info!("{}: {}", notice.severity(), notice.message())
484            }),
485        }
486    }
487}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy