Repository: tower-rs/tower
Pull request #25 (2017-11-02 18:24:53)

Add a `ReadyService` trait
This PR adds a `ReadyService` trait. A `ReadyService` is similar to `Service` except that it is always "ready" to accept a request. A `ReadyService` implementation can immediately error the response if it is "at capacity", but it has no strategy by which to notify the caller that it becomes ready again.

It is expected that types will usually implement either `Service` OR `ReadyService` (though, there may be cases in which a type can implement both). It is also expected that server implementations will only accept `Service` values.

## Adapting

### `ReadyService` -> `Service`

In order to adapt a `ReadyService` to a `Service`, I can think of a couple strategies off the top of my head.

#### Don't do anything special.

In this case, there will be some type `AdaptReadyService` (naming TBD) that takes a `ReadyService` and implements `Service` such that `poll_ready` always returns `Ready`. This requires the user to make an explicit step to say that the server will not have any mechanism to handle back pressure.

#### Add a limiter

In this case, a `ReadyService` value is passed to `Limit::new(my_ready_service, n)`. This type ensures that there are only `n` in-flight requests. This limiter can be scoped to the connection (`n` in-flight requests per connection) or per "app" so that the number of in-flight requests are limited across many connections.

### `Service` -> `ReadyService`

There are reasons to want to adapt the other direction as well. For example a router (a single service that routes a request to one of many possible inner services) cannot easily provide a back pressure strategy. In this case, a router would want to be initialized with a set of `ReadyService` values.

To adapt a `ReadyService` to `Service`, the primary strategy would be to add a buffering layer. This buffer would ideally have an upper limit. When the upper limit is reached, the buffer starts erroring requests immediately.

## Higher level frameworks

Obviously, introducing a new trait adds non trivial complexity. That said, I would expect that `ReadyService` would provide a better suited trait for reducing initial friction. I would not necessarily expect frameworks to ask their users to implement `ReadyService`, but frameworks could use this trait internally and build up a tower stack using `Router`, `Limit`, `Buffer`, etc... and eventually provide a `Service` representing the entire stack and pass that to a server.

## Alternatives

There are two alternatives to introducing `ReadyService`.

### Keep things as is.

In this case, a "ready service" would be a type that implements `Service` such that `poll_ready` always returns `Ready`. The service would need to document that `poll_ready` does not need to be called before `call` (as there are some services that *require* `poll_ready` to return `Ready` before calling `call`).

The router type would accept a set of `Service` values, documenting that these must be "ready service" values and as such `poll_ready` will *not* be called. This means, if a service that requires` poll_ready` to be called is passed, it would just hang (for example, `Reconnect`).

### Remove `poll_ready` from `Service`.

If `ReadyService` is needed, is `poll_ready` actually helpful? I would say *yes* as *most* middleware implementations so far heavily rely on `poll_ready` to do the "right thing". The only middleware that I have written that requires a "ready service" is the router.


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index b94dab8..377aedf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,7 +2,7 @@
 
 name = "tower"
 version = "0.1.0"
-license = "MIT/Apache-2.0"
+license = "MIT"
 authors = ["Carl Lerche <me@carllerche.com>"]
 description = """
 An extensible request / response system, used to construct high-concurrency
@@ -10,9 +10,10 @@ servers and clients.
 """
 
 documentation = "https://docs.rs/tower"
-homepage = "https://tower.rs"
+homepage = "https://github.com/tower-rs/tower"
 repository = "https://github.com/tower-rs/tower"
 readme = "README.md"
+publish = false
 
 [workspace]
 
@@ -25,7 +26,7 @@ members = [
   "tower-mock",
   "tower-rate-limit",
   "tower-reconnect",
-  "tower-route",
+  "tower-router",
   "tower-timeout",
   "tower-util",
 ]
diff --git a/LICENSE-MIT b/LICENSE
similarity index 100%
rename from LICENSE-MIT
rename to LICENSE
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
deleted file mode 100644
index 87d73e7..0000000
--- a/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright 2017 Carl Lerche
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/README.md b/README.md
index 9dc9ef8..312aa40 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,9 @@
 
 fn(Request) -> Future<Response>
 
