| // Copyright 2015 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef WEBSERVER_WEBSERVD_REQUEST_H_ |
| #define WEBSERVER_WEBSERVD_REQUEST_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <tuple> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/files/file.h> |
| #include <base/files/file_path.h> |
| #include <base/macros.h> |
| #include <base/memory/weak_ptr.h> |
| #include <brillo/streams/stream.h> |
| |
| struct MHD_Connection; |
| struct MHD_PostProcessor; |
| |
| namespace webservd { |
| |
| class ProtocolHandler; |
| class TempFileManager; |
| |
| using PairOfStrings = std::pair<std::string, std::string>; |
| |
| // This class represents the file information about a file uploaded via |
| // POST request using multipart/form-data request. |
| class FileInfo final { |
| public: |
| FileInfo(const std::string& in_field_name, |
| const std::string& in_file_name, |
| const std::string& in_content_type, |
| const std::string& in_transfer_encoding); |
| FileInfo(const FileInfo&) = delete; |
| FileInfo& operator=(const FileInfo&) = delete; |
| |
| // The name of the form field for the file upload. |
| std::string field_name; |
| // The name of the file name specified in the form field. |
| std::string file_name; |
| // The content type of the file data. |
| std::string content_type; |
| // Data transfer encoding specified. Could be empty if no transfer encoding |
| // was specified. |
| std::string transfer_encoding; |
| // The file content data. |
| brillo::StreamPtr data_stream; |
| // The temporary file containing the file part data. |
| base::FilePath temp_file_name; |
| }; |
| |
| // A class that represents the HTTP request data. |
| class Request final { |
| public: |
| Request(const std::string& request_handler_id, |
| const std::string& url, |
| const std::string& method, |
| const std::string& version, |
| MHD_Connection* connection, |
| ProtocolHandler* protocol_handler); |
| Request(const Request&) = delete; |
| Request& operator=(const Request&) = delete; |
| |
| ~Request(); |
| |
| // Obtains the file descriptor containing data of uploaded file identified |
| // by |file_id|. |
| base::File GetFileData(int file_id); |
| |
| // Finishes the request and provides the reply data. |
| base::File Complete( |
| int32_t status_code, |
| const std::vector<std::tuple<std::string, std::string>>& headers, |
| int64_t in_data_size); |
| |
| // Helper function to provide the string data and mime type. |
| bool Complete( |
| int32_t status_code, |
| const std::vector<std::tuple<std::string, std::string>>& headers, |
| const std::string& mime_type, |
| const std::string& data); |
| |
| // Returns the unique ID of this request (GUID). |
| const std::string& GetID() const { return id_; } |
| |
| // Returns the unique ID of the request handler this request is processed by |
| // (GUID). |
| const std::string& GetRequestHandlerID() const { return request_handler_id_; } |
| |
| // Returns the unique ID of the protocol handler this request is received |
| // from (GUID or "http"/"https" for the two default handlers). |
| const std::string& GetProtocolHandlerID() const; |
| |
| // Returns the object path of the HTTP request (e.g. "/privet/info"). |
| const std::string& GetURL() const { return url_; } |
| |
| // Returns the request method (e.g. "GET", "POST", ...). |
| const std::string& GetMethod() const { return method_; } |
| |
| // Returns the output end of the body data stream pipe. The file descriptor |
| // is owned by the caller and must be closed when no longer needed. |
| // The pipe will contain the request body data, or no data if the request |
| // had no body or a POST request has been parsed into form data. |
| // In case there is no data, the file descriptor will represent a closed pipe, |
| // so reading from it will just indicate end-of-file (no data to read). |
| int GetBodyDataFileDescriptor() const; |
| |
| // Returns the POST form field data. |
| const std::vector<PairOfStrings>& GetDataPost() const { return post_data_; } |
| |
| // Returns query parameters specified on the URL (as in "?param=value"). |
| const std::vector<PairOfStrings>& GetDataGet() const { return get_data_; } |
| |
| // Returns the information about any files uploaded as part of POST request. |
| const std::vector<std::unique_ptr<FileInfo>>& GetFileInfo() const { |
| return file_info_; |
| } |
| |
| // Returns the HTTP request headers. |
| const std::vector<PairOfStrings>& GetHeaders() const { return headers_; } |
| |
| private: |
| friend class RequestHelper; |
| friend class ServerHelper; |
| |
| // Helper methods for processing request data coming from the raw HTTP |
| // connection. |
| // Helper callback methods used by ProtocolHandler's ConnectionHandler to |
| // transfer request headers and data to the Request object. |
| bool BeginRequestData(); |
| bool AddRequestData(const void* data, size_t* size); |
| void EndRequestData(); |
| |
| // Callback for libmicrohttpd's PostProcessor. |
| bool ProcessPostData(const char* key, |
| const char* filename, |
| const char* content_type, |
| const char* transfer_encoding, |
| const char* data, |
| uint64_t off, |
| size_t size); |
| |
| // These methods parse the request headers and data so they can be accessed |
| // by request handlers later. |
| // AddRawRequestData takes the amount of data to write in |*size|. On output, |
| // |*size| contains the number of bytes REMAINING to be written, or 0 if all |
| // data have been written successfully. |
| bool AddRawRequestData(const void* data, size_t* size); |
| bool AddPostFieldData(const char* key, |
| const char* filename, |
| const char* content_type, |
| const char* transfer_encoding, |
| const char* data, |
| size_t size); |
| bool AppendPostFieldData(const char* key, const char* data, size_t size); |
| |
| // Callback to be called when data can be written to the output pipe again. |
| void OnPipeAvailable(brillo::Stream::AccessMode mode); |
| |
| // Forwards the request to the request handler. |
| void ForwardRequestToHandler(); |
| |
| // Response data callback for MHD_create_response_from_callback(). |
| static ssize_t ResponseDataCallback(void* cls, |
| uint64_t pos, |
| char* buf, |
| size_t max); |
| |
| TempFileManager* GetTempFileManager(); |
| |
| std::string id_; |
| std::string request_handler_id_; |
| std::string url_; |
| std::string method_; |
| std::string version_; |
| MHD_Connection* connection_{nullptr}; |
| MHD_PostProcessor* post_processor_{nullptr}; |
| // Data pipe for request body data (output/read end of the pipe). |
| base::File request_data_pipe_out_; |
| // Data stream for the input/write end of the request data pipe. |
| brillo::StreamPtr request_data_stream_; |
| |
| bool last_posted_data_was_file_{false}; |
| bool request_forwarded_{false}; |
| bool request_data_finished_{false}; |
| bool response_data_started_{false}; |
| bool response_data_finished_{false}; |
| bool waiting_for_data_{false}; |
| |
| std::vector<PairOfStrings> post_data_; |
| std::vector<PairOfStrings> get_data_; |
| std::vector<std::unique_ptr<FileInfo>> file_info_; |
| std::vector<PairOfStrings> headers_; |
| |
| int response_status_code_{0}; |
| // Data size of response, -1 if unknown. |
| int64_t response_data_size_{-1}; |
| // Data stream for the output/read end of the response data pipe. |
| brillo::StreamPtr response_data_stream_; |
| std::vector<PairOfStrings> response_headers_; |
| ProtocolHandler* protocol_handler_; |
| |
| base::WeakPtrFactory<Request> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace webservd |
| |
| #endif // WEBSERVER_WEBSERVD_REQUEST_H_ |