Redirect after-pagination queries to the corresponding before-queries

This normalizes the URLs, avoiding duplicate URLs for a sublist
This commit is contained in:
Magnus Hoff 2017-10-22 13:38:13 +02:00
parent 7a63fdca0e
commit b3ffcb916b
4 changed files with 58 additions and 7 deletions

View file

@ -11,16 +11,19 @@ use state::State;
use web::{Resource, ResponseFuture}; use web::{Resource, ResponseFuture};
use super::pagination::Pagination; use super::pagination::Pagination;
use super::TemporaryRedirectResource;
const PAGE_SIZE: i32 = 30; const PAGE_SIZE: i32 = 30;
type BoxResource = Box<Resource + Sync + Send>;
pub struct ChangesResource { pub struct ChangesResource {
state: State, state: State,
before: Option<i32>, before: Option<i32>,
} }
impl ChangesResource { impl ChangesResource {
pub fn new(state: State, pagination: Pagination<i32>) -> Box<Future<Item=ChangesResource, Error=::web::Error>> { pub fn new(state: State, pagination: Pagination<i32>) -> Box<Future<Item=BoxResource, Error=::web::Error>> {
match pagination { match pagination {
Pagination::After(x) => Box::new( Pagination::After(x) => Box::new(
state.query_article_revision_stubs(move |query| { state.query_article_revision_stubs(move |query| {
@ -38,14 +41,14 @@ impl ChangesResource {
None None
}; };
Ok(Self { Ok(match extra_element {
state, Some(x) => Box::new(TemporaryRedirectResource::new(format!("?before={}", x.sequence_number))) as BoxResource,
before: extra_element.map(|x| x.sequence_number), None => Box::new(TemporaryRedirectResource::new(format!("_changes"))) as BoxResource,
}) })
}) })
), ),
Pagination::Before(x) => Box::new(finished(Self { state, before: Some(x) })), Pagination::Before(x) => Box::new(finished(Box::new(Self { state, before: Some(x) }) as BoxResource)),
Pagination::None => Box::new(finished(Self { state, before: None })), Pagination::None => Box::new(finished(Box::new(Self { state, before: None }) as BoxResource)),
} }
} }
} }

View file

@ -5,9 +5,11 @@ mod article_resource;
mod changes_resource; mod changes_resource;
mod new_article_resource; mod new_article_resource;
mod sitemap_resource; mod sitemap_resource;
mod temporary_redirect_resource;
pub use self::article_redirect_resource::ArticleRedirectResource; pub use self::article_redirect_resource::ArticleRedirectResource;
pub use self::article_resource::ArticleResource; pub use self::article_resource::ArticleResource;
pub use self::changes_resource::ChangesResource; pub use self::changes_resource::ChangesResource;
pub use self::new_article_resource::NewArticleResource; pub use self::new_article_resource::NewArticleResource;
pub use self::sitemap_resource::SitemapResource; pub use self::sitemap_resource::SitemapResource;
pub use self::temporary_redirect_resource::TemporaryRedirectResource;

View file

@ -0,0 +1,46 @@
use futures::{self, Future};
use hyper;
use hyper::header::Location;
use hyper::server::*;
use web::{Resource, ResponseFuture};
pub struct TemporaryRedirectResource {
location: String,
}
impl TemporaryRedirectResource {
pub fn new(location: String) -> Self {
Self { location }
}
}
impl Resource for TemporaryRedirectResource {
fn allow(&self) -> Vec<hyper::Method> {
use hyper::Method::*;
vec![Options, Head, Get, Put, Post]
}
fn head(&self) -> ResponseFuture {
Box::new(futures::finished(Response::new()
.with_status(hyper::StatusCode::TemporaryRedirect)
.with_header(Location::new(self.location.clone()))
))
}
fn get(self: Box<Self>) -> ResponseFuture {
Box::new(self.head()
.and_then(move |head| {
Ok(head
.with_body(format!("Moved to {}", self.location)))
}))
}
fn put(self: Box<Self>, _body: hyper::Body, _identity: Option<String>) -> ResponseFuture {
Box::new(self.head()
.and_then(move |head| {
Ok(head
.with_body(format!("Moved to {}", self.location)))
}))
}
}

View file

@ -87,7 +87,7 @@ impl WikiLookup {
Box::new( Box::new(
done(pagination::from_str(query.unwrap_or("")).map_err(Into::into)) done(pagination::from_str(query.unwrap_or("")).map_err(Into::into))
.and_then(move |pagination| ChangesResource::new(state, pagination)) .and_then(move |pagination| ChangesResource::new(state, pagination))
.and_then(|changes_resource| Ok(Some(Box::new(changes_resource) as BoxResource))) .and_then(|resource| Ok(Some(resource)))
) )
}, },
("_new", None) => ("_new", None) =>