1/*
2 * IXHttp.h
3 * Author: Benjamin Sergeant
4 * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
5 */
6
7#pragma once
8
9#include "IXProgressCallback.h"
10#include "IXWebSocketHttpHeaders.h"
11#include <atomic>
12#include <tuple>
13#include <unordered_map>
14
15namespace ix
16{
17 enum class HttpErrorCode : int
18 {
19 Ok = 0,
20 CannotConnect = 1,
21 Timeout = 2,
22 Gzip = 3,
23 UrlMalformed = 4,
24 CannotCreateSocket = 5,
25 SendError = 6,
26 ReadError = 7,
27 CannotReadStatusLine = 8,
28 MissingStatus = 9,
29 HeaderParsingError = 10,
30 MissingLocation = 11,
31 TooManyRedirects = 12,
32 ChunkReadError = 13,
33 CannotReadBody = 14,
34 Cancelled = 15,
35 Invalid = 100
36 };
37
38 struct HttpResponse
39 {
40 int statusCode;
41 std::string description;
42 HttpErrorCode errorCode;
43 WebSocketHttpHeaders headers;
44 std::string body;
45 std::string errorMsg;
46 uint64_t uploadSize;
47 uint64_t downloadSize;
48
49 HttpResponse(int s = 0,
50 const std::string& des = std::string(),
51 const HttpErrorCode& c = HttpErrorCode::Ok,
52 const WebSocketHttpHeaders& h = WebSocketHttpHeaders(),
53 const std::string& b = std::string(),
54 const std::string& e = std::string(),
55 uint64_t u = 0,
56 uint64_t d = 0)
57 : statusCode(s)
58 , description(des)
59 , errorCode(c)
60 , headers(h)
61 , body(b)
62 , errorMsg(e)
63 , uploadSize(u)
64 , downloadSize(d)
65 {
66 ;
67 }
68 };
69
70 using HttpResponsePtr = std::shared_ptr<HttpResponse>;
71 using HttpParameters = std::unordered_map<std::string, std::string>;
72 using HttpFormDataParameters = std::unordered_map<std::string, std::string>;
73 using Logger = std::function<void(const std::string&)>;
74 using OnResponseCallback = std::function<void(const HttpResponsePtr&)>;
75
76 struct HttpRequestArgs
77 {
78 std::string url;
79 std::string verb;
80 WebSocketHttpHeaders extraHeaders;
81 std::string body;
82 std::string multipartBoundary;
83 int connectTimeout = 60;
84 int transferTimeout = 1800;
85 bool followRedirects = true;
86 int maxRedirects = 5;
87 bool verbose = false;
88 bool compress = true;
89 bool compressRequest = false;
90 Logger logger;
91 OnProgressCallback onProgressCallback;
92 OnChunkCallback onChunkCallback;
93 std::atomic<bool> cancel;
94 };
95
96 using HttpRequestArgsPtr = std::shared_ptr<HttpRequestArgs>;
97
98 struct HttpRequest
99 {
100 std::string uri;
101 std::string method;
102 std::string version;
103 std::string body;
104 WebSocketHttpHeaders headers;
105
106 HttpRequest(const std::string& u,
107 const std::string& m,
108 const std::string& v,
109 const std::string& b,
110 const WebSocketHttpHeaders& h = WebSocketHttpHeaders())
111 : uri(u)
112 , method(m)
113 , version(v)
114 , body(b)
115 , headers(h)
116 {
117 }
118 };
119
120 using HttpRequestPtr = std::shared_ptr<HttpRequest>;
121
122 class Http
123 {
124 public:
125 static std::tuple<bool, std::string, HttpRequestPtr> parseRequest(
126 std::unique_ptr<Socket>& socket, int timeoutSecs);
127 static bool sendResponse(HttpResponsePtr response, std::unique_ptr<Socket>& socket);
128
129 static std::pair<std::string, int> parseStatusLine(const std::string& line);
130 static std::tuple<std::string, std::string, std::string> parseRequestLine(
131 const std::string& line);
132 static std::string trim(const std::string& str);
133 };
134} // namespace ix
135