blob: dece12334c3f23800680aa18ce50e87bdafb7e9d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
//! Filters which can preprocess or postprocess request.
//!
//! TODO: Add the `ClusterFilter` according to the name.
//!
//! # Example
//! ## ClusterFilter
//! ```no_run
//! const USER_AGENT: &str = "user-agent";
//! const USER_AGENT_VAL: &str = "dubbo-test";
//! const USER_AGENT_VAL_2: &str = "dubbo-test-2";
//!
//! #[derive(Clone, Copy)]
//! struct MyFilter;
//!
//! impl ClusterFilter for MyFilter1 {
//! fn call(&mut self, req: Request<()>) -> Result<Request<()>, crate::status::Status> {
//! req.metadata_mut().get_mut().insert(
//! USER_AGENT.to_string(),
//! USER_AGENT_VAL.to_string(),
//! );
//! Ok::<_, Status>(req)
//! }
//! }
//!
//! impl ClusterFilter for MyFilter2 {
//! fn call(&mut self, req: Request<()>) -> Result<Request<()>, crate::status::Status> {
//! assert_eq!(
//! req.metadata()
//! .get_ref()
//! .get(USER_AGENT)
//! .expect("missing user-agent."),
//! USER_AGENT_VAL
//! );
//! req.metadata_mut().get_mut().insert(
//! USER_AGENT.to_string(),
//! USER_AGENT_VAL_2.to_string(),
//! );
//! Ok::<_, Status>(req)
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let svc = service_fn(|req: http::Request<BoxBody>| async move {
//! assert_eq!(
//! req.headers().get(USER_AGENT).map(|v| v.to_str().unwrap()),
//! Some(USER_AGENT_VAL_2)
//! );
//! Ok::<_, Status>(http::Response::new(empty_body()))
//! });
//! let svc = ServiceBuilder::new()
//! .layer(cluster_filter(MyFilter1))
//! .layer(cluster_filter(MyFilter2))
//! .service(svc);
//! let req = http::Request::builder()
//! .body(empty_body())
//! .unwrap();
//! svc.oneshot(req).await.unwrap();
//! }
//! ```
use crate::invocation::Request;
pub mod clusterfilter;
pub mod service;
/// TODO: Implement it.
pub trait Filter {
fn call(&mut self, req: Request<()>) -> Result<Request<()>, crate::status::Status>;
}
/// The `ClusterFilter` can **preprocess** the HTTP Request and then pass the result to the inner
/// [`Service`].
/// `ClusterFilter` is implemented as a tower's [`Layer`], which can let us take full advantage of the
/// other `Layer` provided by [`tower-http`].
///
/// [`tower-http`]: https://docs.rs/tower-http/latest/tower_http/
/// [`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
/// [`Layer`]: https://docs.rs/tower/latest/tower/trait.Layer.html
pub trait ClusterFilter {
fn call(&mut self, req: Request<()>) -> Result<Request<()>, crate::status::Status>;
}