Skip to content

Commit

Permalink
rework landing docs
Browse files Browse the repository at this point in the history
  • Loading branch information
yoshuawuyts committed Sep 27, 2020
1 parent 7a5ac3e commit 3c7f429
Showing 1 changed file with 30 additions and 171 deletions.
201 changes: 30 additions & 171 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
//! # Serve the web
//!
//! Tide is a friendly HTTP server built for casual Rustaceans and veterans alike. It's completely
//! modular, and built directly for `async/await`. Whether it's a quick webhook, or an L7 load
//! balancer, Tide will make it work.
//!
//! # Features
//!
//! - __Fast:__ Written in Rust, and built on Futures, Tide is incredibly efficient.
//! - __Friendly:__ With thorough documentation, and a complete API, Tide helps cover your every
//! need.
//! - __Minimal:__ With only a few concepts to learn, Tide is easy to pick up and become productive
//! with.
//! Tide is a minimal and pragmatic Rust web application framework built for
//! rapid development. It comes with a robust set of features that make
//! building database-backed web applications easier and more fun.
//!
//! # Getting started
//!
//! Add two dependencies to your project's `Cargo.toml` file: `tide` itself, and `async-std` with the feature `attributes` enabled:
//! In order to build a web app in Rust you need an HTTP server, and an async
//! runtime. After running `cargo init` add the following lines to your
//! `Cargo.toml` file:
//!
//! ```toml
//! # Example, use the version numbers you need
//! tide = "0.7.0"
Expand All @@ -23,175 +16,41 @@
//!
//! # Examples
//!
//! __hello world__
//! ```no_run
//! # use async_std::task::block_on;
//! # fn main() -> Result<(), std::io::Error> { block_on(async {
//! #
//! let mut app = tide::new();
//! app.at("/").get(|_| async { Ok("Hello, world!") });
//! app.listen("127.0.0.1:8080").await?;
//! #
//! # Ok(()) }) }
//! ```
//! Create an HTTP server that takes JSON, validates it, and responds with a
//! confirmation message.
//!
//! __echo server__
//! ```no_run
//! # use async_std::task::block_on;
//! # fn main() -> Result<(), std::io::Error> { block_on(async {
//! #
//! let mut app = tide::new();
//! app.at("/").get(|req| async { Ok(req) });
//! app.listen("127.0.0.1:8080").await?;
//! #
//! # Ok(()) }) }
//! ````
//!
//! __send and receive json__
//! ```no_run
//! # use async_std::task::block_on;
//! # fn main() -> Result<(), std::io::Error> { block_on(async {
//! # use tide::{Body, Request, Response};
//! #
//! #[derive(Debug, serde::Deserialize, serde::Serialize)]
//! struct Counter { count: usize }
//!
//! let mut app = tide::new();
//! app.at("/").get(|mut req: Request<()>| async move {
//! let mut counter: Counter = req.body_json().await?;
//! println!("count is {}", counter.count);
//! counter.count += 1;
//! let mut res = Response::new(200);
//! res.set_body(Body::from_json(&counter)?);
//! Ok(res)
//! });
//! app.listen("127.0.0.1:8080").await?;
//! #
//! # Ok(()) }) }
//! ```
//! use tide::Request;
//! use tide::prelude::*;
//!
//! # Concepts
//!
//! ## Request-Response
//!
//! Each Tide endpoint takes a [`Request`] and returns a [`Response`]. Because async functions
//! allow us to wait without blocking, this makes Tide feel similar to synchronous servers. Except
//! it's incredibly efficient.
//!
//! ```txt
//! async fn endpoint(req: Request) -> Result;
//! ```
//!
//! ## Middleware
//!
//! Middleware wrap each request and response pair, allowing code to be run before the endpoint,
//! and after each endpoint. Additionally each handler can choose to never yield to the endpoint
//! and abort early. This is useful for e.g. authentication middleware. Tide's middleware works
//! like a stack. A simplified example of the logger middleware is something like this:
//!
//! ```ignore
//! async fn log(req: Request, next: Next) -> tide::Result {
//! println!("Incoming request from {} on url {}", req.peer_addr(), req.url());
//! let res = next().await?;
//! println!("Outgoing response with status {}", res.status());
//! res
//! #[derive(Debug, Deserialize)]
//! struct Animal {
//! name: String,
//! legs: u8,
//! }
//! ```
//!
//! As a new request comes in, we perform some logic. Then we yield to the next
//! middleware (or endpoint, we don't know when we yield to `next`), and once that's
//! done, we return the Response. We can decide to not yield to `next` at any stage,
//! and abort early. This can then be used in applications using the [`Server::middleware`]
//! method.
//!
//! ## State
//!
//! Middleware often needs to share values with the endpoint. This is done through "request scoped
//! state". Request scoped state is built using a typemap that's available through
//! [`Request::ext`].
//!
//! If the endpoint needs to share values with middleware, response scoped state can be set via
//! [`Response::insert_ext`] and is available through [`Response::ext`].
//!
//! Application scoped state is used when a complete application needs access to a particular
//! value. Examples of this include: database connections, websocket connections, or
//! network-enabled config. Every `Request<State>` has an inner value that must
//! implement `Send + Sync + Clone`, and can thus freely be shared between requests.
//!
//! By default `tide::new` will use `()` as the shared state. But if you want to
//! create a new app with shared state you can use the [`with_state`] function.
//!
//! ## Extension Traits
//!
//! Sometimes having application and request scoped context can require a bit of setup. There are
//! cases where it'd be nice if things were a little easier. This is why Tide
//! encourages people to write _extension traits_.
//!
//! By using an _extension trait_ you can extend [`Request`] or [`Response`] with more
//! functionality. For example, an authentication package could implement a `user` method on
//! `Request`, to access the authenticated user provided by middleware.
//!
//! Extension traits are written by defining a trait + trait impl for the struct that's being
//! extended:
//!
//! ```no_run
//! # use tide::Request;
//! #
//! pub trait RequestExt {
//! fn bark(&self) -> String;
//! }
//!
//! impl<State> RequestExt for Request<State> {
//! fn bark(&self) -> String {
//! "woof".to_string()
//! }
//! }
//! ```
//!
//! Tide apps will then have access to the `bark` method on `Request`:
//!
//! ```no_run
//! # use tide::Request;
//! #
//! # pub trait RequestExt {
//! # fn bark(&self) -> String;
//! # }
//! #
//! # impl<State> RequestExt for Request<State> {
//! # fn bark(&self) -> String {
//! # "woof".to_string()
//! # }
//! # }
//! #
//! #[async_std::main]
//! async fn main() -> Result<(), std::io::Error> {
//! async fn main() -> tide::Result<()> {
//! let mut app = tide::new();
//! app.at("/").get(|req: Request<()>| async move { Ok(req.bark()) });
//! app.listen("127.0.0.1:8080").await
//! app.at("/orders/shoes").post(order_shoes);
//! app.listen("127.0.0.1:8080").await?;
//! Ok(())
//! }
//! ```
//!
//! # HTTP Version 1.1 only
//! async fn order_shoes(req: Request<()>) -> tide::Result {
//! let Animal { name, legs } = req.body_json().await?;
//! Ok(format!("Hello, {}! I've put in an order for {} shoes", name, legs))
//! }
//! ````
//!
//! Tide's default backend currently only supports HTTP/1.1. In order
//! to use nginx as reverse proxy for Tide, your upstream proxy
//! configuration must include this line:
//! ```sh
//! $ curl localhost:8000/orders/shoes -d '{ "name": "Chashu", "legs": 4 }'
//! Hello, Chashu! I've put in an order for 4 shoes
//!
//! ```text
//! proxy_http_version 1.1;
//! $ curl localhost:8000/orders/shoes -d '{ "name": "Mary Millipede", "legs": 750 }'
//! number too large to fit in target type
//! ```
//!
//! # API Stability
//!
//! It's still early in Tide's development cycle. While the general shape of Tide might have
//! roughly established, the exact traits and function parameters may change between versions. In
//! practice this means that building your core business on Tide is probably not a wise idea...
//! yet.
//!
//! However we *are* committed to closely following semver, and documenting any and all breaking
//! changes we make. Also as time goes on you may find that fewer and fewer changes occur, until we
//! eventually remove this notice entirely. The goal of Tide is to build a premier HTTP experience
//! for Async Rust. We have a long journey ahead of us. But we're excited you're here with us!
//! See more examples in the [examples](https://github.com/http-rs/tide/tree/main/examples) directory.
#![cfg_attr(feature = "docs", feature(doc_cfg))]
// #![warn(missing_docs)]
Expand Down

0 comments on commit 3c7f429

Please sign in to comment.