├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── azure-pipelines.yml ├── ci ├── azure-install-rust.yml ├── azure-rustfmt.yml └── azure-test-all.yml ├── src ├── lib.rs └── tcp.rs └── tests └── basic.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.1.0 (May 24, 2019) 2 | 3 | - Initial release 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http-connection" 3 | # When releasing to crates.io: 4 | # - Remove path dependencies 5 | # - Update html_root_url. 6 | # - Update doc url 7 | # - Cargo.toml 8 | # - README.md 9 | # - Update CHANGELOG.md. 10 | # - Create "v0.1.x" git tag. 11 | version = "0.1.0" 12 | authors = ["Lucio Franco "] 13 | readme = "README.md" 14 | documentation = "https://docs.rs/http-connection/0.1.0/http-connection" 15 | homepage = "https://github.com/hyperium/http-connection" 16 | license = "MIT" 17 | description = """ 18 | Trait representing HTTP connections. 19 | """ 20 | keywords = ["http"] 21 | categories = ["web-programming"] 22 | 23 | [dependencies] 24 | http = "0.1" 25 | tokio-tcp = { version = "0.1", optional = true } 26 | 27 | [features] 28 | default = ["tcp"] 29 | tcp = ["tokio-tcp"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Hyper Contributors 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTTP Connection 2 | 3 | A trait representing asynchronous HTTP connection. 4 | 5 | [![Build Status][azure-badge]][azure-url] 6 | 7 | [azure-badge]: https://dev.azure.com/hyperium/http-connection/_apis/build/status/hyperium.http-connection?branchName=master 8 | [azure-url]: https://dev.azure.com/hyperium/http-connection/_build/latest?definitionId=1&branchName=master 9 | 10 | More information about this crate can be found in the [crate 11 | documentation][dox]. 12 | 13 | [dox]: https://docs.rs/http-connection 14 | 15 | ## Usage 16 | 17 | To use `http-connection`, first add this to your `Cargo.toml`: 18 | 19 | ```toml 20 | [dependencies] 21 | http-connection = "0.1.0" 22 | ``` 23 | 24 | Next, add this to your crate: 25 | 26 | ```rust 27 | use http_connection::HttpConnection; 28 | 29 | fn main() { 30 | // ... 31 | } 32 | ``` 33 | 34 | ## License 35 | 36 | This project is licensed under the [MIT license](LICENSE). 37 | 38 | ### Contribution 39 | 40 | Unless you explicitly state otherwise, any contribution intentionally submitted 41 | for inclusion in `http-connection` by you, shall be licensed as MIT, without any additional 42 | terms or conditions. 43 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: ["master"] 2 | pr: ["master"] 3 | 4 | jobs: 5 | # Check formatting 6 | - job: rustfmt 7 | pool: 8 | vmImage: ubuntu-16.04 9 | steps: 10 | - template: ci/azure-rustfmt.yml 11 | 12 | # Run tests 13 | - template: ci/azure-test-all.yml 14 | -------------------------------------------------------------------------------- /ci/azure-install-rust.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | # Linux and macOS. 3 | - script: | 4 | set -e 5 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUSTUP_TOOLCHAIN 6 | echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin" 7 | env: 8 | RUSTUP_TOOLCHAIN: ${{parameters.rust_version}} 9 | displayName: "Install rust (*nix)" 10 | condition: not(eq(variables['Agent.OS'], 'Windows_NT')) 11 | # Windows. 12 | - script: | 13 | curl -sSf -o rustup-init.exe https://win.rustup.rs 14 | rustup-init.exe -y --default-toolchain %RUSTUP_TOOLCHAIN% 15 | set PATH=%PATH%;%USERPROFILE%\.cargo\bin 16 | echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin" 17 | env: 18 | RUSTUP_TOOLCHAIN: ${{parameters.rust_version}} 19 | displayName: "Install rust (windows)" 20 | condition: eq(variables['Agent.OS'], 'Windows_NT') 21 | # All platforms. 22 | - script: | 23 | rustc -Vv 24 | cargo -V 25 | displayName: Query rust and cargo versions 26 | -------------------------------------------------------------------------------- /ci/azure-rustfmt.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: azure-install-rust.yml 3 | parameters: 4 | rust_version: stable 5 | - bash: | 6 | rustup component add rustfmt 7 | displayName: Install rustfmt 8 | - bash: | 9 | cargo fmt --all -- --check 10 | displayName: Check formatting 11 | -------------------------------------------------------------------------------- /ci/azure-test-all.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: cargo_test_all 3 | displayName: cargo test 4 | pool: 5 | vmImage: ubuntu-16.04 6 | strategy: 7 | matrix: 8 | stable: 9 | rust_version: stable 10 | beta: 11 | rust_version: beta 12 | nightly: 13 | rust_version: nightly 14 | steps: 15 | - template: azure-install-rust.yml 16 | parameters: 17 | rust_version: $(rust_version) 18 | - script: cargo test 19 | displayName: cargo test 20 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc(html_root_url = "https://docs.rs/http-connection/0.1.0")] 2 | #![deny(missing_debug_implementations, missing_docs, unreachable_pub)] 3 | #![cfg_attr(test, deny(warnings))] 4 | 5 | //! Asynchronous HTTP connection 6 | //! 7 | //! This trait decorates an `AsyncRead + AsyncWrite` connection stream/sink with HTTP 8 | //! aware information like the connections HTTP version and the remote address. 9 | 10 | extern crate http; 11 | #[cfg(feature = "tcp")] 12 | extern crate tokio_tcp; 13 | 14 | use http::Version; 15 | use std::net::SocketAddr; 16 | 17 | #[cfg(feature = "tcp")] 18 | mod tcp; 19 | 20 | /// Represents a HTTP aware connection. 21 | /// 22 | /// This connection is a `AsyncRead + AsyncWrite` stream that provides information 23 | /// on what http versions were determinted `ALPN` negotiation or what the remote address 24 | /// this stream is connected too. 25 | pub trait HttpConnection { 26 | /// Returns the version that this stream is set too. 27 | /// 28 | /// For `version` this indicates that this stream is accepting http frames of the version 29 | /// returned. If `None` is returned then there has been no prior negotiation for the http 30 | /// version. 31 | fn negotiated_version(&self) -> Option { 32 | None 33 | } 34 | 35 | /// Returns the remote address that this connection is connected to. 36 | fn remote_addr(&self) -> Option { 37 | None 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/tcp.rs: -------------------------------------------------------------------------------- 1 | use http::Version; 2 | use std::net::SocketAddr; 3 | use tokio_tcp::TcpStream; 4 | use HttpConnection; 5 | 6 | impl HttpConnection for TcpStream { 7 | fn negotiated_version(&self) -> Option { 8 | None 9 | } 10 | 11 | fn remote_addr(&self) -> Option { 12 | self.peer_addr().ok() 13 | } 14 | } 15 | 16 | impl HttpConnection for ::std::net::TcpStream { 17 | fn negotiated_version(&self) -> Option { 18 | None 19 | } 20 | 21 | fn remote_addr(&self) -> Option { 22 | self.peer_addr().ok() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/basic.rs: -------------------------------------------------------------------------------- 1 | extern crate http; 2 | extern crate http_connection; 3 | 4 | use http::Version; 5 | use http_connection::HttpConnection; 6 | use std::net::SocketAddr; 7 | 8 | pub struct NoValues; 9 | 10 | impl HttpConnection for NoValues {} 11 | 12 | pub struct WithVersion; 13 | 14 | impl HttpConnection for WithVersion { 15 | fn negotiated_version(&self) -> Option { 16 | Some(Version::HTTP_11) 17 | } 18 | } 19 | 20 | pub struct WithRemoteAddr; 21 | 22 | impl HttpConnection for WithRemoteAddr { 23 | fn remote_addr(&self) -> Option { 24 | Some("127.0.0.1:3000".parse().unwrap()) 25 | } 26 | } 27 | 28 | #[test] 29 | fn no_values() { 30 | let conn = NoValues; 31 | 32 | assert!(conn.negotiated_version().is_none()); 33 | assert!(conn.remote_addr().is_none()); 34 | } 35 | 36 | #[test] 37 | fn version() { 38 | let conn = WithVersion; 39 | 40 | assert_eq!(Some(Version::HTTP_11), conn.negotiated_version()); 41 | assert!(conn.remote_addr().is_none()); 42 | } 43 | 44 | #[test] 45 | fn remote_addr() { 46 | let conn = WithRemoteAddr; 47 | let addr = "127.0.0.1:3000".parse().unwrap(); 48 | 49 | assert_eq!(Some(addr), conn.remote_addr()); 50 | assert!(conn.negotiated_version().is_none()); 51 | } 52 | --------------------------------------------------------------------------------