1use std::io;
16
17use std::pin::Pin;
18use std::task::{Context, Poll};
19
20use actix_web::error::PayloadError;
21use actix_web::{dev, Error, FromRequest, HttpRequest, HttpResponse};
22use bytes::Bytes;
23use futures::{future, Stream};
24use pin_project::pin_project;
25
26pub struct DavRequest {
30 pub request: http::Request<DavBody>,
31 prefix: Option<String>,
32}
33
34impl DavRequest {
35 pub fn prefix(&self) -> Option<&str> {
37 self.prefix.as_ref().map(|s| s.as_str())
38 }
39}
40
41impl FromRequest for DavRequest {
42 type Config = ();
43 type Error = Error;
44 type Future = future::Ready<Result<DavRequest, Error>>;
45
46 fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
47 let mut builder = http::Request::builder()
48 .method(req.method().to_owned())
49 .uri(req.uri().to_owned())
50 .version(req.version().to_owned());
51 for (name, value) in req.headers().iter() {
52 builder = builder.header(name, value);
53 }
54 let path = req.match_info().path();
55 let tail = req.match_info().unprocessed();
56 let prefix = match &path[..path.len() - tail.len()] {
57 "" | "/" => None,
58 x => Some(x.to_string()),
59 };
60
61 let body = DavBody { body: payload.take() };
62 let stdreq = DavRequest {
63 request: builder.body(body).unwrap(),
64 prefix,
65 };
66 future::ready(Ok(stdreq))
67 }
68}
69
70#[pin_project]
74pub struct DavBody {
75 #[pin]
76 body: dev::Payload,
77}
78
79impl http_body::Body for DavBody {
80 type Data = Bytes;
81 type Error = io::Error;
82
83 fn poll_data(
84 self: Pin<&mut Self>,
85 cx: &mut Context<'_>,
86 ) -> Poll<Option<Result<Self::Data, Self::Error>>>
87 {
88 let this = self.project();
89 match this.body.poll_next(cx) {
90 Poll::Ready(Some(Ok(data))) => Poll::Ready(Some(Ok(data))),
91 Poll::Ready(Some(Err(err))) => {
92 Poll::Ready(Some(Err(match err {
93 PayloadError::Incomplete(Some(err)) => err,
94 PayloadError::Incomplete(None) => io::ErrorKind::BrokenPipe.into(),
95 PayloadError::Io(err) => err,
96 other => io::Error::new(io::ErrorKind::Other, format!("{:?}", other)),
97 })))
98 },
99 Poll::Ready(None) => Poll::Ready(None),
100 Poll::Pending => Poll::Pending,
101 }
102 }
103
104 fn poll_trailers(
105 self: Pin<&mut Self>,
106 _cx: &mut Context,
107 ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>>
108 {
109 Poll::Ready(Ok(None))
110 }
111}
112
113pub struct DavResponse(pub http::Response<crate::body::Body>);
117
118impl From<http::Response<crate::body::Body>> for DavResponse {
119 fn from(resp: http::Response<crate::body::Body>) -> DavResponse {
120 DavResponse(resp)
121 }
122}
123
124impl actix_web::Responder for DavResponse {
125
126 fn respond_to(self, _req: &HttpRequest) -> HttpResponse {
127 use crate::body::{Body, BodyType};
128
129 let (parts, body) = self.0.into_parts();
130 let mut builder = HttpResponse::build(parts.status);
131 for (name, value) in parts.headers.into_iter() {
132 builder.append_header((name.unwrap(), value));
133 }
134 let resp = match body.inner {
140 BodyType::Bytes(None) => builder.body(""),
141 BodyType::Bytes(Some(b)) => builder.body(b),
142 BodyType::Empty => builder.body(""),
143 b @ BodyType::AsyncStream(..) => builder.streaming(Body { inner: b }),
144 };
145 resp
146 }
147}