WPILibC++  unspecified
HttpUtil.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #ifndef WPIUTIL_SUPPORT_HTTPUTIL_H_
9 #define WPIUTIL_SUPPORT_HTTPUTIL_H_
10 
11 #include <memory>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 
16 #include "llvm/ArrayRef.h"
17 #include "llvm/SmallString.h"
18 #include "llvm/SmallVector.h"
19 #include "llvm/StringMap.h"
20 #include "llvm/StringRef.h"
21 #include "llvm/Twine.h"
22 #include "support/raw_istream.h"
23 #include "support/raw_socket_istream.h"
24 #include "support/raw_socket_ostream.h"
25 #include "tcpsockets/NetworkStream.h"
26 
27 namespace wpi {
28 
29 // Unescape a %xx-encoded URI.
30 // @param buf Buffer for output
31 // @param error Set to true if an error occurred
32 // @return Escaped string
33 llvm::StringRef UnescapeURI(const llvm::Twine& str,
34  llvm::SmallVectorImpl<char>& buf, bool* error);
35 
36 // Escape a string with %xx-encoding.
37 // @param buf Buffer for output
38 // @param spacePlus If true, encodes spaces to '+' rather than "%20"
39 // @return Escaped string
40 llvm::StringRef EscapeURI(const llvm::Twine& str,
42  bool spacePlus = true);
43 
44 // Parse a set of HTTP headers. Saves just the Content-Type and Content-Length
45 // fields.
46 // @param is Input stream
47 // @param contentType If not null, Content-Type contents are saved here.
48 // @param contentLength If not null, Content-Length contents are saved here.
49 // @return False if error occurred in input stream
50 bool ParseHttpHeaders(wpi::raw_istream& is,
51  llvm::SmallVectorImpl<char>* contentType,
52  llvm::SmallVectorImpl<char>* contentLength);
53 
54 // Look for a MIME multi-part boundary. On return, the input stream will
55 // be located at the character following the boundary (usually "\r\n").
56 // @param is Input stream
57 // @param boundary Boundary string to scan for (not including "--" prefix)
58 // @param saveBuf If not null, all scanned characters up to but not including
59 // the boundary are saved to this string
60 // @return False if error occurred on input stream, true if boundary found.
61 bool FindMultipartBoundary(wpi::raw_istream& is, llvm::StringRef boundary,
62  std::string* saveBuf);
63 
64 class HttpLocation {
65  public:
66  HttpLocation() = default;
67  HttpLocation(const llvm::Twine& url_, bool* error, std::string* errorMsg);
68 
69  std::string url; // retain copy
70  std::string user; // unescaped
71  std::string password; // unescaped
72  std::string host;
73  int port;
74  std::string path; // escaped, not including leading '/'
75  std::vector<std::pair<std::string, std::string>> params; // unescaped
76  std::string fragment;
77 };
78 
79 class HttpRequest {
80  public:
81  HttpRequest() = default;
82 
83  explicit HttpRequest(const HttpLocation& loc)
84  : host{loc.host}, port{loc.port} {
85  SetPath(loc.path, loc.params);
86  SetAuth(loc);
87  }
88 
89  template <typename T>
90  HttpRequest(const HttpLocation& loc, const T& extraParams);
91 
92  HttpRequest(const HttpLocation& loc, llvm::StringRef path_)
93  : host{loc.host}, port{loc.port}, path{path_} {
94  SetAuth(loc);
95  }
96 
97  template <typename T>
98  HttpRequest(const HttpLocation& loc, llvm::StringRef path_, const T& params)
99  : host{loc.host}, port{loc.port} {
100  SetPath(path_, params);
101  SetAuth(loc);
102  }
103 
105  int port;
106  std::string auth;
108 
109  private:
110  void SetAuth(const HttpLocation& loc);
111  template <typename T>
112  void SetPath(llvm::StringRef path_, const T& params);
113 
114  template <typename T>
115  static llvm::StringRef GetFirst(const T& elem) {
116  return elem.first;
117  }
118  template <typename T>
119  static llvm::StringRef GetFirst(const llvm::StringMapEntry<T>& elem) {
120  return elem.getKey();
121  }
122  template <typename T>
123  static llvm::StringRef GetSecond(const T& elem) {
124  return elem.second;
125  }
126 };
127 
129  public:
130  HttpConnection(std::unique_ptr<wpi::NetworkStream> stream_, int timeout)
131  : stream{std::move(stream_)}, is{*stream, timeout}, os{*stream, true} {}
132 
133  bool Handshake(const HttpRequest& request, std::string* warnMsg);
134 
135  std::unique_ptr<wpi::NetworkStream> stream;
138 
139  // Valid after Handshake() is successful
140  llvm::SmallString<64> contentType;
141  llvm::SmallString<64> contentLength;
142 
143  explicit operator bool() const { return stream && !is.has_error(); }
144 };
145 
146 } // namespace wpi
147 
148 #include "HttpUtil.inl"
149 
150 #endif // WPIUTIL_SUPPORT_HTTPUTIL_H_
Definition: HttpUtil.h:79
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
Definition: StringMap.h:31
Definition: raw_socket_istream.h:17
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
Definition: SocketError.cpp:17
Definition: HttpUtil.h:64
Definition: raw_istream.h:21
Definition: HttpUtil.h:128
Definition: raw_socket_ostream.h:17
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:42