1 // Copyright 2015 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef WEBSERVER_WEBSERVD_REQUEST_H_ 16 #define WEBSERVER_WEBSERVD_REQUEST_H_ 17 18 #include <memory> 19 #include <string> 20 #include <tuple> 21 #include <utility> 22 #include <vector> 23 24 #include <base/files/file.h> 25 #include <base/files/file_path.h> 26 #include <base/macros.h> 27 #include <base/memory/weak_ptr.h> 28 #include <brillo/streams/stream.h> 29 30 struct MHD_Connection; 31 struct MHD_PostProcessor; 32 33 namespace webservd { 34 35 class ProtocolHandler; 36 class TempFileManager; 37 38 using PairOfStrings = std::pair<std::string, std::string>; 39 40 // This class represents the file information about a file uploaded via 41 // POST request using multipart/form-data request. 42 class FileInfo final { 43 public: 44 FileInfo(const std::string& in_field_name, 45 const std::string& in_file_name, 46 const std::string& in_content_type, 47 const std::string& in_transfer_encoding); 48 49 // The name of the form field for the file upload. 50 std::string field_name; 51 // The name of the file name specified in the form field. 52 std::string file_name; 53 // The content type of the file data. 54 std::string content_type; 55 // Data transfer encoding specified. Could be empty if no transfer encoding 56 // was specified. 57 std::string transfer_encoding; 58 // The file content data. 59 brillo::StreamPtr data_stream; 60 // The temporary file containing the file part data. 61 base::FilePath temp_file_name; 62 63 private: 64 DISALLOW_COPY_AND_ASSIGN(FileInfo); 65 }; 66 67 // A class that represents the HTTP request data. 68 class Request final { 69 public: 70 Request(const std::string& request_handler_id, 71 const std::string& url, 72 const std::string& method, 73 const std::string& version, 74 MHD_Connection* connection, 75 ProtocolHandler* protocol_handler); 76 ~Request(); 77 78 // Obtains the file descriptor containing data of uploaded file identified 79 // by |file_id|. 80 base::File GetFileData(int file_id); 81 82 // Finishes the request and provides the reply data. 83 base::File Complete( 84 int32_t status_code, 85 const std::vector<std::tuple<std::string, std::string>>& headers, 86 int64_t in_data_size); 87 88 // Helper function to provide the string data and mime type. 89 bool Complete( 90 int32_t status_code, 91 const std::vector<std::tuple<std::string, std::string>>& headers, 92 const std::string& mime_type, 93 const std::string& data); 94 95 // Returns the unique ID of this request (GUID). GetID()96 const std::string& GetID() const { return id_; } 97 98 // Returns the unique ID of the request handler this request is processed by 99 // (GUID). GetRequestHandlerID()100 const std::string& GetRequestHandlerID() const { return request_handler_id_; } 101 102 // Returns the unique ID of the protocol handler this request is received 103 // from (GUID or "http"/"https" for the two default handlers). 104 const std::string& GetProtocolHandlerID() const; 105 106 // Returns the object path of the HTTP request (e.g. "/privet/info"). GetURL()107 const std::string& GetURL() const { return url_; } 108 109 // Returns the request method (e.g. "GET", "POST", ...). GetMethod()110 const std::string& GetMethod() const { return method_; } 111 112 // Returns the output end of the body data stream pipe. The file descriptor 113 // is owned by the caller and must be closed when no longer needed. 114 // The pipe will contain the request body data, or no data if the request 115 // had no body or a POST request has been parsed into form data. 116 // In case there is no data, the file descriptor will represent a closed pipe, 117 // so reading from it will just indicate end-of-file (no data to read). 118 int GetBodyDataFileDescriptor() const; 119 120 // Returns the POST form field data. GetDataPost()121 const std::vector<PairOfStrings>& GetDataPost() const { return post_data_; } 122 123 // Returns query parameters specified on the URL (as in "?param=value"). GetDataGet()124 const std::vector<PairOfStrings>& GetDataGet() const { return get_data_; } 125 126 // Returns the information about any files uploaded as part of POST request. GetFileInfo()127 const std::vector<std::unique_ptr<FileInfo>>& GetFileInfo() const { 128 return file_info_; 129 } 130 131 // Returns the HTTP request headers. GetHeaders()132 const std::vector<PairOfStrings>& GetHeaders() const { return headers_; } 133 134 private: 135 friend class RequestHelper; 136 friend class ServerHelper; 137 138 // Helper methods for processing request data coming from the raw HTTP 139 // connection. 140 // Helper callback methods used by ProtocolHandler's ConnectionHandler to 141 // transfer request headers and data to the Request object. 142 bool BeginRequestData(); 143 bool AddRequestData(const void* data, size_t* size); 144 void EndRequestData(); 145 146 // Callback for libmicrohttpd's PostProcessor. 147 bool ProcessPostData(const char* key, 148 const char* filename, 149 const char* content_type, 150 const char* transfer_encoding, 151 const char* data, 152 uint64_t off, 153 size_t size); 154 155 // These methods parse the request headers and data so they can be accessed 156 // by request handlers later. 157 // AddRawRequestData takes the amount of data to write in |*size|. On output, 158 // |*size| contains the number of bytes REMAINING to be written, or 0 if all 159 // data have been written successfully. 160 bool AddRawRequestData(const void* data, size_t* size); 161 bool AddPostFieldData(const char* key, 162 const char* filename, 163 const char* content_type, 164 const char* transfer_encoding, 165 const char* data, 166 size_t size); 167 bool AppendPostFieldData(const char* key, const char* data, size_t size); 168 169 // Callback to be called when data can be written to the output pipe again. 170 void OnPipeAvailable(brillo::Stream::AccessMode mode); 171 172 // Forwards the request to the request handler. 173 void ForwardRequestToHandler(); 174 175 // Response data callback for MHD_create_response_from_callback(). 176 static ssize_t ResponseDataCallback(void* cls, uint64_t pos, char* buf, 177 size_t max); 178 179 TempFileManager* GetTempFileManager(); 180 181 std::string id_; 182 std::string request_handler_id_; 183 std::string url_; 184 std::string method_; 185 std::string version_; 186 MHD_Connection* connection_{nullptr}; 187 MHD_PostProcessor* post_processor_{nullptr}; 188 // Data pipe for request body data (output/read end of the pipe). 189 base::File request_data_pipe_out_; 190 // Data stream for the input/write end of the request data pipe. 191 brillo::StreamPtr request_data_stream_; 192 193 bool last_posted_data_was_file_{false}; 194 bool request_forwarded_{false}; 195 bool request_data_finished_{false}; 196 bool response_data_started_{false}; 197 bool response_data_finished_{false}; 198 bool waiting_for_data_{false}; 199 200 std::vector<PairOfStrings> post_data_; 201 std::vector<PairOfStrings> get_data_; 202 std::vector<std::unique_ptr<FileInfo>> file_info_; 203 std::vector<PairOfStrings> headers_; 204 205 int response_status_code_{0}; 206 // Data size of response, -1 if unknown. 207 int64_t response_data_size_{-1}; 208 // Data stream for the output/read end of the response data pipe. 209 brillo::StreamPtr response_data_stream_; 210 std::vector<PairOfStrings> response_headers_; 211 ProtocolHandler* protocol_handler_; 212 213 base::WeakPtrFactory<Request> weak_ptr_factory_{this}; 214 DISALLOW_COPY_AND_ASSIGN(Request); 215 }; 216 217 } // namespace webservd 218 219 #endif // WEBSERVER_WEBSERVD_REQUEST_H_ 220