···39394040### Features
41414242-| Feature | Description |
4343-| --------- | ---------------------------------------------------------------- |
4444-| `ast` | Construct AST trees from raw Gemtext. |
4545-| `convert` | Convert from Gemtext to markup formats such as HTML or Markdown. |
4646-| `request` | Make Gemini requests and get sane, structured results. |
4747-| `meta` | Structure-ize a Gemini response's meta section |
4848-| `macros` | Macros to aid with various Germ-related functionalities |
4949-| `quick` | Quick functions to create valid Gemtext elements from input |
5050-| `sync` | An asynchronous version of `request` |
4242+| Feature | Description |
4343+| ---------- | ---------------------------------------------------------------- |
4444+| `default` | `ast`, `convert`, `meta`, `request` |
4545+| `ast` | Construct AST trees from raw Gemtext. |
4646+| `blocking` | Blocking equivalent of `request` |
4747+| `convert` | Convert from Gemtext to markup formats such as HTML or Markdown. |
4848+| `request` | Make Gemini requests and get sane, structured results. |
4949+| `meta` | Structure-ize a Gemini response's meta section |
5050+| `macros` | Macros to aid with various Germ-related functionalities |
5151+| `quick` | Quick functions to create valid Gemtext elements from input |
51525253### Examples
5354
···11// This file is part of Germ <https://github.com/gemrest/germ>.
22-// Copyright (C) 2022-2022 Fuwn <contact@fuwn.me>
22+// Copyright (C) 2022-2023 Fuwn <contact@fuwn.me>
33//
44// This program is free software: you can redistribute it and/or modify
55// it under the terms of the GNU General Public License as published by
···2222mod status;
2323mod verifier;
24242525-#[cfg(feature = "sync")] pub mod sync;
2525+#[cfg(feature = "blocking")]
2626+pub mod blocking;
26272727-use std::io::{Read, Write};
2828+#[cfg(feature = "request")]
2929+pub mod non_blocking;
3030+3131+#[cfg(feature = "request")]
3232+pub use non_blocking::request;
28332934pub(crate) use verifier::GermVerifier;
3035pub use {response::Response, status::Status};
3131-3232-/// Make a request to a Gemini server. The `url` **should** be prefixed with a
3333-/// scheme (e.g. "gemini://").
3434-///
3535-/// # Example
3636-///
3737-/// ```rust
3838-/// match germ::request::request(&url::Url::parse("gemini://fuwn.me").unwrap()) {
3939-/// Ok(response) => println!("{:?}", response),
4040-/// Err(_) => {}
4141-/// }
4242-/// ```
4343-///
4444-/// # Errors
4545-/// - May error if the URL is invalid
4646-/// - May error if the TLS write fails
4747-/// - May error if the TLS read fails
4848-pub fn request(url: &url::Url) -> anyhow::Result<Response> {
4949- let config = rustls::ClientConfig::builder()
5050- .with_safe_defaults()
5151- .with_custom_certificate_verifier(std::sync::Arc::new(GermVerifier::new()))
5252- .with_no_client_auth();
5353- let mut connection = rustls::ClientConnection::new(
5454- std::sync::Arc::new(config),
5555- url.domain().unwrap_or("").try_into()?,
5656- )?;
5757- let mut stream = std::net::TcpStream::connect(format!(
5858- "{}:{}",
5959- url.domain().unwrap_or(""),
6060- url.port().unwrap_or(1965)
6161- ))?;
6262- let mut tls = rustls::Stream::new(&mut connection, &mut stream);
6363-6464- tls.write_all(format!("{url}\r\n").as_bytes())?;
6565-6666- let mut plain_text = Vec::new();
6767-6868- tls.read_to_end(&mut plain_text)?;
6969-7070- Ok(Response::new(&plain_text, tls.conn.negotiated_cipher_suite()))
7171-}
+63
src/request/blocking.rs
···11+// This file is part of Germ <https://github.com/gemrest/germ>.
22+// Copyright (C) 2022-2022 Fuwn <contact@fuwn.me>
33+//
44+// This program is free software: you can redistribute it and/or modify
55+// it under the terms of the GNU General Public License as published by
66+// the Free Software Foundation, version 3.
77+//
88+// This program is distributed in the hope that it will be useful, but
99+// WITHOUT ANY WARRANTY; without even the implied warranty of
1010+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1111+// General Public License for more details.
1212+//
1313+// You should have received a copy of the GNU General Public License
1414+// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515+//
1616+// Copyright (C) 2022-2022 Fuwn <contact@fuwn.me>
1717+// SPDX-License-Identifier: GPL-3.0-only
1818+1919+use {
2020+ crate::request::{GermVerifier, Response},
2121+ std::io::{Read, Write},
2222+};
2323+2424+/// Make a request to a Gemini server. The `url` **should** be prefixed with a
2525+/// scheme (e.g. "gemini://").
2626+///
2727+/// # Example
2828+///
2929+/// ```rust
3030+/// match germ::request::request(&url::Url::parse("gemini://fuwn.me").unwrap()) {
3131+/// Ok(response) => println!("{:?}", response),
3232+/// Err(_) => {}
3333+/// }
3434+/// ```
3535+///
3636+/// # Errors
3737+/// - May error if the URL is invalid
3838+/// - May error if the TLS write fails
3939+/// - May error if the TLS read fails
4040+pub fn request(url: &url::Url) -> anyhow::Result<Response> {
4141+ let config = rustls::ClientConfig::builder()
4242+ .with_safe_defaults()
4343+ .with_custom_certificate_verifier(std::sync::Arc::new(GermVerifier::new()))
4444+ .with_no_client_auth();
4545+ let mut connection = rustls::ClientConnection::new(
4646+ std::sync::Arc::new(config),
4747+ url.domain().unwrap_or("").try_into()?,
4848+ )?;
4949+ let mut stream = std::net::TcpStream::connect(format!(
5050+ "{}:{}",
5151+ url.domain().unwrap_or(""),
5252+ url.port().unwrap_or(1965)
5353+ ))?;
5454+ let mut tls = rustls::Stream::new(&mut connection, &mut stream);
5555+5656+ tls.write_all(format!("{url}\r\n").as_bytes())?;
5757+5858+ let mut plain_text = Vec::new();
5959+6060+ tls.read_to_end(&mut plain_text)?;
6161+6262+ Ok(Response::new(&plain_text, tls.conn.negotiated_cipher_suite()))
6363+}
+1-1
src/request/sync.rs
src/request/non_blocking.rs
···11// This file is part of Germ <https://github.com/gemrest/germ>.
22-// Copyright (C) 2022-2023 Fuwn <contact@fuwn.me>
22+// Copyright (C) 2022-2024 Fuwn <contact@fuwn.me>
33//
44// This program is free software: you can redistribute it and/or modify
55// it under the terms of the GNU General Public License as published by