| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 40a1a11 commit f8c9a58
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -400,6 +400,13 @@ default) is not firewall-protected.** | |||
| 400 | 400 | ||
| 401 | 401 | See the [debugging security implications][] section for more information. | |
| 402 | 402 | ||
| 403 | + ### `--inspect-publish-uid=stderr,http` | ||
| 404 | + | ||
| 405 | + Specify ways of the inspector web socket url exposure. | ||
| 406 | + | ||
| 407 | + By default inspector websocket url is available in stderr and under `/json/list` | ||
| 408 | + endpoint on `http://host:port/json/list`. | ||
| 409 | + | ||
| 403 | 410 | ### `--loader=file` | |
| 404 | 411 | <!-- YAML | |
| 405 | 412 | added: v9.0.0 | |
@@ -992,6 +999,7 @@ Node.js options that are allowed are: | |||
| 992 | 999 | - `--inspect` | |
| 993 | 1000 | - `--inspect-brk` | |
| 994 | 1001 | - `--inspect-port` | |
| 1002 | + - `--inspect-publish-uid` | ||
| 995 | 1003 | - `--loader` | |
| 996 | 1004 | - `--max-http-header-size` | |
| 997 | 1005 | - `--napi-modules` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -792,7 +792,10 @@ bool Agent::StartIoThread() { | |||
| 792 | 792 | ||
| 793 | 793 | CHECK_NOT_NULL(client_); | |
| 794 | 794 | ||
| 795 | - io_ = InspectorIo::Start(client_->getThreadHandle(), path_, host_port_); | ||
| 795 | + io_ = InspectorIo::Start(client_->getThreadHandle(), | ||
| 796 | + path_, | ||
| 797 | + host_port_, | ||
| 798 | + debug_options_.inspect_publish_uid); | ||
| 796 | 799 | if (io_ == nullptr) { | |
| 797 | 800 | return false; | |
| 798 | 801 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -242,9 +242,13 @@ class InspectorIoDelegate: public node::inspector::SocketServerDelegate { | |||
| 242 | 242 | std::unique_ptr<InspectorIo> InspectorIo::Start( | |
| 243 | 243 | std::shared_ptr<MainThreadHandle> main_thread, | |
| 244 | 244 | const std::string& path, | |
| 245 | - std::shared_ptr<HostPort> host_port) { | ||
| 245 | + std::shared_ptr<HostPort> host_port, | ||
| 246 | + const InspectPublishUid& inspect_publish_uid) { | ||
| 246 | 247 | auto io = std::unique_ptr<InspectorIo>( | |
| 247 | - new InspectorIo(main_thread, path, host_port)); | ||
| 248 | + new InspectorIo(main_thread, | ||
| 249 | + path, | ||
| 250 | + host_port, | ||
| 251 | + inspect_publish_uid)); | ||
| 248 | 252 | if (io->request_queue_->Expired()) { // Thread is not running | |
| 249 | 253 | return nullptr; | |
| 250 | 254 | } | |
@@ -253,9 +257,11 @@ std::unique_ptr<InspectorIo> InspectorIo::Start( | |||
| 253 | 257 | ||
| 254 | 258 | InspectorIo::InspectorIo(std::shared_ptr<MainThreadHandle> main_thread, | |
| 255 | 259 | const std::string& path, | |
| 256 | - std::shared_ptr<HostPort> host_port) | ||
| 260 | + std::shared_ptr<HostPort> host_port, | ||
| 261 | + const InspectPublishUid& inspect_publish_uid) | ||
| 257 | 262 | : main_thread_(main_thread), | |
| 258 | 263 | host_port_(host_port), | |
| 264 | + inspect_publish_uid_(inspect_publish_uid), | ||
| 259 | 265 | thread_(), | |
| 260 | 266 | script_name_(path), | |
| 261 | 267 | id_(GenerateID()) { | |
@@ -293,7 +299,8 @@ void InspectorIo::ThreadMain() { | |||
| 293 | 299 | InspectorSocketServer server(std::move(delegate), | |
| 294 | 300 | &loop, | |
| 295 | 301 | host_port_->host(), | |
| 296 | - host_port_->port()); | ||
| 302 | + host_port_->port(), | ||
| 303 | + inspect_publish_uid_); | ||
| 297 | 304 | request_queue_ = queue->handle(); | |
| 298 | 305 | // Its lifetime is now that of the server delegate | |
| 299 | 306 | queue.reset(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -48,7 +48,8 @@ class InspectorIo { | |||
| 48 | 48 | static std::unique_ptr<InspectorIo> Start( | |
| 49 | 49 | std::shared_ptr<MainThreadHandle> main_thread, | |
| 50 | 50 | const std::string& path, | |
| 51 | - std::shared_ptr<HostPort> host_port); | ||
| 51 | + std::shared_ptr<HostPort> host_port, | ||
| 52 | + const InspectPublishUid& inspect_publish_uid); | ||
| 52 | 53 | ||
| 53 | 54 | // Will block till the transport thread shuts down | |
| 54 | 55 | ~InspectorIo(); | |
@@ -61,7 +62,8 @@ class InspectorIo { | |||
| 61 | 62 | private: | |
| 62 | 63 | InspectorIo(std::shared_ptr<MainThreadHandle> handle, | |
| 63 | 64 | const std::string& path, | |
| 64 | - std::shared_ptr<HostPort> host_port); | ||
| 65 | + std::shared_ptr<HostPort> host_port, | ||
| 66 | + const InspectPublishUid& inspect_publish_uid); | ||
| 65 | 67 | ||
| 66 | 68 | // Wrapper for agent->ThreadMain() | |
| 67 | 69 | static void ThreadMain(void* agent); | |
@@ -76,6 +78,7 @@ class InspectorIo { | |||
| 76 | 78 | // running | |
| 77 | 79 | std::shared_ptr<RequestQueue> request_queue_; | |
| 78 | 80 | std::shared_ptr<HostPort> host_port_; | |
| 81 | + InspectPublishUid inspect_publish_uid_; | ||
| 79 | 82 | ||
| 80 | 83 | // The IO thread runs its own uv_loop to implement the TCP server off | |
| 81 | 84 | // the main thread. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -94,14 +94,20 @@ const char* MatchPathSegment(const char* path, const char* expected) { | |||
| 94 | 94 | return nullptr; | |
| 95 | 95 | } | |
| 96 | 96 | ||
| 97 | - void SendHttpResponse(InspectorSocket* socket, const std::string& response) { | ||
| 98 | - const char HEADERS[] = "HTTP/1.0 200 OK\r\n" | ||
| 97 | + void SendHttpResponse(InspectorSocket* socket, | ||
| 98 | + const std::string& response, | ||
| 99 | + int code) { | ||
| 100 | + const char HEADERS[] = "HTTP/1.0 %d OK\r\n" | ||
| 99 | 101 | "Content-Type: application/json; charset=UTF-8\r\n" | |
| 100 | 102 | "Cache-Control: no-cache\r\n" | |
| 101 | 103 | "Content-Length: %zu\r\n" | |
| 102 | 104 | "\r\n"; | |
| 103 | 105 | char header[sizeof(HEADERS) + 20]; | |
| 104 | - int header_len = snprintf(header, sizeof(header), HEADERS, response.size()); | ||
| 106 | + int header_len = snprintf(header, | ||
| 107 | + sizeof(header), | ||
| 108 | + HEADERS, | ||
| 109 | + code, | ||
| 110 | + response.size()); | ||
| 105 | 111 | socket->Write(header, header_len); | |
| 106 | 112 | socket->Write(response.data(), response.size()); | |
| 107 | 113 | } | |
@@ -110,7 +116,11 @@ void SendVersionResponse(InspectorSocket* socket) { | |||
| 110 | 116 | std::map<std::string, std::string> response; | |
| 111 | 117 | response["Browser"] = "node.js/" NODE_VERSION; | |
| 112 | 118 | response["Protocol-Version"] = "1.1"; | |
| 113 | - SendHttpResponse(socket, MapToString(response)); | ||
| 119 | + SendHttpResponse(socket, MapToString(response), 200); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + void SendHttpNotFound(InspectorSocket* socket) { | ||
| 123 | + SendHttpResponse(socket, "", 404); | ||
| 114 | 124 | } | |
| 115 | 125 | ||
| 116 | 126 | void SendProtocolJson(InspectorSocket* socket) { | |
@@ -131,7 +141,7 @@ void SendProtocolJson(InspectorSocket* socket) { | |||
| 131 | 141 | CHECK_EQ(Z_STREAM_END, inflate(&strm, Z_FINISH)); | |
| 132 | 142 | CHECK_EQ(0, strm.avail_out); | |
| 133 | 143 | CHECK_EQ(Z_OK, inflateEnd(&strm)); | |
| 134 | - SendHttpResponse(socket, data); | ||
| 144 | + SendHttpResponse(socket, data, 200); | ||
| 135 | 145 | } | |
| 136 | 146 | } // namespace | |
| 137 | 147 | ||
@@ -224,8 +234,9 @@ void PrintDebuggerReadyMessage( | |||
| 224 | 234 | const std::string& host, | |
| 225 | 235 | const std::vector<InspectorSocketServer::ServerSocketPtr>& server_sockets, | |
| 226 | 236 | const std::vector<std::string>& ids, | |
| 237 | + bool publish_uid_stderr, | ||
| 227 | 238 | FILE* out) { | |
| 228 | - if (out == nullptr) { | ||
| 239 | + if (!publish_uid_stderr || out == nullptr) { | ||
| 229 | 240 | return; | |
| 230 | 241 | } | |
| 231 | 242 | for (const auto& server_socket : server_sockets) { | |
@@ -241,9 +252,15 @@ void PrintDebuggerReadyMessage( | |||
| 241 | 252 | ||
| 242 | 253 | InspectorSocketServer::InspectorSocketServer( | |
| 243 | 254 | std::unique_ptr<SocketServerDelegate> delegate, uv_loop_t* loop, | |
| 244 | - const std::string& host, int port, FILE* out) | ||
| 245 | - : loop_(loop), delegate_(std::move(delegate)), host_(host), port_(port), | ||
| 246 | - next_session_id_(0), out_(out) { | ||
| 255 | + const std::string& host, int port, | ||
| 256 | + const InspectPublishUid& inspect_publish_uid, FILE* out) | ||
| 257 | + : loop_(loop), | ||
| 258 | + delegate_(std::move(delegate)), | ||
| 259 | + host_(host), | ||
| 260 | + port_(port), | ||
| 261 | + inspect_publish_uid_(inspect_publish_uid), | ||
| 262 | + next_session_id_(0), | ||
| 263 | + out_(out) { | ||
| 247 | 264 | delegate_->AssignServer(this); | |
| 248 | 265 | state_ = ServerState::kNew; | |
| 249 | 266 | } | |
@@ -280,8 +297,11 @@ void InspectorSocketServer::SessionTerminated(int session_id) { | |||
| 280 | 297 | if (connected_sessions_.empty()) { | |
| 281 | 298 | if (was_attached && state_ == ServerState::kRunning | |
| 282 | 299 | && !server_sockets_.empty()) { | |
| 283 | - PrintDebuggerReadyMessage(host_, server_sockets_, | ||
| 284 | - delegate_->GetTargetIds(), out_); | ||
| 300 | + PrintDebuggerReadyMessage(host_, | ||
| 301 | + server_sockets_, | ||
| 302 | + delegate_->GetTargetIds(), | ||
| 303 | + inspect_publish_uid_.console, | ||
| 304 | + out_); | ||
| 285 | 305 | } | |
| 286 | 306 | if (state_ == ServerState::kStopped) { | |
| 287 | 307 | delegate_.reset(); | |
@@ -294,6 +314,10 @@ bool InspectorSocketServer::HandleGetRequest(int session_id, | |||
| 294 | 314 | const std::string& path) { | |
| 295 | 315 | SocketSession* session = Session(session_id); | |
| 296 | 316 | InspectorSocket* socket = session->ws_socket(); | |
| 317 | + if (!inspect_publish_uid_.http) { | ||
| 318 | + SendHttpNotFound(socket); | ||
| 319 | + return true; | ||
| 320 | + } | ||
| 297 | 321 | const char* command = MatchPathSegment(path.c_str(), "/json"); | |
| 298 | 322 | if (command == nullptr) | |
| 299 | 323 | return false; | |
@@ -342,7 +366,7 @@ void InspectorSocketServer::SendListResponse(InspectorSocket* socket, | |||
| 342 | 366 | formatted_address); | |
| 343 | 367 | target_map["webSocketDebuggerUrl"] = FormatAddress(detected_host, id, true); | |
| 344 | 368 | } | |
| 345 | - SendHttpResponse(socket, MapsToString(response)); | ||
| 369 | + SendHttpResponse(socket, MapsToString(response), 200); | ||
| 346 | 370 | } | |
| 347 | 371 | ||
| 348 | 372 | std::string InspectorSocketServer::GetFrontendURL(bool is_compat, | |
@@ -397,8 +421,11 @@ bool InspectorSocketServer::Start() { | |||
| 397 | 421 | } | |
| 398 | 422 | delegate_.swap(delegate_holder); | |
| 399 | 423 | state_ = ServerState::kRunning; | |
| 400 | - PrintDebuggerReadyMessage(host_, server_sockets_, | ||
| 401 | - delegate_->GetTargetIds(), out_); | ||
| 424 | + PrintDebuggerReadyMessage(host_, | ||
| 425 | + server_sockets_, | ||
| 426 | + delegate_->GetTargetIds(), | ||
| 427 | + inspect_publish_uid_.console, | ||
| 428 | + out_); | ||
| 402 | 429 | return true; | |
| 403 | 430 | } | |
| 404 | 431 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -43,6 +43,7 @@ class InspectorSocketServer { | |||
| 43 | 43 | uv_loop_t* loop, | |
| 44 | 44 | const std::string& host, | |
| 45 | 45 | int port, | |
| 46 | + const InspectPublishUid& inspect_publish_uid, | ||
| 46 | 47 | FILE* out = stderr); | |
| 47 | 48 | ~InspectorSocketServer(); | |
| 48 | 49 | ||
@@ -88,6 +89,7 @@ class InspectorSocketServer { | |||
| 88 | 89 | std::unique_ptr<SocketServerDelegate> delegate_; | |
| 89 | 90 | const std::string host_; | |
| 90 | 91 | int port_; | |
| 92 | + InspectPublishUid inspect_publish_uid_; | ||
| 91 | 93 | std::vector<ServerSocketPtr> server_sockets_; | |
| 92 | 94 | std::map<int, std::pair<std::string, std::unique_ptr<SocketSession>>> | |
| 93 | 95 | connected_sessions_; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,6 +44,21 @@ void DebugOptions::CheckOptions(std::vector<std::string>* errors) { | |||
| 44 | 44 | errors->push_back("[DEP0062]: `node --inspect --debug-brk` is deprecated. " | |
| 45 | 45 | "Please use `node --inspect-brk` instead."); | |
| 46 | 46 | } | |
| 47 | + | ||
| 48 | + std::vector<std::string> destinations = | ||
| 49 | + SplitString(inspect_publish_uid_string, ','); | ||
| 50 | + inspect_publish_uid.console = false; | ||
| 51 | + inspect_publish_uid.http = false; | ||
| 52 | + for (const std::string& destination : destinations) { | ||
| 53 | + if (destination == "stderr") { | ||
| 54 | + inspect_publish_uid.console = true; | ||
| 55 | + } else if (destination == "http") { | ||
| 56 | + inspect_publish_uid.http = true; | ||
| 57 | + } else { | ||
| 58 | + errors->push_back("--inspect-publish-uid destination can be " | ||
| 59 | + "stderr or http"); | ||
| 60 | + } | ||
| 61 | + } | ||
| 47 | 62 | } | |
| 48 | 63 | ||
| 49 | 64 | void PerProcessOptions::CheckOptions(std::vector<std::string>* errors) { | |
@@ -276,6 +291,12 @@ DebugOptionsParser::DebugOptionsParser() { | |||
| 276 | 291 | AddOption("--debug-brk", "", &DebugOptions::break_first_line); | |
| 277 | 292 | Implies("--debug-brk", "--debug"); | |
| 278 | 293 | AddAlias("--debug-brk=", { "--inspect-port", "--debug-brk" }); | |
| 294 | + | ||
| 295 | + AddOption("--inspect-publish-uid", | ||
| 296 | + "comma separated list of destinations for inspector uid" | ||
| 297 | + "(default: stderr,http)", | ||
| 298 | + &DebugOptions::inspect_publish_uid_string, | ||
| 299 | + kAllowedInEnvironment); | ||
| 279 | 300 | } | |
| 280 | 301 | ||
| 281 | 302 | EnvironmentOptionsParser::EnvironmentOptionsParser() { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -50,6 +50,11 @@ class Options { | |||
| 50 | 50 | virtual ~Options() = default; | |
| 51 | 51 | }; | |
| 52 | 52 | ||
| 53 | + struct InspectPublishUid { | ||
| 54 | + bool console; | ||
| 55 | + bool http; | ||
| 56 | + }; | ||
| 57 | + | ||
| 53 | 58 | // These options are currently essentially per-Environment, but it can be nice | |
| 54 | 59 | // to keep them separate since they are a group of options applying to a very | |
| 55 | 60 | // specific part of Node. It might also make more sense for them to be | |
@@ -70,6 +75,10 @@ class DebugOptions : public Options { | |||
| 70 | 75 | bool break_first_line = false; | |
| 71 | 76 | // --inspect-brk-node | |
| 72 | 77 | bool break_node_first_line = false; | |
| 78 | + // --inspect-publish-uid | ||
| 79 | + std::string inspect_publish_uid_string = "stderr,http"; | ||
| 80 | + | ||
| 81 | + InspectPublishUid inspect_publish_uid; | ||
| 73 | 82 | ||
| 74 | 83 | enum { kDefaultInspectorPort = 9229 }; | |
| 75 | 84 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,7 @@ | |||
| 1 | 1 | #include "inspector_socket_server.h" | |
| 2 | 2 | ||
| 3 | 3 | #include "node.h" | |
| 4 | + #include "node_options.h" | ||
| 4 | 5 | #include "util-inl.h" | |
| 5 | 6 | #include "gtest/gtest.h" | |
| 6 | 7 | ||
@@ -358,8 +359,11 @@ ServerHolder::ServerHolder(bool has_targets, uv_loop_t* loop, | |||
| 358 | 359 | targets = { MAIN_TARGET_ID }; | |
| 359 | 360 | std::unique_ptr<TestSocketServerDelegate> delegate( | |
| 360 | 361 | new TestSocketServerDelegate(this, targets)); | |
| 362 | + node::InspectPublishUid inspect_publish_uid; | ||
| 363 | + inspect_publish_uid.console = true; | ||
| 364 | + inspect_publish_uid.http = true; | ||
| 361 | 365 | server_ = std::make_unique<InspectorSocketServer>( | |
| 362 | - std::move(delegate), loop, host, port, out); | ||
| 366 | + std::move(delegate), loop, host, port, inspect_publish_uid, out); | ||
| 363 | 367 | } | |
| 364 | 368 | ||
| 365 | 369 | static void TestHttpRequest(int port, const std::string& path, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,42 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + | ||
| 4 | + common.skipIfInspectorDisabled(); | ||
| 5 | + | ||
| 6 | + const assert = require('assert'); | ||
| 7 | + const { spawnSync } = require('child_process'); | ||
| 8 | + | ||
| 9 | + (async function test() { | ||
| 10 | + await testArg('stderr'); | ||
| 11 | + await testArg('http'); | ||
| 12 | + await testArg('http,stderr'); | ||
| 13 | + })(); | ||
| 14 | + | ||
| 15 | + async function testArg(argValue) { | ||
| 16 | + console.log('Checks ' + argValue + '..'); | ||
| 17 | + const hasHttp = argValue.split(',').includes('http'); | ||
| 18 | + const hasStderr = argValue.split(',').includes('stderr'); | ||
| 19 | + | ||
| 20 | + const nodeProcess = spawnSync(process.execPath, [ | ||
| 21 | + '--inspect=0', | ||
| 22 | + `--inspect-publish-uid=${argValue}`, | ||
| 23 | + '-e', `(${scriptMain.toString()})(${hasHttp ? 200 : 404})` | ||
| 24 | + ]); | ||
| 25 | + const hasWebSocketInStderr = checkStdError( | ||
| 26 | + nodeProcess.stderr.toString('utf8')); | ||
| 27 | + assert.strictEqual(hasWebSocketInStderr, hasStderr); | ||
| 28 | + | ||
| 29 | + function checkStdError(data) { | ||
| 30 | + const matches = data.toString('utf8').match(/ws:\/\/.+:(\d+)\/.+/); | ||
| 31 | + return !!matches; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + function scriptMain(code) { | ||
| 35 | + const url = require('inspector').url(); | ||
| 36 | + const { host } = require('url').parse(url); | ||
| 37 | + require('http').get('http://' + host + '/json/list', (response) => { | ||
| 38 | + assert.strictEqual(response.statusCode, code); | ||
| 39 | + response.destroy(); | ||
| 40 | + }); | ||
| 41 | + } | ||
| 42 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments