Skip to content

Commit fec0d10

Browse files
committed
Merge pull request #5376
8a5c951 [REST] make selection of output-format mandatory, support dot url syntax (Jonas Schnelli)
2 parents 7026cbd + 8a5c951 commit fec0d10

File tree

1 file changed

+57
-32
lines changed

1 file changed

+57
-32
lines changed

src/rest.cpp

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,24 @@ using namespace std;
1818
using namespace json_spirit;
1919

2020
enum RetFormat {
21+
RF_UNDEF,
2122
RF_BINARY,
2223
RF_HEX,
2324
RF_JSON,
2425
};
2526

2627
static const struct {
2728
enum RetFormat rf;
28-
const char *name;
29+
const char* name;
2930
} rf_names[] = {
30-
{ RF_BINARY, "binary" }, // default, if match not found
31-
{ RF_HEX, "hex" },
32-
{ RF_JSON, "json" },
31+
{RF_UNDEF, ""},
32+
{RF_BINARY, "bin"},
33+
{RF_HEX, "hex"},
34+
{RF_JSON, "json"},
3335
};
3436

35-
class RestErr {
37+
class RestErr
38+
{
3639
public:
3740
enum HTTPStatusCode status;
3841
string message;
@@ -49,15 +52,34 @@ static RestErr RESTERR(enum HTTPStatusCode status, string message)
4952
return re;
5053
}
5154

52-
static enum RetFormat ParseDataFormat(const string& format)
55+
static enum RetFormat ParseDataFormat(vector<string>& params, const string strReq)
5356
{
54-
for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
55-
if (format == rf_names[i].name)
56-
return rf_names[i].rf;
57+
boost::split(params, strReq, boost::is_any_of("."));
58+
if (params.size() > 1) {
59+
for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
60+
if (params[1] == rf_names[i].name)
61+
return rf_names[i].rf;
62+
}
5763

5864
return rf_names[0].rf;
5965
}
6066

67+
static string AvailableDataFormatsString()
68+
{
69+
string formats = "";
70+
for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
71+
if (strlen(rf_names[i].name) > 0) {
72+
formats.append(".");
73+
formats.append(rf_names[i].name);
74+
formats.append(", ");
75+
}
76+
77+
if (formats.length() > 0)
78+
return formats.substr(0, formats.length() - 2);
79+
80+
return formats;
81+
}
82+
6183
static bool ParseHashStr(const string& strReq, uint256& v)
6284
{
6385
if (!IsHex(strReq) || (strReq.size() != 64))
@@ -67,15 +89,13 @@ static bool ParseHashStr(const string& strReq, uint256& v)
6789
return true;
6890
}
6991

70-
static bool rest_block(AcceptedConnection *conn,
92+
static bool rest_block(AcceptedConnection* conn,
7193
string& strReq,
7294
map<string, string>& mapHeaders,
7395
bool fRun)
7496
{
7597
vector<string> params;
76-
boost::split(params, strReq, boost::is_any_of("/"));
77-
78-
enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string(""));
98+
enum RetFormat rf = ParseDataFormat(params, strReq);
7999

80100
string hashStr = params[0];
81101
uint256 hash;
@@ -105,7 +125,7 @@ static bool rest_block(AcceptedConnection *conn,
105125
}
106126

107127
case RF_HEX: {
108-
string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";;
128+
string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
109129
conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
110130
return true;
111131
}
@@ -115,22 +135,24 @@ static bool rest_block(AcceptedConnection *conn,
115135
string strJSON = write_string(Value(objBlock), false) + "\n";
116136
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
117137
return true;
118-
}
138+
}
139+
140+
default: {
141+
throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
142+
}
119143
}
120144

121145
// not reached
122-
return true; // continue to process further HTTP reqs on this cxn
146+
return true; // continue to process further HTTP reqs on this cxn
123147
}
124148

125-
static bool rest_tx(AcceptedConnection *conn,
149+
static bool rest_tx(AcceptedConnection* conn,
126150
string& strReq,
127151
map<string, string>& mapHeaders,
128152
bool fRun)
129153
{
130154
vector<string> params;
131-
boost::split(params, strReq, boost::is_any_of("/"));
132-
133-
enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string(""));
155+
enum RetFormat rf = ParseDataFormat(params, strReq);
134156

135157
string hashStr = params[0];
136158
uint256 hash;
@@ -153,7 +175,7 @@ static bool rest_tx(AcceptedConnection *conn,
153175
}
154176

155177
case RF_HEX: {
156-
string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";;
178+
string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
157179
conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
158180
return true;
159181
}
@@ -165,42 +187,45 @@ static bool rest_tx(AcceptedConnection *conn,
165187
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
166188
return true;
167189
}
190+
191+
default: {
192+
throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
193+
}
168194
}
169195

170196
// not reached
171-
return true; // continue to process further HTTP reqs on this cxn
197+
return true; // continue to process further HTTP reqs on this cxn
172198
}
173199

174200
static const struct {
175-
const char *prefix;
176-
bool (*handler)(AcceptedConnection *conn,
201+
const char* prefix;
202+
bool (*handler)(AcceptedConnection* conn,
177203
string& strURI,
178204
map<string, string>& mapHeaders,
179205
bool fRun);
180206
} uri_prefixes[] = {
181-
{ "/rest/tx/", rest_tx },
182-
{ "/rest/block/", rest_block },
207+
{"/rest/tx/", rest_tx},
208+
{"/rest/block/", rest_block},
183209
};
184210

185-
bool HTTPReq_REST(AcceptedConnection *conn,
211+
bool HTTPReq_REST(AcceptedConnection* conn,
186212
string& strURI,
187213
map<string, string>& mapHeaders,
188214
bool fRun)
189215
{
190216
try {
191217
std::string statusmessage;
192-
if(RPCIsInWarmup(&statusmessage))
193-
throw RESTERR(HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: "+statusmessage);
194-
218+
if (RPCIsInWarmup(&statusmessage))
219+
throw RESTERR(HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: " + statusmessage);
220+
195221
for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++) {
196222
unsigned int plen = strlen(uri_prefixes[i].prefix);
197223
if (strURI.substr(0, plen) == uri_prefixes[i].prefix) {
198224
string strReq = strURI.substr(plen);
199225
return uri_prefixes[i].handler(conn, strReq, mapHeaders, fRun);
200226
}
201227
}
202-
}
203-
catch (RestErr& re) {
228+
} catch (RestErr& re) {
204229
conn->stream() << HTTPReply(re.status, re.message + "\r\n", false, false, "text/plain") << std::flush;
205230
return false;
206231
}

0 commit comments

Comments
 (0)