rippled
JSONRPCUtil.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/Log.h>
21 #include <ripple/json/to_string.h>
22 #include <ripple/protocol/BuildInfo.h>
23 #include <ripple/protocol/SystemParameters.h>
24 #include <ripple/protocol/jss.h>
25 #include <ripple/server/impl/JSONRPCUtil.h>
26 #include <boost/algorithm/string.hpp>
27 
28 namespace ripple {
29 
32 {
33  // CHECKME This is probably called often enough that optimizing it makes
34  // sense. There's no point in doing all this work if this function
35  // gets called multiple times a second.
36  char buffer[96];
37  time_t now;
38  time(&now);
39  struct tm now_gmt
40  {
41  };
42 #ifndef _MSC_VER
43  gmtime_r(&now, &now_gmt);
44 #else
45  gmtime_s(&now_gmt, &now);
46 #endif
47  strftime(
48  buffer,
49  sizeof(buffer),
50  "Date: %a, %d %b %Y %H:%M:%S +0000\r\n",
51  &now_gmt);
52  return std::string(buffer);
53 }
54 
55 void
57  int nStatus,
58  std::string const& content,
59  Json::Output const& output,
61 {
62  JLOG(j.trace()) << "HTTP Reply " << nStatus << " " << content;
63 
64  if (content.empty() && nStatus == 401)
65  {
66  output("HTTP/1.0 401 Authorization Required\r\n");
67  output(getHTTPHeaderTimestamp());
68 
69  // CHECKME this returns a different version than the replies below. Is
70  // this by design or an accident or should it be using
71  // BuildInfo::getFullVersionString () as well?
72  output("Server: " + systemName() + "-json-rpc/v1");
73  output("\r\n");
74 
75  // Be careful in modifying this! If you change the contents you MUST
76  // update the Content-Length header as well to indicate the correct
77  // size of the data.
78  output(
79  "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
80  "Content-Type: text/html\r\n"
81  "Content-Length: 296\r\n"
82  "\r\n"
83  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 "
84  "Transitional//EN\"\r\n"
85  "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"
86  "\">\r\n"
87  "<HTML>\r\n"
88  "<HEAD>\r\n"
89  "<TITLE>Error</TITLE>\r\n"
90  "<META HTTP-EQUIV='Content-Type' "
91  "CONTENT='text/html; charset=ISO-8859-1'>\r\n"
92  "</HEAD>\r\n"
93  "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n");
94 
95  return;
96  }
97 
98  switch (nStatus)
99  {
100  case 200:
101  output("HTTP/1.1 200 OK\r\n");
102  break;
103  case 202:
104  output("HTTP/1.1 202 Accepted\r\n");
105  break;
106  case 400:
107  output("HTTP/1.1 400 Bad Request\r\n");
108  break;
109  case 401:
110  output("HTTP/1.1 401 Authorization Required\r\n");
111  break;
112  case 403:
113  output("HTTP/1.1 403 Forbidden\r\n");
114  break;
115  case 404:
116  output("HTTP/1.1 404 Not Found\r\n");
117  break;
118  case 405:
119  output("HTTP/1.1 405 Method Not Allowed\r\n");
120  break;
121  case 429:
122  output("HTTP/1.1 429 Too Many Requests\r\n");
123  break;
124  case 500:
125  output("HTTP/1.1 500 Internal Server Error\r\n");
126  break;
127  case 501:
128  output("HTTP/1.1 501 Not Implemented\r\n");
129  break;
130  case 503:
131  output("HTTP/1.1 503 Server is overloaded\r\n");
132  break;
133  }
134 
135  output(getHTTPHeaderTimestamp());
136 
137  output(
138  "Connection: Keep-Alive\r\n"
139  "Content-Length: ");
140 
141  // VFALCO TODO Determine if/when this header should be added
142  // if (context.app.config().RPC_ALLOW_REMOTE)
143  // output ("Access-Control-Allow-Origin: *\r\n");
144 
145  output(std::to_string(content.size() + 2));
146  output(
147  "\r\n"
148  "Content-Type: application/json; charset=UTF-8\r\n");
149 
150  output("Server: " + systemName() + "-json-rpc/");
152  output(
153  "\r\n"
154  "\r\n");
155  output(content);
156  output("\r\n");
157 }
158 
159 } // namespace ripple
std::string
STL class.
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::getHTTPHeaderTimestamp
std::string getHTTPHeaderTimestamp()
Definition: JSONRPCUtil.cpp:31
ripple::HTTPReply
void HTTPReply(int nStatus, std::string const &content, Json::Output const &output, beast::Journal j)
Definition: JSONRPCUtil.cpp:56
std::function
std::to_string
T to_string(T... args)
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::BuildInfo::getFullVersionString
std::string const & getFullVersionString()
Full server version string.
Definition: BuildInfo.cpp:78
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::systemName
static std::string const & systemName()
Definition: SystemParameters.h:34