Skip to content

Commit 7971e86

Browse files
committed
DNS lookup
1 parent 20b7b54 commit 7971e86

3 files changed

Lines changed: 67 additions & 32 deletions

File tree

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct Person {
2222
}
2323

2424
fn main() {
25-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
25+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
2626

2727
conn.update("CREATE TABLE person (
2828
id SERIAL PRIMARY KEY,
@@ -74,9 +74,6 @@ Connect to a Postgres server using the standard URI format:
7474
```rust
7575
let conn = PostgresConnection::connect("postgres://user:pass@host:port/database?arg1=val1&arg2=val2");
7676
```
77-
As the Rust standard library currently lacks DNS lookup functionality, `host`
78-
must currently be an IP address.
79-
8077
`pass` may be omitted if not needed. `port` defaults to `5432` and `database`
8178
defaults to the value of `user` if not specified. The driver supports `trust`,
8279
`password` and `md5` authentication.

src/lib.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use std::cell::Cell;
1313
use std::hashmap::HashMap;
1414
use std::rt::io::{io_error, Decorator};
1515
use std::rt::io::mem::MemWriter;
16+
use std::rt::io::net;
17+
use std::rt::io::net::ip;
1618
use std::rt::io::net::ip::SocketAddr;
1719
use std::rt::io::net::tcp::TcpStream;
1820

@@ -70,6 +72,8 @@ fn handle_notice_response(fields: ~[(u8, ~str)]) {
7072
pub enum PostgresConnectError {
7173
InvalidUrl,
7274
MissingUser,
75+
DnsError,
76+
SocketError,
7377
DbError(PostgresDbError),
7478
MissingPassword,
7579
UnsupportedAuthentication
@@ -164,17 +168,19 @@ impl PostgresConnection {
164168
};
165169
let mut args = args;
166170

167-
// This seems silly
168-
let socket_url = format!("{}:{}", host,
169-
port.unwrap_or_default(~"5432"));
170-
let addr: SocketAddr = match FromStr::from_str(socket_url) {
171-
Some(addr) => addr,
172-
None => return Err(InvalidUrl)
171+
let port = match port {
172+
Some(port) => FromStr::from_str(port).unwrap(),
173+
None => 5432
174+
};
175+
176+
let stream = match PostgresConnection::open_socket(host, port) {
177+
Ok(stream) => stream,
178+
Err(err) => return Err(err)
173179
};
174180

175181
let conn = PostgresConnection {
176182
// Need to figure out what to do about unwrap here
177-
stream: Cell::new(TcpStream::connect(addr).unwrap()),
183+
stream: Cell::new(stream),
178184
next_stmt_id: Cell::new(0)
179185
};
180186

@@ -204,6 +210,29 @@ impl PostgresConnection {
204210
Ok(conn)
205211
}
206212

213+
fn open_socket(host: &str, port: ip::Port)
214+
-> Result<TcpStream, PostgresConnectError> {
215+
let addrs = do io_error::cond.trap(|_| {}).inside {
216+
net::get_host_addresses(host)
217+
};
218+
let addrs = match addrs {
219+
Some(addrs) => addrs,
220+
None => return Err(DnsError)
221+
};
222+
223+
for addr in addrs.iter() {
224+
let socket = do io_error::cond.trap(|_| {}).inside {
225+
TcpStream::connect(SocketAddr { ip: *addr, port: port })
226+
};
227+
match socket {
228+
Some(socket) => return Ok(socket),
229+
None => ()
230+
}
231+
}
232+
233+
Err(SocketError)
234+
}
235+
207236
fn write_messages(&self, messages: &[&FrontendMessage]) {
208237
let mut buf = MemWriter::new();
209238
for &message in messages.iter() {

src/test.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use postgres::types::{ToSql, FromSql, PgInt4, PgVarchar};
1313

1414
#[test]
1515
fn test_prepare_err() {
16-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
16+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
1717
match conn.try_prepare("invalid sql statment") {
1818
Err(PostgresDbError { position, code, _ }) => {
1919
assert_eq!(code, ~"42601");
@@ -28,7 +28,7 @@ fn test_prepare_err() {
2828
2929
#[test]
3030
fn test_transaction_commit() {
31-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
31+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
3232
conn.update("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY)", []);
3333

3434
do conn.in_transaction |trans| {
@@ -43,7 +43,7 @@ fn test_transaction_commit() {
4343

4444
#[test]
4545
fn test_transaction_rollback() {
46-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
46+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
4747
conn.update("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY)", []);
4848

4949
conn.update("INSERT INTO foo (id) VALUES ($1)", [&1i32 as &ToSql]);
@@ -60,7 +60,7 @@ fn test_transaction_rollback() {
6060

6161
#[test]
6262
fn test_nested_transactions() {
63-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
63+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
6464
conn.update("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY)", []);
6565

6666
conn.update("INSERT INTO foo (id) VALUES (1)", []);
@@ -102,7 +102,7 @@ fn test_nested_transactions() {
102102

103103
#[test]
104104
fn test_query() {
105-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
105+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
106106
conn.update("CREATE TEMPORARY TABLE foo (id BIGINT PRIMARY KEY)", []);
107107
conn.update("INSERT INTO foo (id) VALUES ($1), ($2)",
108108
[&1i64 as &ToSql, &2i64 as &ToSql]);
@@ -114,7 +114,7 @@ fn test_query() {
114114

115115
#[test]
116116
fn test_lazy_query() {
117-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
117+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
118118

119119
do conn.in_transaction |trans| {
120120
trans.update("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY)", []);
@@ -134,22 +134,22 @@ fn test_lazy_query() {
134134

135135
#[test]
136136
fn test_param_types() {
137-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
137+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
138138
let stmt = conn.prepare("SELECT $1::INT, $2::VARCHAR");
139139
assert_eq!(stmt.param_types(), [PgInt4, PgVarchar]);
140140
}
141141

142142
#[test]
143143
fn test_result_descriptions() {
144-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
144+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
145145
let stmt = conn.prepare("SELECT 1::INT as a, 'hi'::VARCHAR as b");
146146
assert_eq!(stmt.result_descriptions(),
147147
[ResultDescription { name: ~"a", ty: PgInt4},
148148
ResultDescription { name: ~"b", ty: PgVarchar}]);
149149
}
150150
151151
fn test_type<T: Eq+FromSql+ToSql>(sql_type: &str, checks: &[(T, &str)]) {
152-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
152+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
153153
for &(ref val, ref repr) in checks.iter() {
154154
let stmt = conn.prepare("SELECT " + *repr + "::" + sql_type);
155155
let result = stmt.query([]).next().unwrap()[0];
@@ -223,7 +223,7 @@ fn test_text_params() {
223223
224224
#[test]
225225
fn test_bpchar_params() {
226-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
226+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
227227
conn.update("CREATE TEMPORARY TABLE foo (
228228
id SERIAL PRIMARY KEY,
229229
b CHAR(5)
@@ -273,7 +273,7 @@ fn test_tm_params() {
273273
}
274274
275275
fn test_nan_param<T: Float+ToSql+FromSql>(sql_type: &str) {
276-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
276+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
277277
let nan: T = Float::NaN();
278278
let stmt = conn.prepare("SELECT $1::" + sql_type);
279279
let mut result = stmt.query([&nan as &ToSql]);
@@ -294,13 +294,13 @@ fn test_f64_nan_param() {
294294
#[test]
295295
#[should_fail]
296296
fn test_wrong_param_type() {
297-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
297+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
298298
conn.try_update("SELECT $1::VARCHAR", [&1i32 as &ToSql]);
299299
}
300300

301301
#[test]
302302
fn test_find_col_named() {
303-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
303+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
304304
let stmt = conn.prepare("SELECT 1 as my_id, 'hi' as val");
305305
assert_eq!(Some(0), stmt.find_col_named("my_id"));
306306
assert_eq!(Some(1), stmt.find_col_named("val"));
@@ -309,7 +309,7 @@ fn test_find_col_named() {
309309

310310
#[test]
311311
fn test_get_named() {
312-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
312+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
313313
let stmt = conn.prepare("SELECT 10::INT as val");
314314
let result = stmt.query([]);
315315

@@ -319,7 +319,7 @@ fn test_get_named() {
319319
#[test]
320320
#[should_fail]
321321
fn test_get_named_fail() {
322-
let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1");
322+
let conn = PostgresConnection::connect("postgres://postgres@localhost");
323323
let stmt = conn.prepare("SELECT 10::INT as id");
324324
let mut result = stmt.query([]);
325325

@@ -328,12 +328,12 @@ fn test_get_named_fail() {
328328

329329
#[test]
330330
fn test_plaintext_pass() {
331-
PostgresConnection::connect("postgres://pass_user:password@127.0.0.1");
331+
PostgresConnection::connect("postgres://pass_user:password@localhost");
332332
}
333333

334334
#[test]
335335
fn test_plaintext_pass_no_pass() {
336-
let ret = PostgresConnection::try_connect("postgres://pass_user@127.0.0.1");
336+
let ret = PostgresConnection::try_connect("postgres://pass_user@localhost");
337337
match ret {
338338
Err(MissingPassword) => (),
339339
ret => fail!("Unexpected result %?", ret)
@@ -342,7 +342,7 @@ fn test_plaintext_pass_no_pass() {
342342

343343
#[test]
344344
fn test_plaintext_pass_wrong_pass() {
345-
let ret = PostgresConnection::try_connect("postgres://pass_user:asdf@127.0.0.1");
345+
let ret = PostgresConnection::try_connect("postgres://pass_user:asdf@localhost");
346346
match ret {
347347
Err(DbError(PostgresDbError { code: ~"28P01", _ })) => (),
348348
ret => fail!("Unexpected result %?", ret)
@@ -351,12 +351,12 @@ fn test_plaintext_pass_wrong_pass() {
351351
352352
#[test]
353353
fn test_md5_pass() {
354-
PostgresConnection::connect("postgres://md5_user:password@127.0.0.1");
354+
PostgresConnection::connect("postgres://md5_user:password@localhost");
355355
}
356356

357357
#[test]
358358
fn test_md5_pass_no_pass() {
359-
let ret = PostgresConnection::try_connect("postgres://md5_user@127.0.0.1");
359+
let ret = PostgresConnection::try_connect("postgres://md5_user@localhost");
360360
match ret {
361361
Err(MissingPassword) => (),
362362
ret => fail!("Unexpected result %?", ret)
@@ -365,9 +365,18 @@ fn test_md5_pass_no_pass() {
365365

366366
#[test]
367367
fn test_md5_pass_wrong_pass() {
368-
let ret = PostgresConnection::try_connect("postgres://md5_user:asdf@127.0.0.1");
368+
let ret = PostgresConnection::try_connect("postgres://md5_user:asdf@localhost");
369369
match ret {
370370
Err(DbError(PostgresDbError { code: ~"28P01", _ })) => (),
371371
ret => fail!("Unexpected result %?", ret)
372372
}
373373
}
374+
375+
#[test]
376+
fn test_dns_failure() {
377+
let ret = PostgresConnection::try_connect("postgres://postgres@asdfasdfasdf");
378+
match ret {
379+
Err(DnsError) => (),
380+
ret => fail!("Unexpected result %?", ret)
381+
}
382+
}

0 commit comments

Comments
 (0)