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