]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | ||
20 | #include <limits> | |
21 | #include <cstdlib> | |
22 | #include <sstream> | |
23 | #include <boost/algorithm/string.hpp> | |
24 | ||
25 | #include <thrift/config.h> | |
26 | #include <thrift/transport/THttpClient.h> | |
27 | #include <thrift/transport/TSocket.h> | |
28 | ||
29 | using std::string; | |
30 | ||
31 | namespace apache { | |
32 | namespace thrift { | |
33 | namespace transport { | |
34 | ||
35 | THttpClient::THttpClient(std::shared_ptr<TTransport> transport, | |
36 | std::string host, | |
37 | std::string path) | |
38 | : THttpTransport(transport), host_(host), path_(path) { | |
39 | } | |
40 | ||
41 | THttpClient::THttpClient(string host, int port, string path) | |
42 | : THttpTransport(std::shared_ptr<TTransport>(new TSocket(host, port))), | |
43 | host_(host), | |
44 | path_(path) { | |
45 | } | |
46 | ||
47 | THttpClient::~THttpClient() = default; | |
48 | ||
49 | void THttpClient::parseHeader(char* header) { | |
50 | char* colon = strchr(header, ':'); | |
51 | if (colon == nullptr) { | |
52 | return; | |
53 | } | |
54 | char* value = colon + 1; | |
55 | ||
56 | if (boost::istarts_with(header, "Transfer-Encoding")) { | |
57 | if (boost::iends_with(value, "chunked")) { | |
58 | chunked_ = true; | |
59 | } | |
60 | } else if (boost::istarts_with(header, "Content-Length")) { | |
61 | chunked_ = false; | |
62 | contentLength_ = atoi(value); | |
63 | } | |
64 | } | |
65 | ||
66 | bool THttpClient::parseStatusLine(char* status) { | |
67 | char* http = status; | |
68 | ||
69 | char* code = strchr(http, ' '); | |
70 | if (code == nullptr) { | |
71 | throw TTransportException(string("Bad Status: ") + status); | |
72 | } | |
73 | ||
74 | *code = '\0'; | |
75 | while (*(code++) == ' ') { | |
76 | }; | |
77 | ||
78 | char* msg = strchr(code, ' '); | |
79 | if (msg == nullptr) { | |
80 | throw TTransportException(string("Bad Status: ") + status); | |
81 | } | |
82 | *msg = '\0'; | |
83 | ||
84 | if (strcmp(code, "200") == 0) { | |
85 | // HTTP 200 = OK, we got the response | |
86 | return true; | |
87 | } else if (strcmp(code, "100") == 0) { | |
88 | // HTTP 100 = continue, just keep reading | |
89 | return false; | |
90 | } else { | |
91 | throw TTransportException(string("Bad Status: ") + status); | |
92 | } | |
93 | } | |
94 | ||
95 | void THttpClient::flush() { | |
96 | // Fetch the contents of the write buffer | |
97 | uint8_t* buf; | |
98 | uint32_t len; | |
99 | writeBuffer_.getBuffer(&buf, &len); | |
100 | ||
101 | // Construct the HTTP header | |
102 | std::ostringstream h; | |
103 | h << "POST " << path_ << " HTTP/1.1" << CRLF << "Host: " << host_ << CRLF | |
104 | << "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF | |
105 | << "Accept: application/x-thrift" << CRLF << "User-Agent: Thrift/" << PACKAGE_VERSION | |
106 | << " (C++/THttpClient)" << CRLF << CRLF; | |
107 | string header = h.str(); | |
108 | ||
109 | if (header.size() > (std::numeric_limits<uint32_t>::max)()) | |
110 | throw TTransportException("Header too big"); | |
111 | // Write the header, then the data, then flush | |
112 | transport_->write((const uint8_t*)header.c_str(), static_cast<uint32_t>(header.size())); | |
113 | transport_->write(buf, len); | |
114 | transport_->flush(); | |
115 | ||
116 | // Reset the buffer and header variables | |
117 | writeBuffer_.resetBuffer(); | |
118 | readHeaders_ = true; | |
119 | } | |
120 | } | |
121 | } | |
122 | } // apache::thrift::transport |