azure_functions/http/response_builder.rs
1use crate::bindings::HttpResponse;
2use crate::http::{Body, Status};
3
4/// Represents a builder for HTTP responses.
5#[derive(Default, Debug)]
6pub struct ResponseBuilder(pub(crate) HttpResponse);
7
8impl ResponseBuilder {
9 /// Creates a new `ResponseBuilder`.
10 pub fn new() -> ResponseBuilder {
11 ResponseBuilder(HttpResponse::new())
12 }
13
14 /// Sets the status for the response.
15 ///
16 /// # Examples
17 ///
18 /// ```rust
19 /// # use azure_functions::http::ResponseBuilder;
20 /// use azure_functions::http::Status;
21 ///
22 /// let response = ResponseBuilder::new()
23 /// .status(Status::InternalServerError)
24 /// .finish();
25 ///
26 /// assert_eq!(response.status(), Status::InternalServerError);
27 /// ```
28 pub fn status<S: Into<Status>>(mut self, status: S) -> Self {
29 self.0.status = status.into();
30 self
31 }
32
33 /// Sets a header for the response.
34 ///
35 /// # Examples
36 ///
37 /// ```rust
38 /// # use azure_functions::http::ResponseBuilder;
39 ///
40 /// let value = "custom header value";
41 ///
42 /// let response = ResponseBuilder::new()
43 /// .header("X-Custom-Header", value)
44 /// .finish();
45 ///
46 /// assert_eq!(
47 /// response
48 /// .headers()
49 /// .get("X-Custom-Header")
50 /// .unwrap(),
51 /// value
52 /// );
53 /// ```
54 pub fn header<T: Into<String>, U: Into<String>>(mut self, name: T, value: U) -> Self {
55 self.0.data.headers.insert(name.into(), value.into());
56 self
57 }
58
59 /// Sets the body of the response.
60 ///
61 /// This will automatically set a `Content-Type` header for the response depending on the body type.
62 ///
63 /// # Examples
64 ///
65 /// ```rust
66 /// # use azure_functions::http::ResponseBuilder;
67 /// use azure_functions::http::{Body, Status};
68 ///
69 /// let message = "The resouce was created.";
70 ///
71 /// let response = ResponseBuilder::new()
72 /// .status(Status::Created)
73 /// .body(message)
74 /// .finish();
75 ///
76 /// assert_eq!(response.status(), Status::Created);
77 /// assert_eq!(
78 /// response.body().as_str().unwrap(),
79 /// message
80 /// );
81 /// ```
82 pub fn body<'a, B>(mut self, body: B) -> Self
83 where
84 B: Into<Body<'a>>,
85 {
86 let body = body.into();
87 if let Body::Empty = &body {
88 self.0.data.body = None;
89 return self;
90 }
91
92 if !self.0.headers().contains_key("Content-Type") {
93 self.0.data.headers.insert(
94 "Content-Type".to_string(),
95 body.default_content_type().to_string(),
96 );
97 }
98 self.0.data.body = Some(Box::new(body.into()));
99 self
100 }
101
102 /// Consumes the builder and returns the HTTP response.
103 pub fn finish(self) -> HttpResponse {
104 self.0
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn it_creates_an_empty_response() {
114 let response: HttpResponse = ResponseBuilder::new().finish();
115 assert_eq!(response.status(), Status::Ok);
116 assert_eq!(response.body().as_str().unwrap(), "");
117 }
118
119 #[test]
120 fn it_sets_a_status() {
121 let response: HttpResponse = ResponseBuilder::new().status(Status::BadRequest).finish();
122 assert_eq!(response.status(), Status::BadRequest);
123 assert_eq!(response.body().as_str().unwrap(), "");
124 }
125
126 #[test]
127 fn it_sets_a_header() {
128 let response: HttpResponse = ResponseBuilder::new().header("foo", "bar").finish();
129 assert_eq!(response.headers().get("foo").unwrap(), "bar");
130 assert_eq!(response.body().as_str().unwrap(), "");
131 }
132
133 #[test]
134 fn it_sets_a_body() {
135 let response: HttpResponse = ResponseBuilder::new().body("test").finish();
136 assert_eq!(
137 response.headers().get("Content-Type").unwrap(),
138 "text/plain"
139 );
140 assert_eq!(response.body().as_str().unwrap(), "test");
141 }
142}