anterofit Build Status On Crates.io

Anterofit is a collection of Rust macros coupled to a lightweight, self-contained HTTP framework that allows you to create strongly-typed Rust wrappers around REST APIs with ease.

```rust // See examples/post_service.rs for more details

[macro_use] extern crate anterofit;

extern crate rustc_serialize;

use anterofit::{Adapter, Url};

[derive(Debug, RustcDecodable)]

struct Post { pub userid: Option, pub id: u64, pub title: String, pub body: String }

service! { trait PostService { /// Get a Post by id. fn get_post(&self, id: u64) -> Post { GET("/posts/{}", id) }

    /// Get all posts.
    fn get_posts(&self) -> Vec<Post> {
        GET("/posts")
    }

    /// Create a new Post under the given user ID with the given title and body.
    fn new_post(&self, userid: u64, title: &str, body: &str) -> Post {
        POST("/posts/");
        // We use the `EAGER:` keyword so we can use borrowed values in the body.
        // This serializes the body value immediately instead of waiting to serialize
        // it on the executor.
        body_map!(EAGER:
            "userid" => userid,
            "title": title,
            "body": body
        )
    }
}

}

fn main() { // Navigate to this URL in your browser for details. Very useful test API. let url = Url::parse("https://jsonplaceholder.typicode.com").unwrap();

let adapter = Adapter::builder()
    .base_url(url)
    // When your REST API uses JSON in both requests and responses
    .serialize_json()
    .build();

create_post(&adapter);
fetch_posts(&adapter);

}

/// Create a new Post. // All service traits are implemented for Adapter by default; using generics like this promotes good namespacing. fn createpost(postservice: &P) { let post = postservice.newpost(42, "Hello", "World!") // Execute the request in the background and wait for it to complete .exec().block() .unwrap();

println!("{:?}", post);

}

/// Fetch the top 3 posts in the database. // Service traits are object-safe by default fn fetchposts(postservice: &PostService) { let posts = postservice.getposts() // Shorthand for .exec().block(), but executes the request on the current thread. .exec_here() .unwrap();

for post in posts.into_iter().take(3) {
    println!("{:?}", post);
}

} ```

Inspired by Square's Retrofit, as referenced in the name, Anterofit is even more strongly typed as everything that is feasible to check at compile-time, is. Runtime errors are, with few exceptions, reserved for error conditions that can only be discovered at runtime.

Usage

Get started with our User Guide

Or an in-depth look with our Documentation

Setup

Serde and JSON serialization:

Enabled by default with the serde-all feature.

Cargo.toml: ```toml [dependencies] anterofit = "0.1"

serde is required in the dependencies but not in the crate root.

serde = "0.9" serde_derive = "0.9" ```

Crate Root: ```rust

[macro_use] extern crate anterofit;

[macrouse] extern crate serdederive;

```

rustc-serialize:

Cargo.toml: ```toml [dependencies] rustc-serialize = "0.3"

[dependencies.anterofit] version = "0.1" default-features = false features = ["rustc-serialize"] ```

Crate Root: ```rust

[macro_use] extern crate anterofit;

extern crate rustc_serialize; ```

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.