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