diff --git a/src/index.rs b/src/index.rs
index c077a8ba4c..837a27d129 100644
--- a/src/index.rs
+++ b/src/index.rs
@@ -251,7 +251,7 @@ impl Index {
let height_to_hash = rtx.0.open_table(HEIGHT_TO_HASH)?;
let mut cursor = height_to_hash
- .range(height.saturating_sub(take)..=height)?
+ .range(height.saturating_sub(take.saturating_sub(1))..=height)?
.rev();
while let Some(next) = cursor.next() {
diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs
index 96c10679b0..786dfb6ec3 100644
--- a/src/subcommand/server.rs
+++ b/src/subcommand/server.rs
@@ -4,7 +4,7 @@ use {
self::{
deserialize_ordinal_from_str::DeserializeOrdinalFromStr,
templates::{
- block::BlockHtml, ordinal::OrdinalHtml, output::OutputHtml, root::RootHtml,
+ block::BlockHtml, ordinal::OrdinalHtml, output::OutputHtml, range::RangeHtml, root::RootHtml,
transaction::TransactionHtml, Content,
},
tls_acceptor::TlsAcceptor,
@@ -16,6 +16,7 @@ use {
AcmeConfig,
},
serde::{de, Deserializer},
+ std::cmp::Ordering,
tokio_stream::StreamExt,
};
@@ -203,21 +204,15 @@ impl Server {
(DeserializeOrdinalFromStr, DeserializeOrdinalFromStr),
>,
) -> impl IntoResponse {
- if start == end {
- return (StatusCode::BAD_REQUEST, Html("Empty Range".to_string()));
- }
-
- if start > end {
- return (
+ match start.cmp(&end) {
+ Ordering::Equal => (StatusCode::BAD_REQUEST, Html("Empty Range".to_string())).into_response(),
+ Ordering::Greater => (
StatusCode::BAD_REQUEST,
Html("Range Start Greater Than Range End".to_string()),
- );
+ )
+ .into_response(),
+ Ordering::Less => RangeHtml { start, end }.page().into_response(),
}
-
- (
- StatusCode::OK,
- Html(format!("first")),
- )
}
async fn root(index: extract::Extension>) -> impl IntoResponse {
diff --git a/src/subcommand/server/templates.rs b/src/subcommand/server/templates.rs
index 3163726964..a5f76222b6 100644
--- a/src/subcommand/server/templates.rs
+++ b/src/subcommand/server/templates.rs
@@ -3,6 +3,7 @@ use {super::*, boilerplate::Display};
pub(crate) mod block;
pub(crate) mod ordinal;
pub(crate) mod output;
+pub(crate) mod range;
pub(crate) mod root;
pub(crate) mod transaction;
diff --git a/src/subcommand/server/templates/range.rs b/src/subcommand/server/templates/range.rs
new file mode 100644
index 0000000000..96a4715435
--- /dev/null
+++ b/src/subcommand/server/templates/range.rs
@@ -0,0 +1,62 @@
+use super::*;
+
+#[derive(Display)]
+pub(crate) struct RangeHtml {
+ pub(crate) start: Ordinal,
+ pub(crate) end: Ordinal,
+}
+
+impl Content for RangeHtml {
+ fn title(&self) -> String {
+ format!("Ordinal range [{},{})", self.start, self.end)
+ }
+
+ fn page(self) -> PageHtml {
+ PageHtml {
+ content: Box::new(self),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use {super::*, pretty_assertions::assert_eq, unindent::Unindent};
+
+ #[test]
+ fn ordinal_html() {
+ assert_eq!(
+ RangeHtml {
+ start: Ordinal(0),
+ end: Ordinal(1),
+ }
+ .to_string(),
+ "
+ Ordinal range [0,1)
+
+ - size
- 1
+ - first
- 0
+
+ "
+ .unindent()
+ );
+ }
+
+ #[test]
+ fn bugfix_broken_link() {
+ assert_eq!(
+ RangeHtml {
+ start: Ordinal(1),
+ end: Ordinal(10),
+ }
+ .to_string(),
+ "
+ Ordinal range [1,10)
+
+ - size
- 9
+ - first
- 1
+
+ "
+ .unindent()
+ );
+ }
+}
diff --git a/templates/range.html b/templates/range.html
new file mode 100644
index 0000000000..ada1a58ca6
--- /dev/null
+++ b/templates/range.html
@@ -0,0 +1,5 @@
+Ordinal range [{{self.start}},{{self.end}})
+
+ - size
- {{self.end.n() - self.start.n()}}
+ - first
- {{self.start.n()}}
+
diff --git a/tests/server.rs b/tests/server.rs
index d5354f8537..9b4089f8ab 100644
--- a/tests/server.rs
+++ b/tests/server.rs
@@ -62,8 +62,16 @@ fn empty_range_returns_400() {
}
#[test]
-fn range_links_to_first() {
- State::new().request("range/0/1", 200, "first");
+fn range() {
+ State::new().request_regex(
+ "range/0/1",
+ 200,
+ r".*Ordinal range \[0,1\).*Ordinal range \[0,1\)
+
+ - size
- 1
+ - first
- 0
+
.*",
+ );
}
#[test]
@@ -162,7 +170,7 @@ fn root_block_limit() {
state.request_regex(
"/",
200,
- ".*.*"
+ ".*.*"
);
}