The backend of a gist server written in Rust
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

routes.rs 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. use diesel::result::Error;
  2. use rocket::http::Status;
  3. use rocket::request::Request;
  4. use rocket::response::status;
  5. use rocket_contrib::json::Json;
  6. use rocket_contrib::templates::Template;
  7. use std::collections::HashMap;
  8. use crate::connection::DbConn;
  9. use crate::snippet;
  10. use crate::snippet::{ApiSnippet, Snippet};
  11. fn error_response(error: Error) -> Status {
  12. match error {
  13. Error::NotFound => Status::NotFound,
  14. _ => Status::InternalServerError,
  15. }
  16. }
  17. #[get("/")]
  18. pub fn index() -> Template {
  19. let context: HashMap<&str, String> = HashMap::new();
  20. Template::render("index", &context)
  21. }
  22. #[derive(Serialize, Deserialize)]
  23. struct Context {
  24. snippet: Snippet,
  25. lines: Vec<String>,
  26. }
  27. #[get("/snippets/<uuid>")]
  28. pub fn show_snippet(uuid: String, connection: DbConn) -> Template {
  29. let mut context: HashMap<&str, Context> = HashMap::new();
  30. if let Ok(snippet) = snippet::get(&connection, &uuid) {
  31. let lines: Vec<String> = snippet
  32. .formatted_body
  33. .split('\n')
  34. .collect::<Vec<&str>>()
  35. .iter()
  36. .map(|line| line.to_string())
  37. .collect();
  38. context.insert("context", Context { snippet, lines });
  39. Template::render("snippets/show", &context)
  40. } else {
  41. Template::render("404", &context)
  42. }
  43. }
  44. #[get("/snippets/<uuid>/raw")]
  45. pub fn show_raw_snippet(uuid: String, connection: DbConn) -> String {
  46. match snippet::get(&connection, &uuid) {
  47. Ok(snippet) => htmlescape::decode_html(&snippet.body).expect("Invalid HTML"),
  48. Err(_) => String::from("Snippet not found"),
  49. }
  50. }
  51. #[post("/api/snippets", format = "application/json", data = "<snippet>")]
  52. pub fn create_snippet(
  53. snippet: Json<ApiSnippet>,
  54. connection: DbConn,
  55. ) -> Result<status::Created<Json<Snippet>>, Status> {
  56. snippet::insert(snippet.into_inner(), &connection)
  57. .map(|snippet| status::Created(String::from(""), Some(Json(snippet))))
  58. .map_err(error_response)
  59. }
  60. #[catch(400)]
  61. pub fn bad_request(req: &Request) -> String {
  62. req.headers().get_one("content-length").map_or(
  63. String::from("{\"message\": \"Bad request\"}"),
  64. |length| {
  65. if length
  66. .parse::<i32>()
  67. .expect("Content length is non-numeric")
  68. > 1_000_000
  69. {
  70. String::from("{\"message\": \"Snippet must be under 1mb\"}")
  71. } else {
  72. String::from("{\"message\": \"Bad request\"}")
  73. }
  74. },
  75. )
  76. }
  77. #[catch(404)]
  78. pub fn not_found() -> Template {
  79. let context: HashMap<(), ()> = HashMap::new();
  80. Template::render("404", &context)
  81. }