blob: 37ea1c16911306bd39b5239045225af257d391c7 [file] [log] [blame]
Alex Vakulenko039da312015-02-03 08:58:55 -08001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <libwebserv/request.h>
6
7#include <libwebserv/connection.h>
8
9namespace libwebserv {
10
11FileInfo::FileInfo(const std::string& file_name,
12 const std::string& content_type,
13 const std::string& transfer_encoding)
14 : file_name_(file_name),
15 content_type_(content_type),
16 transfer_encoding_(transfer_encoding) {
17}
18
19const std::vector<uint8_t>& FileInfo::GetData() const {
20 return data_;
21}
22
23Request::Request(const std::string& url, const std::string& method)
24 : url_{url}, method_{method} {
25}
26
27Request::~Request() {
28}
29
30scoped_ptr<Request> Request::Create(const std::string& url,
31 const std::string& method) {
32 // Can't use make_shared here since Request::Request is private.
33 return scoped_ptr<Request>(new Request(url, method));
34}
35
36const std::vector<uint8_t>& Request::GetData() const {
37 return raw_data_;
38}
39
40bool Request::AddRawRequestData(const void* data, size_t size) {
41 const uint8_t* byte_data_ = static_cast<const uint8_t*>(data);
42 raw_data_.insert(raw_data_.end(), byte_data_, byte_data_ + size);
43 return true;
44}
45
46bool Request::AddPostFieldData(const char* key,
47 const char* filename,
48 const char* content_type,
49 const char* transfer_encoding,
50 const char* data,
51 size_t size) {
52 if (filename) {
53 std::unique_ptr<FileInfo> file_info{
54 new FileInfo{filename, content_type ? content_type : "",
55 transfer_encoding ? transfer_encoding : ""}};
56 file_info->data_.assign(data, data + size);
57 file_info_.emplace(key, std::move(file_info));
58 last_posted_data_was_file_ = true;
59 return true;
60 }
61 std::string value{data, size};
62 post_data_.emplace(key, value);
63 last_posted_data_was_file_ = false;
64 return true;
65}
66
67bool Request::AppendPostFieldData(const char* key,
68 const char* data,
69 size_t size) {
70 if (last_posted_data_was_file_) {
71 auto file_pair = file_info_.equal_range(key);
72 if (file_pair.first == file_info_.end())
73 return false;
74 FileInfo* file_info = file_pair.second->second.get();
75 file_info->data_.insert(file_info->data_.end(), data, data + size);
76 return true;
77 }
78
79 auto pair = post_data_.equal_range(key);
80 if (pair.first == post_data_.end())
81 return false;
82 --pair.second; // Get the last form field with this name/key.
83 pair.second->second.append(data, size);
84 return true;
85}
86
87std::vector<PairOfStrings> Request::GetFormData() const {
88 auto data = GetFormDataGet();
89 auto post_data = GetFormDataPost();
90 data.insert(data.end(), post_data.begin(), post_data.end());
91 return data;
92}
93
94std::vector<PairOfStrings> Request::GetFormDataGet() const {
95 return std::vector<PairOfStrings>{get_data_.begin(), get_data_.end()};
96}
97
98std::vector<PairOfStrings> Request::GetFormDataPost() const {
99 return std::vector<PairOfStrings>{post_data_.begin(), post_data_.end()};
100}
101
102std::vector<std::pair<std::string, const FileInfo*>> Request::GetFiles() const {
103 std::vector<std::pair<std::string, const FileInfo*>> data;
104 data.reserve(file_info_.size());
105 for (const auto& pair : file_info_) {
106 data.emplace_back(pair.first, pair.second.get());
107 }
108 return data;
109}
110
111std::vector<std::string> Request::GetFormField(const std::string& name) const {
112 std::vector<std::string> data;
113 auto pair = get_data_.equal_range(name);
114 while (pair.first != pair.second) {
115 data.push_back(pair.first->second);
116 ++pair.first;
117 }
118 pair = post_data_.equal_range(name);
119 while (pair.first != pair.second) {
120 data.push_back(pair.first->second);
121 ++pair.first;
122 }
123 return data;
124}
125
126std::vector<std::string> Request::GetFormFieldPost(
127 const std::string& name) const {
128 std::vector<std::string> data;
129 auto pair = post_data_.equal_range(name);
130 while (pair.first != pair.second) {
131 data.push_back(pair.first->second);
132 ++pair.first;
133 }
134 return data;
135}
136
137std::vector<std::string> Request::GetFormFieldGet(
138 const std::string& name) const {
139 std::vector<std::string> data;
140 auto pair = get_data_.equal_range(name);
141 while (pair.first != pair.second) {
142 data.push_back(pair.first->second);
143 ++pair.first;
144 }
145 return data;
146}
147
148std::vector<const FileInfo*> Request::GetFileInfo(
149 const std::string& name) const {
150 std::vector<const FileInfo*> data;
151 auto pair = file_info_.equal_range(name);
152 while (pair.first != pair.second) {
153 data.push_back(pair.first->second.get());
154 ++pair.first;
155 }
156 return data;
157}
158
159std::vector<PairOfStrings> Request::GetHeaders() const {
160 return std::vector<PairOfStrings>{headers_.begin(), headers_.end()};
161}
162
163std::vector<std::string> Request::GetHeader(const std::string& name) const {
164 std::vector<std::string> data;
165 auto pair = headers_.equal_range(GetCanonicalHeaderName(name));
166 while (pair.first != pair.second) {
167 data.push_back(pair.first->second);
168 ++pair.first;
169 }
170 return data;
171}
172
173std::string Request::GetCanonicalHeaderName(const std::string& name) {
174 std::string canonical_name = name;
175 bool word_begin = true;
176 for (char& c : canonical_name) {
177 if (c == '-') {
178 word_begin = true;
179 } else {
180 if (word_begin) {
181 c = toupper(c);
182 } else {
183 c = tolower(c);
184 }
185 word_begin = false;
186 }
187 }
188 return canonical_name;
189}
190
191} // namespace libwebserv