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