-[![Build Status](https://travis-ci.org/carllerche/tower.svg?branch=master)](https://travis-ci.org/carllerche/tower)
+This is not ready for usage yet (unless you are brave).
+
+[![Build Status](https://travis-ci.org/tower-rs/tower.svg?branch=master)](https://travis-ci.org/tower-rs/tower)
 
 ## Usage
 
@@ -18,15 +20,3 @@ Next, add this to your crate:
 ```rust
 extern crate tower;
 ```
-
-You can find extensive examples and tutorials in addition to the [API
-documentation](https://docs.rs/tower) at
-[https://tower.rs](https://tower.rs)
-
-# License
-
-`tower` is primarily distributed under the terms of both the MIT
-license and the Apache License (Version 2.0), with portions covered by various
-BSD-like licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/src/lib.rs b/src/lib.rs
index f1a9b12..52a600d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -197,6 +197,47 @@ pub trait Service {
     fn call(&mut self, req: Self::Request) -> Self::Future;
 }
 
+/// An asynchronous function from `Request` to a `Response` that is always ready
+/// to process a request.
+///
+/// `ReadyService` is similar to `Service`, except that it is always able to
+/// accept a request. This request may either complete successfully or resolve
+/// to an error, i.e., `ReadyService` implementations may handle out of capacity
+/// situations by returning a response future that immediately resolves to an
+/// error.
+///
+/// The `Service` trait should be prefered over this one. `ReadyService` should
+/// only be used in situations where there is no way to handle back pressure.
+/// When usin a `ReadyService` implementation, back pressure needs to be handled
+/// via some other strategy, such as limiting the total number of in flight
+/// requests.
+///
+/// One situation in which there is no way to handle back pressure is routing.
+/// A router service receives inbound requests and dispatches them to one of N
+/// inner services. In this case, one of the inner services may become "not
+/// ready" while the others remain ready. It would not be ideal for the router
+/// service to flag itself as "not ready" when only one of the inner services is
+/// not ready, but there is no way for the router to communicate to the caller
+/// which requests will be accepted and which will be rejected. The router
+/// service will implement `ReadyService`, indicating to the user that they are
+/// responsible for handling back pressure via some other strategy.
+pub trait ReadyService {
+    /// Requests handled by the service.
+    type Request;
+
+    /// Responses returned by the service.
+    type Response;
+
+    /// Errors produced by the service.
+    type Error;
+
+    /// The future response value.
+    type Future: Future<Item = Self::Response, Error = Self::Error>;
+
+    /// Process the request and return the response asynchronously.
+    fn call(&mut self, req: Self::Request) -> Self::Future;
+}
+
 /// Future yielding a `Service` once the service is ready to process a request
 pub struct Ready<T> {
     inner: Option<T>,
diff --git a/tower-balance/Cargo.toml b/tower-balance/Cargo.toml
index 2ac8110..a858a76 100644
--- a/tower-balance/Cargo.toml
+++ b/tower-balance/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-balance"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-balance/README.md b/tower-balance/README.md
index 9b715fa..521e709 100644
--- a/tower-balance/README.md
+++ b/tower-balance/README.md
@@ -1,12 +1,3 @@
 Tower Balance
 
 A Tower middleware that load balances across a uniform set of services.
-
-# License
-
-`tower-timeout` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
-
diff --git a/tower-balance/src/lib.rs b/tower-balance/src/lib.rs
index b33e307..4ac991b 100644
--- a/tower-balance/src/lib.rs
+++ b/tower-balance/src/lib.rs
@@ -19,6 +19,7 @@ where T: Discover,
 }
 
 /// Error produced by `Balance`
+#[derive(Debug)]
 pub enum Error<T, U> {
     Inner(T),
     Balance(U),
diff --git a/tower-buffer/Cargo.toml b/tower-buffer/Cargo.toml
index cc26573..c9c4735 100644
--- a/tower-buffer/Cargo.toml
+++ b/tower-buffer/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-buffer"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-buffer/README.md b/tower-buffer/README.md
index 230ba87..c060013 100644
--- a/tower-buffer/README.md
+++ b/tower-buffer/README.md
@@ -1,11 +1,3 @@
 # Tower Buffer
 
 Tower middleware providing a buffering layer in front of an inner `Service`.
-
-# License
-
-`tower-buffer` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-buffer/src/lib.rs b/tower-buffer/src/lib.rs
index 674b0eb..9e2ab20 100644
--- a/tower-buffer/src/lib.rs
+++ b/tower-buffer/src/lib.rs
@@ -41,6 +41,7 @@ where T: Service,
 }
 
 /// Errors produced by `Buffer`.
+#[derive(Debug)]
 pub enum Error<T> {
     Inner(T),
     Closed,
diff --git a/tower-discover/Cargo.toml b/tower-discover/Cargo.toml
index 9164a41..cf6cc0f 100644
--- a/tower-discover/Cargo.toml
+++ b/tower-discover/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-discover"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-discover/README.md b/tower-discover/README.md
index 3e9d1a9..000719f 100644
--- a/tower-discover/README.md
+++ b/tower-discover/README.md
@@ -1,11 +1,3 @@
 Tower Discovery
 
 Abstracts over service discovery strategies.
-
-# License
-
-`tower-discover` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-filter/Cargo.toml b/tower-filter/Cargo.toml
index b71ef2c..96b9a58 100644
--- a/tower-filter/Cargo.toml
+++ b/tower-filter/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-filter"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-filter/README.md b/tower-filter/README.md
index 3e71106..dc17a5b 100644
--- a/tower-filter/README.md
+++ b/tower-filter/README.md
@@ -2,11 +2,3 @@ Tower Filter
 
 A Tower middleware that conditionally allows requests to be dispatched to the
 inner service based on the result of a predicate.
-
-# License
-
-`tower-filter` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-mock/Cargo.toml b/tower-mock/Cargo.toml
index 25d8103..aa4a8a5 100644
--- a/tower-mock/Cargo.toml
+++ b/tower-mock/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-mock"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-mock/README.md b/tower-mock/README.md
index 11ce833..0a84b0e 100644
--- a/tower-mock/README.md
+++ b/tower-mock/README.md
@@ -1,11 +1,3 @@
 Tower Mock
 
 A mock `Service` that can be used to test middleware or clients.
-
-# License
-
-`tower-mock` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-rate-limit/Cargo.toml b/tower-rate-limit/Cargo.toml
index 35a9112..b94687f 100644
--- a/tower-rate-limit/Cargo.toml
+++ b/tower-rate-limit/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-rate-limit"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-rate-limit/README.md b/tower-rate-limit/README.md
index 2a85f5f..b469075 100644
--- a/tower-rate-limit/README.md
+++ b/tower-rate-limit/README.md
@@ -2,12 +2,3 @@ Tower Rate Limit
 
 A Tower middleware that rate limits the requests that are passed to the inner
 service.
-
-# License
-
-`tower-rate-limit` is primarily distributed under the terms of both the MIT
-license and the Apache License (Version 2.0), with portions covered by various
-BSD-like licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
-
diff --git a/tower-reconnect/Cargo.toml b/tower-reconnect/Cargo.toml
index 98738c0..e4c7f7a 100644
--- a/tower-reconnect/Cargo.toml
+++ b/tower-reconnect/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-reconnect"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-reconnect/README.md b/tower-reconnect/README.md
index 11cf174..ad5f805 100644
--- a/tower-reconnect/README.md
+++ b/tower-reconnect/README.md
@@ -2,11 +2,3 @@ Tower Reconnect
 
 A Tower middleware that automatically recreates an inner service when an error
 is encountered.
-
-# License
-
-`tower-timeout` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-route/README.md b/tower-route/README.md
deleted file mode 100644
index 0901ab3..0000000
--- a/tower-route/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-Tower Route
-
-A Tower middleware that routes requests to one of a set of inner services using
-a request predicate.
-
-# License
-
-`tower-route` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-route/Cargo.toml b/tower-router/Cargo.toml
similarity index 89%
rename from tower-route/Cargo.toml
rename to tower-router/Cargo.toml
index c04de5e..b367b1f 100644
--- a/tower-route/Cargo.toml
+++ b/tower-router/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "tower-route"
+name = "tower-router"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-router/README.md b/tower-router/README.md
new file mode 100644
index 0000000..5a3877d
--- /dev/null
+++ b/tower-router/README.md
@@ -0,0 +1,4 @@
+Tower Router
+
+A Tower middleware that routes requests to one of a set of inner services using
+a request predicate.
diff --git a/tower-route/src/lib.rs b/tower-router/src/lib.rs
similarity index 96%
rename from tower-route/src/lib.rs
rename to tower-router/src/lib.rs
index 77fd899..1727c40 100644
--- a/tower-route/src/lib.rs
+++ b/tower-router/src/lib.rs
@@ -16,7 +16,7 @@ use std::mem;
 use self::ResponseState::*;
 
 /// Routes requests to an inner service based on the request.
-pub struct Route<T> {
+pub struct Router<T> {
     recognize: Borrow<T>,
 }
 
@@ -60,7 +60,7 @@ where T: Recognize,
     state: ResponseState<T>,
 }
 
-/// Error produced by the `Route` service
+/// Error produced by the `Router` service
 ///
 /// TODO: Make variants priv
 #[derive(Debug)]
@@ -88,18 +88,18 @@ where T: Recognize
     Invalid,
 }
 
-// ===== impl Route =====
+// ===== impl Router =====
 
-impl<T> Route<T>
+impl<T> Router<T>
 where T: Recognize
 {
     /// Create a new router
     pub fn new(recognize: T) -> Self {
-        Route { recognize: Borrow::new(recognize) }
+        Router { recognize: Borrow::new(recognize) }
     }
 }
 
-impl<T> Service for Route<T>
+impl<T> Service for Router<T>
 where T: Recognize,
 {
     type Request = T::Request;
diff --git a/tower-timeout/Cargo.toml b/tower-timeout/Cargo.toml
index a06472f..4bc6f86 100644
--- a/tower-timeout/Cargo.toml
+++ b/tower-timeout/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-timeout"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-timeout/README.md b/tower-timeout/README.md
index 916b10a..28207f6 100644
--- a/tower-timeout/README.md
+++ b/tower-timeout/README.md
@@ -1,11 +1,3 @@
 Tower Timeout
 
 A Tower middleware that applies a timeout to requests.
-
-# License
-
-`tower-timeout` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-util/Cargo.toml b/tower-util/Cargo.toml
index 59f242b..801a3ed 100644
--- a/tower-util/Cargo.toml
+++ b/tower-util/Cargo.toml
@@ -2,6 +2,7 @@
 name = "tower-util"
 version = "0.1.0"
 authors = ["Carl Lerche <me@carllerche.com>"]
+publish = false
 
 [dependencies]
 futures = "0.1"
diff --git a/tower-util/README.md b/tower-util/README.md
index 4be46b8..1ec10e6 100644
--- a/tower-util/README.md
+++ b/tower-util/README.md
@@ -3,11 +3,3 @@
 Additional, generally useful, utilities for working with Tower. Contents from
 this crate may eventually be moved into `tower` proper. They are kept here until
 they prove their utility.
-
-# License
-
-`tower-timeout` is primarily distributed under the terms of both the MIT license
-and the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
-
-See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/tower-util/src/option.rs b/tower-util/src/option.rs
index abb6f55..d4a0e04 100644
--- a/tower-util/src/option.rs
+++ b/tower-util/src/option.rs
@@ -18,6 +18,7 @@ pub struct ResponseFuture<T> {
 }
 
 /// Error produced by `OptionService` responding to a request.
+#[derive(Debug)]
 pub enum Error<T> {
     Inner(T),
     None,


Test patch:
diff --git a/tower-route/tests/route.rs b/tower-router/tests/router.rs
similarity index 95%
rename from tower-route/tests/route.rs
rename to tower-router/tests/router.rs
index 542fe7e..d88dbec 100644
--- a/tower-route/tests/route.rs
+++ b/tower-router/tests/router.rs
@@ -1,10 +1,10 @@
 extern crate futures;
 extern crate futures_test;
 extern crate tower;
-extern crate tower_route;
+extern crate tower_router;
 
 use tower::Service;
-use tower_route::*;
+use tower_router::*;
 
 use futures::*;
 use futures::future::FutureResult;
@@ -34,7 +34,7 @@ fn basic_routing() {
     recognize.map.insert("one".into(), StringService::ok("hello"));
     recognize.map.insert("two".into(), StringService::ok("world"));
 
-    let mut service = Route::new(recognize);
+    let mut service = Router::new(recognize);
 
     // Router is ready by default
     assert_ready!(&mut service);
@@ -61,7 +61,7 @@ fn inner_service_err() {
     recognize.map.insert("one".into(), StringService::ok("hello"));
     recognize.map.insert("two".into(), StringService::err());
 
-    let mut service = Route::new(recognize);
+    let mut service = Router::new(recognize);
 
     let resp = service.call("two".into());
     assert!(resp.wait().is_err());
@@ -78,7 +78,7 @@ fn inner_service_not_ready() {
     recognize.map.insert("one".into(), MaybeService::new("hello"));
     recognize.map.insert("two".into(), MaybeService::none());
 
-    let mut service = Route::new(recognize);
+    let mut service = Router::new(recognize);
 
     let resp = service.call("two".into());
     let mut resp = Harness::new(resp);