-
Notifications
You must be signed in to change notification settings - Fork 6
fix: proper 404s + JSON profile pages #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,7 +15,7 @@ use hyper_util::rt::TokioIo; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use metrics_exporter_prometheus::PrometheusHandle; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::sync::Arc; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use tokio::net::TcpListener; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use tracing::{error, info}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use tracing::{debug, error, info}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error::Error, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -515,9 +515,12 @@ async fn serve( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let nip19 = match Nip19::from_bech32(&r.uri().path()[1..path_len - until]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(nip19) => nip19, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Err(_) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Ok(Response::builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .status(StatusCode::NOT_FOUND) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(Full::new(Bytes::from("Invalid url\n")))?); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let msg = "That doesn't look like a valid Nostr bech32 identifier."; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Ok(if is_json { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html::not_found_json(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html::not_found_response(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -581,9 +584,9 @@ async fn serve( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if is_json { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match render_data { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RenderData::Note(note_rd) => html::serve_note_json(&app.ndb, ¬e_rd), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RenderData::Profile(_profile_rd) => Ok(Response::builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .status(StatusCode::NOT_FOUND) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(Full::new(Bytes::from("todo: profile json")))?), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RenderData::Profile(profile_rd) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html::serve_profile_json(&app.ndb, profile_rd.as_ref()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match render_data { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -698,8 +701,42 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tokio::task::spawn(async move { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Finally, we bind the incoming connection to our `hello` service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Err(err) = http1::Builder::new() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // `service_fn` converts our function in a `Service` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .serve_connection(io, service_fn(|req| serve(&app_copy, req))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .serve_connection( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| io, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| service_fn(|req| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let app = &app_copy; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async move { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let wants_json = req.uri().path().ends_with(".json"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match serve(app, req).await { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(resp) => Ok::<_, std::convert::Infallible>(resp), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Err(err) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let resp = match &err { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Error::NotFound => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 404s are routine (notes that haven't | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // propagated yet, bad ids); log quietly. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| debug!("serve error (404): {}", err); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let msg = "We couldn't find that note or profile \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on the relays we checked."; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if wants_json { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html::not_found_json(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| html::not_found_response(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error!("serve error (500): {}", err); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Response::builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .status(StatusCode::INTERNAL_SERVER_ERROR) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(Full::new(Bytes::from(format!("{}\n", err)))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("building error response") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+726
to
+731
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't expose raw internal errors on Lines 726-731 return Suggested fix- _ => {
- error!("serve error (500): {}", err);
- Response::builder()
- .status(StatusCode::INTERNAL_SERVER_ERROR)
- .body(Full::new(Bytes::from(format!("{}\n", err))))
- .expect("building error response")
- }
+ _ => {
+ error!("serve error (500): {}", err);
+ if wants_json {
+ Response::builder()
+ .status(StatusCode::INTERNAL_SERVER_ERROR)
+ .header(
+ header::CONTENT_TYPE,
+ "application/json; charset=utf-8",
+ )
+ .body(Full::new(Bytes::from(
+ r#"{"error":"internal_server_error","message":"Internal server error"}"#,
+ )))
+ .expect("building error response")
+ } else {
+ Response::builder()
+ .status(StatusCode::INTERNAL_SERVER_ERROR)
+ .header(
+ header::CONTENT_TYPE,
+ "text/plain; charset=utf-8",
+ )
+ .body(Full::new(Bytes::from(
+ "Internal server error\n",
+ )))
+ .expect("building error response")
+ }
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(resp) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| println!("Error serving connection: {:?}", err); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Propagate recent-note query failures instead of returning an empty feed.
Lines 415-423 swallow
ndb.query(...)errors and still return200withrecent_notes: []. That makes a backend failure indistinguishable from a genuinely empty profile, so API clients can cache incomplete data as truth.Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents