@@ -84,6 +84,59 @@ void RelayServer::runWebsocket(ThreadPool<MsgWebsocket>::Thread &thr) {
84
84
return std::string_view (rendered); // memory only valid until next call
85
85
};
86
86
87
+ auto getNodeInfoHttpResponse = [ver = uint64_t (0 ), rendered = std::string (" " )](std::string host) mutable {
88
+ if (ver != cfg ().version ()) {
89
+ tao::json::value nodeinfo = tao::json::value ({
90
+ { " links" , tao::json::value::array ({
91
+ tao::json::value ({
92
+ { " rel" , " http://nodeinfo.diaspora.software/ns/schema/2.1" },
93
+ { " href" , " https://" + host + " /nodeinfo/2.1" },
94
+ }),
95
+ }) },
96
+ });
97
+
98
+ rendered = preGenerateHttpResponse (" application/json" , tao::json::to_string (nodeinfo));
99
+ ver = cfg ().version ();
100
+ }
101
+
102
+ return std::string_view (rendered); // memory only valid until next call
103
+ };
104
+
105
+ auto getNodeInfo21HttpResponse = [ver = uint64_t (0 ), rendered = std::string (" " )]() mutable {
106
+ if (ver != cfg ().version ()) {
107
+ // https://github.com/jhass/nodeinfo/blob/main/schemas/2.1/schema.json
108
+ tao::json::value nodeinfo = tao::json::value ({
109
+ { " version" , " 2.1" },
110
+ { " software" , tao::json::value ({
111
+ { " name" , " strfry" },
112
+ { " version" , APP_GIT_VERSION },
113
+ { " repository" , " https://github.com/hoytech/strfry" },
114
+ { " homepage" , " https://github.com/hoytech/strfry" },
115
+ }) },
116
+ { " protocols" , tao::json::value::array ({
117
+ " nostr" ,
118
+ }) },
119
+ { " services" , tao::json::value ({
120
+ { " inbound" , tao::json::value::array ({}) },
121
+ { " outbound" , tao::json::value::array ({}) },
122
+ }) },
123
+ { " openRegistrations" , false },
124
+ { " usage" , tao::json::value ({
125
+ { " users" , tao::json::value ({}) },
126
+ }) },
127
+ { " metadata" , tao::json::value ({
128
+ { " features" , tao::json::value::array ({
129
+ " nostr_relay" ,
130
+ }) },
131
+ }) },
132
+ });
133
+
134
+ rendered = preGenerateHttpResponse (" application/json" , tao::json::to_string (nodeinfo));
135
+ ver = cfg ().version ();
136
+ }
137
+
138
+ return std::string_view (rendered); // memory only valid until next call
139
+ };
87
140
88
141
89
142
{
@@ -100,7 +153,16 @@ void RelayServer::runWebsocket(ThreadPool<MsgWebsocket>::Thread &thr) {
100
153
hubGroup->onHttpRequest ([&](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t length, size_t remainingBytes){
101
154
LI << " HTTP request for [" << req.getUrl ().toString () << " ]" ;
102
155
103
- if (req.getHeader (" accept" ).toStringView () == " application/nostr+json" ) {
156
+ std::string host = req.getHeader (" host" ).toString ();
157
+ std::string url = req.getUrl ().toString ();
158
+
159
+ if (url == " /.well-known/nodeinfo" ) {
160
+ auto nodeInfo = getNodeInfoHttpResponse (host);
161
+ res->write (nodeInfo.data (), nodeInfo.size ());
162
+ } else if (url == " /nodeinfo/2.1" ) {
163
+ auto nodeInfo = getNodeInfo21HttpResponse ();
164
+ res->write (nodeInfo.data (), nodeInfo.size ());
165
+ } else if (req.getHeader (" accept" ).toStringView () == " application/nostr+json" ) {
104
166
auto info = getServerInfoHttpResponse ();
105
167
res->write (info.data (), info.size ());
106
168
} else {
0 commit comments