1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include "http_ex.h"
#include <util/generic/buffer.h>
#include <util/generic/cast.h>
#include <util/stream/null.h>
bool THttpClientRequestExtension::Parse(char* req, TBaseServerRequestData& rd) {
rd.SetSocket(Socket());
if (!rd.Parse(req)) {
Output() << "HTTP/1.1 403 Forbidden\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 39\r\n"
"\r\n"
"The server cannot be used as a proxy.\r\n";
return false;
}
return true;
}
bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBlob& postData) {
for (const auto& header : ParsedHeaders) {
rd.AddHeader(header.first, header.second);
}
char* s = RequestString.begin();
enum EMethod {
NotImplemented,
Get,
Post,
Put,
Patch,
Delete,
Options,
};
enum EMethod foundMethod;
char* urlStart;
if (strnicmp(s, "GET ", 4) == 0) {
foundMethod = Get;
urlStart = s + 4;
} else if (strnicmp(s, "POST ", 5) == 0) {
foundMethod = Post;
urlStart = s + 5;
} else if (strnicmp(s, "PUT ", 4) == 0) {
foundMethod = Put;
urlStart = s + 4;
} else if (strnicmp(s, "PATCH ", 6) == 0) {
foundMethod = Patch;
urlStart = s + 6;
} else if (strnicmp(s, "DELETE ", 7) == 0) {
foundMethod = Delete;
urlStart = s + 7;
} else if (strnicmp(s, "OPTIONS ", 8) == 0) {
foundMethod = Options;
urlStart = s + 8;
} else {
foundMethod = NotImplemented;
}
switch (foundMethod) {
case Get:
case Delete:
if (!Parse(urlStart, rd)) {
return false;
}
break;
case Post:
case Put:
case Patch:
try {
ui64 contentLength = 0;
if (Input().HasExpect100Continue()) {
Output().SendContinue();
}
if (!Input().ContentEncoded() && Input().GetContentLength(contentLength)) {
if (contentLength > HttpServ()->Options().MaxInputContentLength) {
Output() << "HTTP/1.1 413 Payload Too Large\r\nContent-Length:0\r\n\r\n";
Output().Finish();
return false;
}
TBuffer buf(SafeIntegerCast<size_t>(contentLength));
Input().LoadOrFail(buf.Data(), (size_t)contentLength);
buf.Resize((size_t)contentLength);
postData = TBlob::FromBuffer(buf);
} else {
postData = TBlob::FromStream(Input());
}
} catch (...) {
Output() << "HTTP/1.1 400 Bad request\r\n\r\n";
return false;
}
if (!Parse(urlStart, rd)) {
return false;
}
break;
case Options:
if (!OptionsAllowed()) {
Output() << "HTTP/1.1 405 Method Not Allowed\r\n\r\n";
return false;
} else if (!Parse(urlStart, rd)) {
return false;
}
break;
case NotImplemented:
Output() << "HTTP/1.1 501 Not Implemented\r\n\r\n";
return false;
}
return true;
}
|