]>
git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/http/file_handler.cc
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
19 * Copyright 2015 Cloudius Systems
22 #include <seastar/http/file_handler.hh>
25 #include <seastar/core/reactor.hh>
26 #include <seastar/core/fstream.hh>
27 #include <seastar/core/shared_ptr.hh>
28 #include <seastar/core/app-template.hh>
29 #include <seastar/http/exception.hh>
35 directory_handler::directory_handler(const sstring
& doc_root
,
36 file_transformer
* transformer
)
37 : file_interaction_handler(transformer
), doc_root(doc_root
) {
40 future
<std::unique_ptr
<reply
>> directory_handler::handle(const sstring
& path
,
41 std::unique_ptr
<request
> req
, std::unique_ptr
<reply
> rep
) {
42 sstring full_path
= doc_root
+ req
->param
["path"];
44 return engine().file_type(full_path
).then(
45 [h
, full_path
, req
= std::move(req
), rep
= std::move(rep
)](auto val
) mutable {
47 if (val
.value() == directory_entry_type::directory
) {
48 if (h
->redirect_if_needed(*req
.get(), *rep
.get())) {
49 return make_ready_future
<std::unique_ptr
<reply
>>(std::move(rep
));
51 full_path
+= "/index.html";
53 return h
->read(full_path
, std::move(req
), std::move(rep
));
55 rep
->set_status(reply::status_type::not_found
).done();
56 return make_ready_future
<std::unique_ptr
<reply
>>(std::move(rep
));
61 file_interaction_handler::~file_interaction_handler() {
65 sstring
file_interaction_handler::get_extension(const sstring
& file
) {
66 size_t last_slash_pos
= file
.find_last_of('/');
67 size_t last_dot_pos
= file
.find_last_of('.');
69 if (last_dot_pos
!= sstring::npos
&& last_dot_pos
> last_slash_pos
) {
70 extension
= file
.substr(last_dot_pos
+ 1);
75 output_stream
<char> file_interaction_handler::get_stream(std::unique_ptr
<request
> req
,
76 const sstring
& extension
, output_stream
<char>&& s
) {
78 return transformer
->transform(std::move(req
), extension
, std::move(s
));
83 future
<std::unique_ptr
<reply
>> file_interaction_handler::read(
84 sstring file_name
, std::unique_ptr
<request
> req
,
85 std::unique_ptr
<reply
> rep
) {
86 sstring extension
= get_extension(file_name
);
87 rep
->write_body(extension
, [req
= std::move(req
), extension
, file_name
, this] (output_stream
<char>&& s
) mutable {
88 return do_with(output_stream
<char>(get_stream(std::move(req
), extension
, std::move(s
))),
89 [file_name
] (output_stream
<char>& os
) {
90 return open_file_dma(file_name
, open_flags::ro
).then([&os
] (file f
) {
91 return do_with(input_stream
<char>(make_file_input_stream(std::move(f
))), [&os
](input_stream
<char>& is
) {
92 return copy(is
, os
).then([&os
] {
101 return make_ready_future
<std::unique_ptr
<reply
>>(std::move(rep
));
104 bool file_interaction_handler::redirect_if_needed(const request
& req
,
106 if (req
._url
.length() == 0 || req
._url
.back() != '/') {
107 rep
.set_status(reply::status_type::moved_permanently
);
108 rep
._headers
["Location"] = req
.get_url() + "/";
115 future
<std::unique_ptr
<reply
>> file_handler::handle(const sstring
& path
,
116 std::unique_ptr
<request
> req
, std::unique_ptr
<reply
> rep
) {
117 if (force_path
&& redirect_if_needed(*req
.get(), *rep
.get())) {
118 return make_ready_future
<std::unique_ptr
<reply
>>(std::move(rep
));
120 return read(file
, std::move(req
), std::move(rep
));