File: reply.hpp

package info (click to toggle)
libzeep 5.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 3,596 kB
  • sloc: cpp: 27,393; xml: 7,798; javascript: 180; sh: 37; makefile: 8
file content (183 lines) | stat: -rw-r--r-- 5,737 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Copyright Maarten L. Hekkelman, Radboud University 2008-2013.
//        Copyright Maarten L. Hekkelman, 2014-2022
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#pragma once

/// \file
/// definition of the zeep::http::reply class encapsulating a valid HTTP reply

#include <zeep/config.hpp>

#include <boost/asio/buffer.hpp>

#include <zeep/http/header.hpp>
#include <zeep/xml/document.hpp>
#include <zeep/json/element.hpp>

namespace zeep::http
{

/// Various predefined HTTP status codes

enum status_type
{
    cont =                  100,
    ok =                    200,
    created =               201,
    accepted =              202,
    no_content =            204,
    multiple_choices =      300,
    moved_permanently =     301,
    moved_temporarily =     302,
	see_other =             303,
    not_modified =          304,
    bad_request =           400,
    unauthorized =          401,
    forbidden =             403,
    not_found =             404,
	method_not_allowed =	405,
	proxy_authentication_required =	407,
    internal_server_error = 500,
    not_implemented =       501,
    bad_gateway =           502,
    service_unavailable =   503
};

/// Return the error string for the status_type
std::string get_status_text(status_type status);

/// Return the string describing the status_type in more detail
std::string get_status_description(status_type status);

/// \brief the class containing all to generate a HTTP reply
///
/// Create a HTTP reply, should be either HTTP 1.0 or 1.1

class reply
{
  public:
	using cookie_directive = header;

	/// Create a reply, default is HTTP 1.0. Use 1.1 if you want to use keep alive e.g.
	reply(status_type status = internal_server_error, std::tuple<int,int> version = { 1, 0 });

	reply(status_type status, std::tuple<int,int> version,
		std::vector<header>&& headers, std::string&& payload);

	reply(const reply& rhs);
	reply(reply &&rhs);

	~reply();
	reply& operator=(const reply &);
	reply& operator=(reply &&);

	void reset();

	void set_version(int version_major, int version_minor);

	void set_version(std::tuple<int,int> version)
	{
		set_version(std::get<0>(version), std::get<1>(version));
	}

	/// Add a header with name \a name and value \a value
	void set_header(const std::string& name, const std::string& value);

	/// \brief Return the value of the header with name \a name
	std::string get_header(const std::string& name) const;

	/// \brief Remove the header with name \a name from the list of headers
	void remove_header(const std::string& name);

	/// Set a cookie
	void set_cookie(const char* name, const std::string& value, std::initializer_list<cookie_directive> directives = {});

	/// \brief Set a header to delete the \a name cookie
	void set_delete_cookie(const char* name);

	/// Get a cookie
	std::string get_cookie(const char* name) const;

	std::string get_content_type() const
	{
		return get_header("Content-Type");
	}

	void set_content_type(const std::string& type) ///< Set the Content-Type header
	{
		set_header("Content-Type", type);
	}

	/// Set the content and the content-type header depending on the content of doc (might be xhtml)
	void set_content(xml::document& doc);

	/// Set the content and the content-type header to text/xml
	void set_content(const xml::element& data);

	/// Set the content and the content-type header based on JSON data
	void set_content(const json::element& json);

	/// Set the content and the content-type header
	void set_content(const std::string& data, const std::string& contentType);

	/// Set the content by copying \a data and the content-type header
	void set_content(const char* data, size_t size, const std::string& contentType);

	/// To send a stream of data, with unknown size (using chunked transfer).
	/// reply takes ownership of \a data and deletes it when done.
	void set_content(std::istream* data, const std::string& contentType);

	/// return the content, only useful if the content was set with
	/// some constant string data. 
	const std::string& get_content() const
	{
		return m_content;
	}

	/// return the content of the reply as an array of boost::asio::const_buffer objects
	std::vector<boost::asio::const_buffer> to_buffers() const;

	/// for istream data, if the returned buffer array is empty, the data is done
	std::vector<boost::asio::const_buffer> data_to_buffers();

	/// Create a standard reply based on a HTTP status code
	static reply stock_reply(status_type inStatus);
	static reply stock_reply(status_type inStatus, const std::string& info);

	/// Create a standard redirect reply with the specified \a location
	static reply redirect(const std::string& location);
	static reply redirect(const std::string& location, status_type status);

	void set_status(status_type status) { m_status = status; }
	status_type get_status() const { return m_status; }

	/// return the size of the reply, only correct if the reply is fully memory based (no streams)
	size_t size() const;

	/// \brief Return true if the content will be sent chunked encoded
	bool get_chunked() const												{ return m_chunked; }

	/// for debugging
	friend std::ostream& operator<<(std::ostream& os, const reply& rep);

  private:
	friend class reply_parser;

	status_type m_status;
	int m_version_major, m_version_minor;
	std::vector<header> m_headers;
	std::istream* m_data;
	std::vector<char> m_buffer;
	std::string m_content;
	
	bool m_chunked = false;
	char m_size_buffer[8];	///< to store the string with the size for chunked encoding

	// this status line is only here to have a sensible location to store it
	mutable std::string m_status_line;
};

}