]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/webserver.hh
"Adress" is actually prural in query-local-address
[thirdparty/pdns.git] / pdns / webserver.hh
CommitLineData
12c86877 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
e8c59f2d 22#pragma once
12c86877
BH
23#include <map>
24#include <string>
232f0877 25#include <list>
3ae143b0
CH
26#include <boost/utility.hpp>
27#include <yahttp/yahttp.hpp>
5938c49f 28#include "json11.hpp"
10f4eea8 29#include "namespaces.hh"
825fa717 30#include "sstuff.hh"
12c86877 31
80d59cd1
CH
32class HttpRequest : public YaHTTP::Request {
33public:
e35f9e46 34 HttpRequest(const string& logprefix_="") : YaHTTP::Request(), accept_json(false), accept_html(false), complete(false), logprefix(logprefix_) { };
80d59cd1 35
80d59cd1
CH
36 bool accept_json;
37 bool accept_html;
825fa717 38 bool complete;
a53cd863 39 string logprefix;
5938c49f 40 json11::Json json();
bbef8f04
CH
41
42 // checks password _only_.
43 bool compareAuthorization(const string &expected_password);
44 bool compareHeader(const string &header_name, const string &expected_value);
80d59cd1
CH
45};
46
47class HttpResponse: public YaHTTP::Response {
48public:
49 HttpResponse() : YaHTTP::Response() { };
80d59cd1 50 HttpResponse(const YaHTTP::Response &resp) : YaHTTP::Response(resp) { };
669822d0 51
5938c49f 52 void setBody(const json11::Json& document);
692829aa
CH
53 void setErrorResult(const std::string& message, const int status);
54 void setSuccessResult(const std::string& message, const int status = 200);
80d59cd1
CH
55};
56
57
33196945
CH
58class HttpException
59{
60public:
80d59cd1 61 HttpException(int status) : d_response()
33196945 62 {
80d59cd1 63 d_response.status = status;
33196945
CH
64 };
65
8204102e
PL
66 HttpException(int status, const string& msg) : d_response()
67 {
68 d_response.setErrorResult(msg, status);
69 };
70
80d59cd1
CH
71 HttpResponse response()
72 {
73 return d_response;
33196945
CH
74 }
75
80d59cd1
CH
76protected:
77 HttpResponse d_response;
33196945
CH
78};
79
80class HttpBadRequestException : public HttpException {
81public:
80d59cd1 82 HttpBadRequestException() : HttpException(400) { };
8204102e 83 HttpBadRequestException(const string& msg) : HttpException(400, msg) { };
33196945
CH
84};
85
86class HttpUnauthorizedException : public HttpException {
87public:
53255086 88 HttpUnauthorizedException(string const &scheme) : HttpException(401)
80d59cd1 89 {
53255086 90 d_response.headers["WWW-Authenticate"] = scheme + " realm=\"PowerDNS\"";
33196945
CH
91 }
92};
93
53255086
PL
94class HttpForbiddenException : public HttpException {
95public:
96 HttpForbiddenException() : HttpException(403) { };
8204102e 97 HttpForbiddenException(const string& msg) : HttpException(403, msg) { };
53255086
PL
98};
99
33196945
CH
100class HttpNotFoundException : public HttpException {
101public:
80d59cd1 102 HttpNotFoundException() : HttpException(404) { };
8204102e 103 HttpNotFoundException(const string& msg) : HttpException(404, msg) { };
33196945
CH
104};
105
106class HttpMethodNotAllowedException : public HttpException {
107public:
80d59cd1 108 HttpMethodNotAllowedException() : HttpException(405) { };
8204102e 109 HttpMethodNotAllowedException(const string& msg) : HttpException(405, msg) { };
33196945
CH
110};
111
331d3062
CH
112class HttpConflictException : public HttpException {
113public:
114 HttpConflictException() : HttpException(409) { };
f7b99555 115 HttpConflictException(const string& msg) : HttpException(409, msg) { };
331d3062
CH
116};
117
0f67eeda
CH
118class HttpInternalServerErrorException : public HttpException {
119public:
120 HttpInternalServerErrorException() : HttpException(500) { };
8204102e 121 HttpInternalServerErrorException(const string& msg) : HttpException(500, msg) { };
0f67eeda
CH
122};
123
3ae143b0
CH
124class ApiException : public runtime_error
125{
126public:
1df079f5 127 ApiException(const string& what_arg) : runtime_error(what_arg) {
3ae143b0
CH
128 }
129};
02c04144 130
a7650f23
CH
131class Server
132{
133public:
93f4e5ce 134 Server(const string &localaddress, int port) : d_local(localaddress.empty() ? "0.0.0.0" : localaddress, port), d_server_socket(d_local.sin4.sin_family, SOCK_STREAM, 0) {
a7650f23
CH
135 d_server_socket.setReuseAddr();
136 d_server_socket.bind(d_local);
137 d_server_socket.listen();
138 }
690984d4 139 virtual ~Server() { };
a7650f23
CH
140
141 ComboAddress d_local;
142
d4c53d8c
RG
143 std::shared_ptr<Socket> accept() {
144 return std::shared_ptr<Socket>(d_server_socket.accept());
a7650f23
CH
145 }
146
147protected:
148 Socket d_server_socket;
149};
150
3ae143b0 151class WebServer : public boost::noncopyable
12c86877
BH
152{
153public:
bbef8f04 154 WebServer(const string &listenaddress, int port);
690984d4 155 virtual ~WebServer() { };
29997a3c
PL
156
157 void setApiKey(const string &apikey) {
29997a3c
PL
158 d_apikey = apikey;
159 }
160
0c3b088c 161 void setPassword(const string &password) {
0c3b088c
PL
162 d_webserverPassword = password;
163 }
164
214b034e
PD
165 void setMaxBodySize(ssize_t s) { // in megabytes
166 d_maxbodysize = s * 1024 * 1024;
167 }
168
0010aefa
PL
169 void setACL(const NetmaskGroup &nmg) {
170 d_acl = nmg;
171 }
172
825fa717 173 void bind();
12c86877 174 void go();
232f0877 175
b184a9dc
RG
176 void serveConnection(std::shared_ptr<Socket> client) const;
177 void handleRequest(HttpRequest& request, HttpResponse& resp) const;
232f0877 178
80d59cd1 179 typedef boost::function<void(HttpRequest* req, HttpResponse* resp)> HandlerFunction;
c563cbe5 180 void registerApiHandler(const string& url, HandlerFunction handler, bool allowPassword=false);
bbef8f04 181 void registerWebHandler(const string& url, HandlerFunction handler);
232f0877 182
a53cd863
PL
183 enum class LogLevel : uint8_t {
184 None = 0, // No logs from requests at all
a35306f9 185 Normal = 10, // A "common log format"-like line e.g. '127.0.0.1 "GET /apache_pb.gif HTTP/1.0" 200 2326'
a53cd863
PL
186 Detailed = 20, // The full request headers and body, and the full response headers and body
187 };
188
60986c4b
PL
189 void setLogLevel(const string& level) {
190 if (level == "none") {
191 d_loglevel = LogLevel::None;
192 return;
193 }
194
a35306f9
PL
195 if (level == "normal") {
196 d_loglevel = LogLevel::Normal;
60986c4b
PL
197 return;
198 }
199
200 if (level == "detailed") {
201 d_loglevel = LogLevel::Detailed;
202 return;
203 }
204
205 throw PDNSException("Unknown webserver log level: " + level);
206 }
207
a53cd863
PL
208 void setLogLevel(const LogLevel level) {
209 d_loglevel = level;
210 };
211
212 LogLevel getLogLevel() {
213 return d_loglevel;
214 };
b2cb8982 215
3ae143b0 216protected:
bbef8f04 217 void registerBareHandler(const string& url, HandlerFunction handler);
612ad9ec
PL
218 void logRequest(const HttpRequest& req, const ComboAddress& remote) const;
219 void logResponse(const HttpResponse& resp, const ComboAddress& remote, const string& logprefix) const;
232f0877 220
690984d4
RG
221 virtual std::shared_ptr<Server> createServer() {
222 return std::make_shared<Server>(d_listenaddress, d_port);
825fa717
CH
223 }
224
12c86877
BH
225 string d_listenaddress;
226 int d_port;
232f0877 227 string d_password;
690984d4 228 std::shared_ptr<Server> d_server;
29997a3c
PL
229
230 std::string d_apikey;
c563cbe5 231 void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp, bool allowPassword);
0c3b088c 232 std::string d_webserverPassword;
7579a7b9 233 void webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp);
0010aefa 234
214b034e
PD
235 ssize_t d_maxbodysize; // in bytes
236
0010aefa 237 NetmaskGroup d_acl;
b2cb8982
PL
238
239 const string d_logprefix = "[webserver] ";
a53cd863
PL
240
241 // Describes the amount of logging the webserver does
242 WebServer::LogLevel d_loglevel{WebServer::LogLevel::Detailed};
12c86877 243};