]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/http/file_handler.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / src / http / file_handler.cc
1 /*
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.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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
16 * under the License.
17 */
18 /*
19 * Copyright 2015 Cloudius Systems
20 */
21
22 #include <seastar/http/file_handler.hh>
23 #include <algorithm>
24 #include <iostream>
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>
30
31 namespace seastar {
32
33 namespace httpd {
34
35 directory_handler::directory_handler(const sstring& doc_root,
36 file_transformer* transformer)
37 : file_interaction_handler(transformer), doc_root(doc_root) {
38 }
39
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"];
43 auto h = this;
44 return engine().file_type(full_path).then(
45 [h, full_path, req = std::move(req), rep = std::move(rep)](auto val) mutable {
46 if (val) {
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));
50 }
51 full_path += "/index.html";
52 }
53 return h->read(full_path, std::move(req), std::move(rep));
54 }
55 rep->set_status(reply::status_type::not_found).done();
56 return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
57
58 });
59 }
60
61 file_interaction_handler::~file_interaction_handler() {
62 delete transformer;
63 }
64
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('.');
68 sstring extension;
69 if (last_dot_pos != sstring::npos && last_dot_pos > last_slash_pos) {
70 extension = file.substr(last_dot_pos + 1);
71 }
72 return extension;
73 }
74
75 output_stream<char> file_interaction_handler::get_stream(std::unique_ptr<request> req,
76 const sstring& extension, output_stream<char>&& s) {
77 if (transformer) {
78 return transformer->transform(std::move(req), extension, std::move(s));
79 }
80 return std::move(s);
81 }
82
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] {
93 return os.close();
94 }).then([&is] {
95 return is.close();
96 });
97 });
98 });
99 });
100 });
101 return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
102 }
103
104 bool file_interaction_handler::redirect_if_needed(const request& req,
105 reply& rep) const {
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() + "/";
109 rep.done();
110 return true;
111 }
112 return false;
113 }
114
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));
119 }
120 return read(file, std::move(req), std::move(rep));
121 }
122
123 }
124
125 }