4
0

https.rs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #![cfg_attr(not(feature="https"), allow(unused))]
  2. use async_trait::async_trait;
  3. use log::*;
  4. use dns::{Request, Response};
  5. use super::{Transport, Error};
  6. /// The **HTTPS transport**, which uses Hyper.
  7. ///
  8. /// # Examples
  9. ///
  10. /// ```no_run
  11. /// use dns_transport::{Transport, HttpsTransport};
  12. /// use dns::{Request, Flags, Query, Labels, QClass, qtype, record::A};
  13. ///
  14. /// let query = Query {
  15. /// qname: Labels::encode("dns.lookup.dog").unwrap(),
  16. /// qclass: QClass::IN,
  17. /// qtype: qtype!(A),
  18. /// };
  19. ///
  20. /// let request = Request {
  21. /// transaction_id: 0xABCD,
  22. /// flags: Flags::query(),
  23. /// query: query,
  24. /// additional: None,
  25. /// };
  26. ///
  27. /// let transport = HttpsTransport::new("https://cloudflare-dns.com/dns-query");
  28. /// transport.send(&request);
  29. /// ```
  30. #[derive(Debug)]
  31. pub struct HttpsTransport {
  32. url: String,
  33. }
  34. impl HttpsTransport {
  35. /// Creates a new HTTPS transport that connects to the given URL.
  36. pub fn new(url: impl Into<String>) -> Self {
  37. Self { url: url.into() }
  38. }
  39. }
  40. #[async_trait]
  41. impl Transport for HttpsTransport {
  42. #[cfg(feature="https")]
  43. async fn send(&self, request: &Request) -> Result<Response, Error> {
  44. use hyper::body::HttpBody as _;
  45. let https = hyper_tls::HttpsConnector::new();
  46. let client = hyper::Client::builder().build::<_, hyper::Body>(https);
  47. let bytes = request.to_bytes().expect("failed to serialise request");
  48. info!("Sending {} bytes of data to {:?}", bytes.len(), self.url);
  49. let request = hyper::Request::builder()
  50. .method("POST")
  51. .uri(&self.url)
  52. .header("Content-Type", "application/dns-message")
  53. .header("Accept", "application/dns-message")
  54. .body(hyper::Body::from(bytes))
  55. .expect("Failed to build request"); // we control the request, so this should never fail
  56. let mut response = client.request(request).await?;
  57. debug!("Response: {}", response.status());
  58. debug!("Headers: {:#?}", response.headers());
  59. if response.status() != 200 {
  60. return Err(Error::BadRequest);
  61. }
  62. debug!("Reading body...");
  63. let mut buf = Vec::new();
  64. while let Some(chunk) = response.body_mut().data().await {
  65. buf.extend(&chunk?);
  66. }
  67. info!("Received {} bytes of data", buf.len());
  68. let response = Response::from_bytes(&buf)?;
  69. Ok(response)
  70. }
  71. #[cfg(not(feature="https"))]
  72. async fn send(&self, _request: &Request) -> Result<Response, Error> {
  73. unimplemented!("HTTPS feature disabled")
  74. }
  75. }