@@ -911,35 +911,231 @@ possible to connect to a long-running Node.js process without restarting it.
911
911
912
912
### Examples
913
913
914
- * Running a "full-featured" (` terminal ` ) REPL over
915
- a ` net.Server ` and ` net.Socket ` instance:
916
- < https://gist.github.com/TooTallNate/2209310 > .
914
+ #### Full-featured "terminal" REPL over ` net.Server ` and ` net.Socket `
917
915
918
- * Running a REPL instance over [ ` curl(1) ` ] [ ] :
919
- < https://gist.github.com/TooTallNate/2053342 > .
916
+ This is an example on how to run a "full-featured" (terminal) REPL using
917
+ [ ` net.Server ` ] [ ] and [ ` net.Socket ` ] [ ]
920
918
921
- ** Note** : This example is intended purely for educational purposes to demonstrate how
922
- Node.js REPLs can be started using different I/O streams.
923
- It should ** not** be used in production environments or any context where security
924
- is a concern without additional protective measures.
925
- If you need to implement REPLs in a real-world application, consider alternative
926
- approaches that mitigate these risks, such as using secure input mechanisms and
927
- avoiding open network interfaces.
919
+ The following script starts an HTTP server on port ` 1337 ` that allows
920
+ clients to establish socket connections to its REPL instance.
928
921
922
+ ``` mjs
923
+ // repl-server.js
924
+ import repl from ' node:repl' ;
925
+ import net from ' node:net' ;
926
+
927
+ net
928
+ .createServer ((socket ) => {
929
+ const r = repl .start ({
930
+ prompt: ` socket ${ socket .remoteAddress } :${ socket .remotePort } > ` ,
931
+ input: socket,
932
+ output: socket,
933
+ terminal: true ,
934
+ useGlobal: false ,
935
+ });
936
+ r .on (' exit' , () => {
937
+ socket .end ();
938
+ });
939
+ r .context .socket = socket;
940
+ })
941
+ .listen (1337 );
942
+ ```
943
+
944
+ ``` cjs
945
+ // repl-server.js
946
+ const repl = require (' node:repl' );
947
+ const net = require (' node:net' );
948
+
949
+ net
950
+ .createServer ((socket ) => {
951
+ const r = repl .start ({
952
+ prompt: ` socket ${ socket .remoteAddress } :${ socket .remotePort } > ` ,
953
+ input: socket,
954
+ output: socket,
955
+ terminal: true ,
956
+ useGlobal: false ,
957
+ });
958
+ r .on (' exit' , () => {
959
+ socket .end ();
960
+ });
961
+ r .context .socket = socket;
962
+ })
963
+ .listen (1337 );
964
+ ```
965
+
966
+ While the following implements a client that can create a socket connection
967
+ with the above defined server over port ` 1337 ` .
968
+
969
+ ``` mjs
970
+ // repl-client.js
971
+ import net from ' node:net' ;
972
+ import process from ' node:process' ;
973
+
974
+ const sock = net .connect (1337 );
975
+
976
+ process .stdin .pipe (sock);
977
+ sock .pipe (process .stdout );
978
+
979
+ sock .on (' connect' , () => {
980
+ process .stdin .resume ();
981
+ process .stdin .setRawMode (true );
982
+ });
983
+
984
+ sock .on (' close' , () => {
985
+ process .stdin .setRawMode (false );
986
+ process .stdin .pause ();
987
+ sock .removeListener (' close' , done);
988
+ });
989
+
990
+ process .stdin .on (' end' , () => {
991
+ sock .destroy ();
992
+ console .log ();
993
+ });
994
+
995
+ process .stdin .on (' data' , (b ) => {
996
+ if (b .length === 1 && b[0 ] === 4 ) {
997
+ process .stdin .emit (' end' );
998
+ }
999
+ });
1000
+ ```
1001
+
1002
+ ``` cjs
1003
+ // repl-client.js
1004
+ const net = require (' node:net' );
1005
+
1006
+ const sock = net .connect (1337 );
1007
+
1008
+ process .stdin .pipe (sock);
1009
+ sock .pipe (process .stdout );
1010
+
1011
+ sock .on (' connect' , () => {
1012
+ process .stdin .resume ();
1013
+ process .stdin .setRawMode (true );
1014
+ });
1015
+
1016
+ sock .on (' close' , () => {
1017
+ process .stdin .setRawMode (false );
1018
+ process .stdin .pause ();
1019
+ sock .removeListener (' close' , done);
1020
+ });
1021
+
1022
+ process .stdin .on (' end' , () => {
1023
+ sock .destroy ();
1024
+ console .log ();
1025
+ });
1026
+
1027
+ process .stdin .on (' data' , (b ) => {
1028
+ if (b .length === 1 && b[0 ] === 4 ) {
1029
+ process .stdin .emit (' end' );
1030
+ }
1031
+ });
1032
+ ```
1033
+
1034
+ To run the example open two different terminals on your machine, start the server
1035
+ with ` node repl-server.js ` in one terminal and ` node repl-client.js ` on the other.
1036
+
1037
+ Original code from: [ gist.github.com/TooTallNate/2209310] [ full-featured REPL gist ]
1038
+
1039
+ #### REPL over ` curl `
1040
+
1041
+ This is an example on how to run a REPL instance over [ ` curl() ` ] [ ]
1042
+
1043
+ The following script starts an HTTP server on port ` 8000 ` that can accept
1044
+ a connection established via [ ` curl() ` ] [ ] .
1045
+
1046
+ ``` mjs
1047
+ import http from ' node:http' ;
1048
+ import repl from ' node:repl' ;
1049
+ import { Buffer } from ' node:buffer' ;
1050
+
1051
+ const buf0 = Buffer .from ([0 ]);
1052
+
1053
+ const server = http .createServer ((req , res ) => {
1054
+ res .setHeader (' content-type' , ' multipart/octet-stream' );
1055
+
1056
+ repl .start ({
1057
+ prompt: ' curl repl> ' ,
1058
+ input: req,
1059
+ output: res,
1060
+ terminal: false ,
1061
+ useColors: true ,
1062
+ useGlobal: false ,
1063
+ });
1064
+
1065
+ // Hack to thread stdin and stdout
1066
+ // simultaneously in curl's single thread
1067
+ const iv = setInterval (() => {
1068
+ res .write (buf0);
1069
+ }, 100 );
1070
+
1071
+ req .on (' close' , () => {
1072
+ clearInterval (iv);
1073
+ });
1074
+ });
1075
+ server .listen (8000 );
1076
+ ```
1077
+
1078
+ ``` cjs
1079
+ const http = require (' node:http' );
1080
+ const repl = require (' node:repl' );
1081
+ const buf0 = Buffer .from ([0 ]);
1082
+
1083
+ const server = http .createServer ((req , res ) => {
1084
+ res .setHeader (' content-type' , ' multipart/octet-stream' );
1085
+
1086
+ repl .start ({
1087
+ prompt: ' curl repl> ' ,
1088
+ input: req,
1089
+ output: res,
1090
+ terminal: false ,
1091
+ useColors: true ,
1092
+ useGlobal: false ,
1093
+ });
1094
+
1095
+ // Hack to thread stdin and stdout
1096
+ // simultaneously in curl's single thread
1097
+ const iv = setInterval (() => {
1098
+ res .write (buf0);
1099
+ }, 100 );
1100
+
1101
+ req .on (' close' , () => {
1102
+ clearInterval (iv);
1103
+ });
1104
+ });
1105
+ server .listen (8000 );
1106
+ ```
1107
+
1108
+ When the above script is running you can then use [ ` curl() ` ] [ ] to connect to
1109
+ the server and connect to its REPL instance by running ` curl -sSNT. localhost:8000 `
1110
+
1111
+ ** Warning** This example is intended purely for educational purposes to demonstrate how
1112
+ Node.js REPLs can be started using different I/O streams.
1113
+ It should ** not** be used in production environments or any context where security
1114
+ is a concern without additional protective measures.
1115
+ If you need to implement REPLs in a real-world application, consider alternative
1116
+ approaches that mitigate these risks, such as using secure input mechanisms and
1117
+ avoiding open network interfaces.
1118
+
1119
+ Original code from: [ gist.github.com/TooTallNate/2053342] [ REPL over curl gist ]
1120
+
1121
+ [ REPL over curl gist ] : https://gist.github.com/TooTallNate/2053342
929
1122
[ TTY keybindings ] : readline.md#tty-keybindings
930
1123
[ ZSH ] : https://en.wikipedia.org/wiki/Z_shell
931
1124
[ `'uncaughtException'` ] : process.md#event-uncaughtexception
932
1125
[ `--no-experimental-repl-await` ] : cli.md#--no-experimental-repl-await
933
1126
[ `ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE` ] : errors.md#err_domain_cannot_set_uncaught_exception_capture
934
1127
[ `ERR_INVALID_REPL_INPUT` ] : errors.md#err_invalid_repl_input
935
- [ `curl(1 )` ] : https://curl.haxx.se/docs/manpage.html
1128
+ [ `curl()` ] : https://curl.haxx.se/docs/manpage.html
936
1129
[ `domain` ] : domain.md
937
1130
[ `module.builtinModules` ] : module.md#modulebuiltinmodules
1131
+ [ `net.Server` ] : net.md#class-netserver
1132
+ [ `net.Socket` ] : net.md#class-netsocket
938
1133
[ `process.setUncaughtExceptionCaptureCallback()` ] : process.md#processsetuncaughtexceptioncapturecallbackfn
939
1134
[ `readline.InterfaceCompleter` ] : readline.md#use-of-the-completer-function
940
1135
[ `repl.ReplServer` ] : #class-replserver
941
1136
[ `repl.start()` ] : #replstartoptions
942
1137
[ `reverse-i-search` ] : #reverse-i-search
943
1138
[ `util.inspect()` ] : util.md#utilinspectobject-options
944
1139
[ custom evaluation functions ] : #custom-evaluation-functions
1140
+ [ full-featured REPL gist ] : https://gist.github.com/TooTallNate/2209310
945
1141
[ stream ] : stream.md
0 commit comments