web_plsql 0.12.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -5
- package/examples/config-apex.js +2 -3
- package/examples/config-docker.js +0 -1
- package/examples/config-docker.json +1 -2
- package/examples/config-native.js +2 -3
- package/examples/sql/install.sql +2 -0
- package/examples/sql/sample_package.sql +2 -1
- package/examples/sql/sample_package_body.sql +71 -16
- package/examples/sql/uninstall.sql +2 -0
- package/package.json +9 -11
- package/src/handler/handlerMetrics.js +68 -0
- package/src/{handlerUpload.js → handler/handlerUpload.js} +2 -2
- package/src/{cgi.js → handler/plsql/cgi.js} +6 -2
- package/src/{errorPage.js → handler/plsql/errorPage.js} +5 -5
- package/src/{handlerPlSql.js → handler/plsql/handlerPlSql.js} +2 -2
- package/src/{parsePage.js → handler/plsql/parsePage.js} +24 -8
- package/src/{procedure.js → handler/plsql/procedure.js} +7 -10
- package/src/{procedureError.js → handler/plsql/procedureError.js} +2 -2
- package/src/{procedureNamed.js → handler/plsql/procedureNamed.js} +4 -4
- package/src/{procedureSanitize.js → handler/plsql/procedureSanitize.js} +6 -6
- package/src/{procedureVariable.js → handler/plsql/procedureVariable.js} +3 -3
- package/src/{request.js → handler/plsql/request.js} +3 -9
- package/src/{sendResponse.js → handler/plsql/sendResponse.js} +6 -6
- package/src/{upload.js → handler/plsql/upload.js} +2 -2
- package/src/index.js +8 -9
- package/src/server/config.js +45 -0
- package/src/server/connections.js +40 -0
- package/src/server/server.js +184 -0
- package/src/types.js +2 -13
- package/src/util/date.js +23 -0
- package/src/{shutdown.js → util/shutdown.js} +3 -16
- package/src/util/type.js +6 -0
- package/types/handler/handlerMetrics.d.ts +25 -0
- package/types/{handlerUpload.d.ts → handler/handlerUpload.d.ts} +2 -2
- package/types/{cgi.d.ts → handler/plsql/cgi.d.ts} +2 -2
- package/types/{errorPage.d.ts → handler/plsql/errorPage.d.ts} +3 -3
- package/types/{handlerPlSql.d.ts → handler/plsql/handlerPlSql.d.ts} +2 -2
- package/types/handler/plsql/parsePage.d.ts +3 -0
- package/types/{procedure.d.ts → handler/plsql/procedure.d.ts} +5 -5
- package/types/{procedureError.d.ts → handler/plsql/procedureError.d.ts} +4 -4
- package/types/{procedureNamed.d.ts → handler/plsql/procedureNamed.d.ts} +3 -3
- package/types/{procedureSanitize.d.ts → handler/plsql/procedureSanitize.d.ts} +5 -5
- package/types/{procedureVariable.d.ts → handler/plsql/procedureVariable.d.ts} +3 -3
- package/types/{request.d.ts → handler/plsql/request.d.ts} +2 -2
- package/types/{sendResponse.d.ts → handler/plsql/sendResponse.d.ts} +3 -1
- package/types/{upload.d.ts → handler/plsql/upload.d.ts} +1 -1
- package/types/index.d.ts +8 -9
- package/types/server/config.d.ts +2 -0
- package/types/server/server.d.ts +52 -0
- package/types/types.d.ts +4 -37
- package/types/util/type.d.ts +1 -0
- package/src/handlerMetrics.js +0 -46
- package/src/server.js +0 -223
- package/src/tty.js +0 -48
- package/types/handlerMetrics.d.ts +0 -4
- package/types/parsePage.d.ts +0 -3
- package/types/server.d.ts +0 -14
- package/types/tty.d.ts +0 -4
- /package/src/{handlerLogger.js → handler/handlerLogger.js} +0 -0
- /package/src/{requestError.js → handler/plsql/requestError.js} +0 -0
- /package/src/{stream.js → handler/plsql/stream.js} +0 -0
- /package/src/{error.js → util/errorToString.js} +0 -0
- /package/src/{file.js → util/file.js} +0 -0
- /package/src/{oracle.js → util/oracle.js} +0 -0
- /package/src/{trace.js → util/trace.js} +0 -0
- /package/types/{handlerLogger.d.ts → handler/handlerLogger.d.ts} +0 -0
- /package/types/{requestError.d.ts → handler/plsql/requestError.d.ts} +0 -0
- /package/types/{stream.d.ts → handler/plsql/stream.d.ts} +0 -0
- /package/types/{error.d.ts → util/errorToString.d.ts} +0 -0
- /package/types/{file.d.ts → util/file.d.ts} +0 -0
- /package/types/{oracle.d.ts → util/oracle.d.ts} +0 -0
- /package/types/{shutdown.d.ts → util/shutdown.d.ts} +0 -0
- /package/types/{trace.d.ts → util/trace.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -39,12 +39,12 @@ Please visit the [node-oracledb](https://node-oracledb.readthedocs.io/en/latest/
|
|
|
39
39
|
# Configuration
|
|
40
40
|
|
|
41
41
|
There are 2 options on how to use the web_plsql express middleware:
|
|
42
|
-
- Use the predefined `
|
|
42
|
+
- Use the predefined `startServer` api in `src/server.js` like in the `examples/config-native.js` example
|
|
43
43
|
- Hand craft a new Express server using the `handlerWebPlSql` middleware in `src/handlerPlSql.js`
|
|
44
44
|
|
|
45
|
-
## Use the predefined `
|
|
45
|
+
## Use the predefined `startServer`
|
|
46
46
|
|
|
47
|
-
The `
|
|
47
|
+
The `startServer` api uses the following configuration object:
|
|
48
48
|
|
|
49
49
|
```
|
|
50
50
|
/**
|
|
@@ -80,7 +80,6 @@ export const z$errorStyleType = z.enum(['basic', 'debug']);
|
|
|
80
80
|
* @property {configPlSqlType[]} routePlSql - The PL/SQL routes.
|
|
81
81
|
* @property {errorStyleType} errorStyle - The error style.
|
|
82
82
|
* @property {string} loggerFilename - name of the request logger filename or '' if not required.
|
|
83
|
-
* @property {boolean} monitorConsole - Enable console status monitor.
|
|
84
83
|
*/
|
|
85
84
|
```
|
|
86
85
|
|
|
@@ -138,7 +137,6 @@ The following mod_plsql DAD configuration translates to the configuration option
|
|
|
138
137
|
},
|
|
139
138
|
],
|
|
140
139
|
loggerFilename: 'access.log', // PlsqlLogEnable and PlsqlLogDirectory
|
|
141
|
-
monitorConsole: false,
|
|
142
140
|
}
|
|
143
141
|
```
|
|
144
142
|
|
package/examples/config-apex.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {startServer} from '../src/index.js';
|
|
2
2
|
|
|
3
|
-
void
|
|
3
|
+
void startServer({
|
|
4
4
|
port: 80,
|
|
5
5
|
routeStatic: [
|
|
6
6
|
{
|
|
@@ -22,5 +22,4 @@ void startHttpServer({
|
|
|
22
22
|
},
|
|
23
23
|
],
|
|
24
24
|
loggerFilename: 'access.log',
|
|
25
|
-
monitorConsole: false,
|
|
26
25
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {startServer} from '../src/index.js';
|
|
4
4
|
|
|
5
|
-
void
|
|
5
|
+
void startServer({
|
|
6
6
|
port: 8888,
|
|
7
7
|
routeStatic: [
|
|
8
8
|
{
|
|
@@ -26,5 +26,4 @@ void startHttpServer({
|
|
|
26
26
|
},
|
|
27
27
|
],
|
|
28
28
|
loggerFilename: 'access.log', // PlsqlLogEnable and PlsqlLogDirectory
|
|
29
|
-
monitorConsole: false,
|
|
30
29
|
});
|
package/examples/sql/install.sql
CHANGED
|
@@ -9,8 +9,9 @@ PROCEDURE page_index(p IN VARCHAR2 DEFAULT NULL);
|
|
|
9
9
|
PROCEDURE pag_simple(text IN VARCHAR2 DEFAULT NULL);
|
|
10
10
|
PROCEDURE page_flexible(name_array IN owa.vc_arr, value_array IN owa.vc_arr);
|
|
11
11
|
PROCEDURE page_array(text IN vc_arr);
|
|
12
|
+
PROCEDURE page_slow;
|
|
12
13
|
PROCEDURE page_cgi;
|
|
13
|
-
PROCEDURE page_cookie;
|
|
14
|
+
PROCEDURE page_cookie(p_action IN VARCHAR2 DEFAULT NULL);
|
|
14
15
|
PROCEDURE page_form;
|
|
15
16
|
PROCEDURE page_form_process(firstname IN VARCHAR2 DEFAULT NULL, lastname IN VARCHAR2 DEFAULT NULL, age IN VARCHAR2 DEFAULT NULL, sex IN VARCHAR2 DEFAULT NULL, vehicle IN vc_arr DEFAULT emptyArray);
|
|
16
17
|
PROCEDURE page_file_upload;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
CREATE OR REPLACE
|
|
2
2
|
PACKAGE BODY sample_pkg IS
|
|
3
3
|
|
|
4
|
+
COOKIE_ACTION_REMOVE CONSTANT VARCHAR2(30) := 'REMOVE';
|
|
5
|
+
COOKIE_ACTION_SEND CONSTANT VARCHAR2(30) := 'SEND';
|
|
6
|
+
|
|
7
|
+
COOKIE_NAME_NO_EXPIRES CONSTANT VARCHAR2(30) := 'COOKIE_NO_EXPIRES';
|
|
8
|
+
COOKIE_NAME_ONE_DAY CONSTANT VARCHAR2(30) := 'COOKIE_ONE_DAY';
|
|
9
|
+
|
|
4
10
|
PROCEDURE open_page(title IN VARCHAR2);
|
|
5
11
|
PROCEDURE close_page;
|
|
6
12
|
|
|
@@ -19,6 +25,7 @@ BEGIN
|
|
|
19
25
|
htp.p('<li><a href="sample_pkg.pag_simple?text=some-text">Simple page</a></li>');
|
|
20
26
|
htp.p('<li><a href="sample_pkg.page_array?text=some-text'||CHR(38)||'text=more-text'||CHR(38)||'text=last-text">Array passing</a></li>');
|
|
21
27
|
htp.p('<li><a href="!sample_pkg.page_flexible?p1=v1'||CHR(38)||'p2=v2'||CHR(38)||'p3=v3.1'||CHR(38)||'p3=v3.2"">Flexible parameter passing</a></li>');
|
|
28
|
+
htp.p('<li><a href="sample_pkg.page_slow">Slow page (5 seconds)</a></li>');
|
|
22
29
|
htp.p('<li><a href="sample_pkg.page_cgi">CGI</a></li>');
|
|
23
30
|
htp.p('<li><a href="sample_pkg.page_cookie">Cookies</a></li>');
|
|
24
31
|
htp.p('<li><a href="sample_pkg.page_form">Form</a></li>');
|
|
@@ -40,6 +47,21 @@ BEGIN
|
|
|
40
47
|
close_page();
|
|
41
48
|
END pag_simple;
|
|
42
49
|
|
|
50
|
+
PROCEDURE page_slow
|
|
51
|
+
IS
|
|
52
|
+
l_start TIMESTAMP := SYSTIMESTAMP;
|
|
53
|
+
l_now TIMESTAMP;
|
|
54
|
+
BEGIN
|
|
55
|
+
LOOP
|
|
56
|
+
l_now := SYSTIMESTAMP;
|
|
57
|
+
EXIT WHEN l_now >= l_start + INTERVAL '5' SECOND;
|
|
58
|
+
END LOOP;
|
|
59
|
+
|
|
60
|
+
open_page('web_plsql - Slow page');
|
|
61
|
+
htp.p('<p>I am slow</p>');
|
|
62
|
+
close_page();
|
|
63
|
+
END page_slow;
|
|
64
|
+
|
|
43
65
|
PROCEDURE page_array(text IN vc_arr)
|
|
44
66
|
IS
|
|
45
67
|
BEGIN
|
|
@@ -79,26 +101,56 @@ BEGIN
|
|
|
79
101
|
close_page();
|
|
80
102
|
END page_cgi;
|
|
81
103
|
|
|
82
|
-
PROCEDURE page_cookie
|
|
104
|
+
PROCEDURE page_cookie(p_action IN VARCHAR2 DEFAULT NULL)
|
|
83
105
|
IS
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
l_names owa_cookie.vc_arr;
|
|
107
|
+
l_vals owa_cookie.vc_arr;
|
|
108
|
+
l_num_vals INTEGER;
|
|
87
109
|
BEGIN
|
|
88
|
-
|
|
110
|
+
CASE UPPER(p_action)
|
|
89
111
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
owa_util.http_header_close;
|
|
112
|
+
WHEN COOKIE_ACTION_REMOVE THEN
|
|
113
|
+
owa_util.mime_header('text/html', FALSE);
|
|
93
114
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
owa_cookie.remove(name=>COOKIE_NAME_NO_EXPIRES, val=>'');
|
|
116
|
+
owa_cookie.remove(name=>COOKIE_NAME_ONE_DAY, val=>'');
|
|
117
|
+
|
|
118
|
+
owa_util.redirect_url('sample_pkg.page_cookie');
|
|
119
|
+
owa_util.http_header_close;
|
|
120
|
+
|
|
121
|
+
WHEN COOKIE_ACTION_SEND THEN
|
|
122
|
+
owa_util.mime_header('text/html', FALSE);
|
|
123
|
+
|
|
124
|
+
owa_cookie.send(name=>COOKIE_NAME_NO_EXPIRES, value=>'VALUE-' || TO_CHAR(TRUNC(dbms_random.value(1, 101))));
|
|
125
|
+
owa_cookie.send(name=>COOKIE_NAME_ONE_DAY, value=>'VALUE-' || TO_CHAR(TRUNC(dbms_random.value(1, 101))), expires=>SYSDATE + 1);
|
|
126
|
+
|
|
127
|
+
owa_util.redirect_url('sample_pkg.page_cookie');
|
|
128
|
+
owa_util.http_header_close;
|
|
129
|
+
|
|
130
|
+
ELSE
|
|
131
|
+
owa_cookie.get_all(names=>l_names, vals=>l_vals, num_vals=>l_num_vals);
|
|
132
|
+
|
|
133
|
+
open_page('web_plsql - Cookies');
|
|
134
|
+
|
|
135
|
+
-- actions
|
|
136
|
+
htp.p('<p>');
|
|
137
|
+
htp.p('<form method="POST" action="sample_pkg.page_cookie">');
|
|
138
|
+
htp.p('<input type="submit" name="p_action" value="' || COOKIE_ACTION_REMOVE || '">');
|
|
139
|
+
htp.p('<input type="submit" name="p_action" value="' || COOKIE_ACTION_SEND || '">');
|
|
140
|
+
htp.p('</form>');
|
|
141
|
+
htp.p('</p>');
|
|
142
|
+
|
|
143
|
+
-- show cookies
|
|
144
|
+
htp.p('<table>');
|
|
145
|
+
htp.p('<tr><th>name</th><th>value</th></tr>');
|
|
146
|
+
FOR i IN 1 .. l_num_vals LOOP
|
|
147
|
+
htp.p('<tr><td>'||l_names(i)||'</td><td>'||l_vals(i)||'</td></tr>');
|
|
148
|
+
END LOOP;
|
|
149
|
+
htp.p('</table>');
|
|
150
|
+
|
|
151
|
+
close_page();
|
|
152
|
+
|
|
153
|
+
END CASE;
|
|
102
154
|
END page_cookie;
|
|
103
155
|
|
|
104
156
|
PROCEDURE page_form
|
|
@@ -241,5 +293,8 @@ BEGIN
|
|
|
241
293
|
htp.p('</html>');
|
|
242
294
|
END close_page;
|
|
243
295
|
|
|
296
|
+
BEGIN
|
|
297
|
+
dbms_random.seed(TO_CHAR(SYSDATE,'MM-DD-YYYY HH24:MI:SS'));
|
|
298
|
+
|
|
244
299
|
END sample_pkg;
|
|
245
300
|
/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "web_plsql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"author": "Dieter Oberkofler <dieter.oberkofler@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "The Express Middleware for Oracle PL/SQL",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"test": "node --test --test-concurrency=1 \"./tests/**/*.test.js\"",
|
|
48
48
|
"types": "rm -rf types && tsc --noEmit false --declaration true --declarationDir types --emitDeclarationOnly true --allowJs true --target es2020 --module es2020 --moduleResolution node --allowSyntheticDefaultImports true src/*.js",
|
|
49
49
|
"clean": "shx rm -f *.tgz && shx rm -f *.log",
|
|
50
|
-
"ci": "npm run clean && npm run lint && npm run test",
|
|
50
|
+
"ci": "npm run clean && npm run lint && npm run test && npm run types",
|
|
51
51
|
"create-package": "shx rm -f *.tgz && npm pack",
|
|
52
52
|
"image-build": "docker build --no-cache --progress=plain --tag=web_plsql .",
|
|
53
53
|
"image-save": "docker save web_plsql | gzip > web_plsql.tar.gz"
|
|
@@ -57,22 +57,20 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"basic-auth": "2.0.1",
|
|
60
|
-
"body-parser": "2.2.0",
|
|
61
60
|
"compression": "1.8.1",
|
|
62
61
|
"cookie-parser": "1.4.7",
|
|
63
|
-
"debug": "4.4.
|
|
62
|
+
"debug": "4.4.3",
|
|
64
63
|
"escape-html": "1.0.3",
|
|
65
64
|
"express": "5.1.0",
|
|
66
|
-
"fs-extra": "11.3.
|
|
65
|
+
"fs-extra": "11.3.2",
|
|
67
66
|
"http-parser-js": "0.5.10",
|
|
68
67
|
"morgan": "1.10.1",
|
|
69
68
|
"multer": "2.0.2",
|
|
70
69
|
"rotating-file-stream": "3.2.7",
|
|
71
|
-
"zod": "4.1.
|
|
70
|
+
"zod": "4.1.11"
|
|
72
71
|
},
|
|
73
72
|
"devDependencies": {
|
|
74
73
|
"@types/basic-auth": "1.1.8",
|
|
75
|
-
"@types/body-parser": "1.19.6",
|
|
76
74
|
"@types/compression": "1.8.1",
|
|
77
75
|
"@types/cookie-parser": "1.4.9",
|
|
78
76
|
"@types/debug": "4.1.12",
|
|
@@ -80,16 +78,16 @@
|
|
|
80
78
|
"@types/fs-extra": "11.0.4",
|
|
81
79
|
"@types/morgan": "1.9.10",
|
|
82
80
|
"@types/multer": "2.0.0",
|
|
83
|
-
"@types/node": "24.
|
|
81
|
+
"@types/node": "24.5.2",
|
|
84
82
|
"@types/oracledb": "6.9.1",
|
|
85
83
|
"@types/supertest": "6.0.3",
|
|
86
|
-
"eslint": "9.
|
|
87
|
-
"eslint-plugin-jsdoc": "
|
|
84
|
+
"eslint": "9.36.0",
|
|
85
|
+
"eslint-plugin-jsdoc": "60.1.1",
|
|
88
86
|
"prettier": "3.6.2",
|
|
89
87
|
"rimraf": "6.0.1",
|
|
90
88
|
"shx": "0.4.0",
|
|
91
89
|
"supertest": "7.1.4",
|
|
92
90
|
"typescript": "5.9.2",
|
|
93
|
-
"typescript-eslint": "8.
|
|
91
|
+
"typescript-eslint": "8.44.0"
|
|
94
92
|
}
|
|
95
93
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import debugModule from 'debug';
|
|
2
|
+
const debug = debugModule('webplsql:handlerMetrics');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('express').RequestHandler} RequestHandler
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} metricsType
|
|
10
|
+
* @property {Date} started - When was the server started.
|
|
11
|
+
* @property {number} totalRequests - Total number of requests.
|
|
12
|
+
* @property {number} totalRequestDuration - Total amount of time in ms in request.
|
|
13
|
+
* @property {number} minRequestDuration - Min amount of time in ms in request.
|
|
14
|
+
* @property {number} maxRequestDuration - Max amount of time in ms in request.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Convert hrtime to ms.
|
|
19
|
+
* @param {[number, number]} hrtime - Time
|
|
20
|
+
* @returns {number} Millisecoinds.
|
|
21
|
+
*/
|
|
22
|
+
const hrtime2ms = (hrtime) => hrtime[0] * 1000 + hrtime[1] / 1_000_000;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* metrics initializer.
|
|
26
|
+
* @returns {metricsType} The metrics.
|
|
27
|
+
*/
|
|
28
|
+
export const initMetrics = () => {
|
|
29
|
+
return {
|
|
30
|
+
started: new Date(),
|
|
31
|
+
totalRequests: 0,
|
|
32
|
+
totalRequestDuration: 0,
|
|
33
|
+
minRequestDuration: -1,
|
|
34
|
+
maxRequestDuration: -1,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The metrics handler.
|
|
40
|
+
* @param {metricsType} metrics - the nmetrics.
|
|
41
|
+
* @returns {RequestHandler} - Request handler.
|
|
42
|
+
*/
|
|
43
|
+
export const handlerMetrics = (metrics) => {
|
|
44
|
+
debug('register');
|
|
45
|
+
|
|
46
|
+
return (req, res, next) => {
|
|
47
|
+
metrics.totalRequests++;
|
|
48
|
+
|
|
49
|
+
const start = hrtime2ms(process.hrtime());
|
|
50
|
+
res.on('finish', () => {
|
|
51
|
+
const duration = hrtime2ms(process.hrtime()) - start;
|
|
52
|
+
|
|
53
|
+
metrics.totalRequestDuration += duration;
|
|
54
|
+
if (metrics.minRequestDuration < 0 || duration < metrics.minRequestDuration) {
|
|
55
|
+
metrics.minRequestDuration = duration;
|
|
56
|
+
}
|
|
57
|
+
if (metrics.maxRequestDuration < 0 || duration > metrics.maxRequestDuration) {
|
|
58
|
+
metrics.maxRequestDuration = duration;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (debug.enabled) {
|
|
62
|
+
debug(`Request to ${req.params?.name} ${req.url} took ${duration.toFixed(3)}ms`);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
next();
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -6,8 +6,8 @@ import multer from 'multer';
|
|
|
6
6
|
* @typedef {import('express').Response} Response
|
|
7
7
|
* @typedef {import('express').NextFunction} NextFunction
|
|
8
8
|
* @typedef {import('oracledb').Pool} Pool
|
|
9
|
-
* @typedef {import('
|
|
10
|
-
* @typedef {import('
|
|
9
|
+
* @typedef {import('../types.js').environmentType} environmentType
|
|
10
|
+
* @typedef {import('../types.js').configType} configType
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import {URL} from 'node:url';
|
|
7
|
+
import debugModule from 'debug';
|
|
8
|
+
const debug = debugModule('webplsql:cgi');
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* @typedef {import('express').Request} Request
|
|
10
|
-
* @typedef {import('
|
|
11
|
-
* @typedef {import('
|
|
12
|
+
* @typedef {import('../../types.js').environmentType} environmentType
|
|
13
|
+
* @typedef {import('../../types.js').configPlSqlType} configPlSqlType
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
/** @type {environmentType} */
|
|
@@ -57,6 +59,8 @@ const getCookieString = (req) => {
|
|
|
57
59
|
cookieString += `${propName}=${req.cookies[propName]};`;
|
|
58
60
|
}
|
|
59
61
|
|
|
62
|
+
debug('getCookieString', req.cookies, cookieString);
|
|
63
|
+
|
|
60
64
|
return cookieString;
|
|
61
65
|
};
|
|
62
66
|
|
|
@@ -6,15 +6,15 @@ import util from 'node:util';
|
|
|
6
6
|
import escape from 'escape-html';
|
|
7
7
|
import {ProcedureError} from './procedureError.js';
|
|
8
8
|
import {RequestError} from './requestError.js';
|
|
9
|
-
import {inspectRequest, logToFile} from '
|
|
10
|
-
import {errorToString} from '
|
|
9
|
+
import {inspectRequest, logToFile} from '../../util/trace.js';
|
|
10
|
+
import {errorToString} from '../../util/errorToString.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @typedef {import('express').Request} Request
|
|
14
14
|
* @typedef {import('express').Response} Response
|
|
15
|
-
* @typedef {import('
|
|
16
|
-
* @typedef {import('
|
|
17
|
-
* @typedef {import('
|
|
15
|
+
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
16
|
+
* @typedef {import('../../types.js').environmentType} environmentType
|
|
17
|
+
* @typedef {import('../../types.js').configPlSqlHandlerType} configPlSqlHandlerType
|
|
18
18
|
* @typedef {{html: string; text: string}} outputType
|
|
19
19
|
*/
|
|
20
20
|
|
|
@@ -16,8 +16,8 @@ import {errorPage} from './errorPage.js';
|
|
|
16
16
|
* @typedef {import('express').Response} Response
|
|
17
17
|
* @typedef {import('express').NextFunction} NextFunction
|
|
18
18
|
* @typedef {import('oracledb').Pool} Pool
|
|
19
|
-
* @typedef {import('
|
|
20
|
-
* @typedef {import('
|
|
19
|
+
* @typedef {import('../../types.js').environmentType} environmentType
|
|
20
|
+
* @typedef {import('../../types.js').configPlSqlHandlerType} configPlSqlHandlerType
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import debugModule from 'debug';
|
|
2
|
+
const debug = debugModule('webplsql:parsePage');
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
* @typedef {import('
|
|
3
|
-
* @typedef {import('
|
|
5
|
+
* @typedef {import('../../types.js').pageType} pageType
|
|
6
|
+
* @typedef {import('../../types.js').cookieType} cookieType
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
/**
|
|
@@ -42,6 +45,7 @@ export const parsePage = (text) => {
|
|
|
42
45
|
// 2) parse the headers
|
|
43
46
|
//
|
|
44
47
|
|
|
48
|
+
debug('parsing the headers received from PL/SQL');
|
|
45
49
|
head.split('\n').forEach((line) => {
|
|
46
50
|
const header = getHeader(line);
|
|
47
51
|
|
|
@@ -50,15 +54,19 @@ export const parsePage = (text) => {
|
|
|
50
54
|
case 'set-cookie':
|
|
51
55
|
{
|
|
52
56
|
const cookie = parseCookie(header.value);
|
|
57
|
+
debug(`oracle header "set-cookie" with value "${header.value}" was received has been parsed to ${JSON.stringify(cookie)}`);
|
|
53
58
|
/* istanbul ignore else */
|
|
54
59
|
if (cookie !== null) {
|
|
55
60
|
page.head.cookies.push(cookie);
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error(`Unable to parse header "set-cookie" with value "${header.value}" received from PL/SQL`);
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
break;
|
|
59
66
|
|
|
60
67
|
case 'content-type':
|
|
61
68
|
page.head.contentType = header.value;
|
|
69
|
+
debug(`oracle header "content-type" with value "${page.head.contentType}" was parsed`);
|
|
62
70
|
break;
|
|
63
71
|
|
|
64
72
|
case 'x-db-content-length':
|
|
@@ -67,6 +75,9 @@ export const parsePage = (text) => {
|
|
|
67
75
|
/* istanbul ignore else */
|
|
68
76
|
if (!Number.isNaN(contentLength)) {
|
|
69
77
|
page.head.contentLength = contentLength;
|
|
78
|
+
debug(`oracle header "x-db-content-length" with value "${page.head.contentLength}" was parsed`);
|
|
79
|
+
} else {
|
|
80
|
+
throw new Error(`Unable to parse header "x-db-content-length" with value "${header.value}" received from PL/SQL`);
|
|
70
81
|
}
|
|
71
82
|
}
|
|
72
83
|
break;
|
|
@@ -77,17 +88,21 @@ export const parsePage = (text) => {
|
|
|
77
88
|
/* istanbul ignore else */
|
|
78
89
|
if (!Number.isNaN(statusCode)) {
|
|
79
90
|
page.head.statusCode = statusCode;
|
|
91
|
+
debug(`oracle header "status" with value "${page.head.statusCode}" was parsed`);
|
|
80
92
|
const index = header.value.indexOf(' ');
|
|
81
93
|
/* istanbul ignore else */
|
|
82
94
|
if (index !== -1) {
|
|
83
95
|
page.head.statusDescription = header.value.substring(index + 1);
|
|
84
96
|
}
|
|
97
|
+
} else {
|
|
98
|
+
throw new Error(`Unable to parse header "status" with value "${header.value}" received from PL/SQL`);
|
|
85
99
|
}
|
|
86
100
|
}
|
|
87
101
|
break;
|
|
88
102
|
|
|
89
103
|
case 'location':
|
|
90
104
|
page.head.redirectLocation = header.value;
|
|
105
|
+
debug(`oracle header "location" with value "${page.head.statusCode}" was parsed`);
|
|
91
106
|
break;
|
|
92
107
|
|
|
93
108
|
case 'x-oracle-ignore':
|
|
@@ -151,27 +166,28 @@ const parseCookie = (text) => {
|
|
|
151
166
|
const cookie = {
|
|
152
167
|
name: cookieElements[0].substring(0, index).trim(),
|
|
153
168
|
value: cookieElements[0].substring(index + 1).trim(),
|
|
169
|
+
options: {},
|
|
154
170
|
};
|
|
155
171
|
|
|
156
|
-
// remove the
|
|
172
|
+
// remove the first element
|
|
157
173
|
cookieElements.shift();
|
|
158
174
|
|
|
159
175
|
// get the other options
|
|
160
176
|
cookieElements.forEach((element) => {
|
|
161
177
|
if (element.startsWith('path=')) {
|
|
162
|
-
cookie.path = element.substring(5);
|
|
178
|
+
cookie.options.path = element.substring(5);
|
|
163
179
|
} else if (element.toLowerCase().startsWith('domain=')) {
|
|
164
|
-
cookie.domain = element.substring(7);
|
|
180
|
+
cookie.options.domain = element.substring(7);
|
|
165
181
|
} else if (element.toLowerCase().startsWith('secure=')) {
|
|
166
182
|
/* istanbul ignore next */
|
|
167
|
-
cookie.secure =
|
|
183
|
+
cookie.options.secure = true;
|
|
168
184
|
} else if (element.toLowerCase().startsWith('expires=')) {
|
|
169
185
|
const date = tryDecodeDate(element.substring(8));
|
|
170
186
|
if (date) {
|
|
171
|
-
cookie.expires = date;
|
|
187
|
+
cookie.options.expires = date;
|
|
172
188
|
}
|
|
173
189
|
} else if (element.toLowerCase().startsWith('httponly')) {
|
|
174
|
-
cookie.httpOnly = true;
|
|
190
|
+
cookie.options.httpOnly = true;
|
|
175
191
|
}
|
|
176
192
|
});
|
|
177
193
|
|
|
@@ -16,19 +16,19 @@ import {getProcedureNamed} from './procedureNamed.js';
|
|
|
16
16
|
import {parsePage} from './parsePage.js';
|
|
17
17
|
import {sendResponse} from './sendResponse.js';
|
|
18
18
|
import {ProcedureError} from './procedureError.js';
|
|
19
|
-
import {inspect, getBlock} from '
|
|
20
|
-
import {errorToString} from '
|
|
19
|
+
import {inspect, getBlock} from '../../util/trace.js';
|
|
20
|
+
import {errorToString} from '../../util/errorToString.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* @typedef {import('express').Request} Request
|
|
24
24
|
* @typedef {import('express').Response} Response
|
|
25
25
|
* @typedef {import('oracledb').Connection} Connection
|
|
26
26
|
* @typedef {import('oracledb').Result<unknown>} Result
|
|
27
|
-
* @typedef {import('
|
|
28
|
-
* @typedef {import('
|
|
29
|
-
* @typedef {import('
|
|
30
|
-
* @typedef {import('
|
|
31
|
-
* @typedef {import('
|
|
27
|
+
* @typedef {import('../../types.js').argObjType} argObjType
|
|
28
|
+
* @typedef {import('../../types.js').fileUploadType} fileUploadType
|
|
29
|
+
* @typedef {import('../../types.js').environmentType} environmentType
|
|
30
|
+
* @typedef {import('../../types.js').configPlSqlHandlerType} configPlSqlHandlerType
|
|
31
|
+
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -215,9 +215,6 @@ export const invokeProcedure = async (req, res, argObj, cgiObj, filesToUpload, o
|
|
|
215
215
|
|
|
216
216
|
// combine page
|
|
217
217
|
const pageContent = data.lines.join('');
|
|
218
|
-
if (debug.enabled && pageContent.length > 0) {
|
|
219
|
-
debug(getBlock('PLAIN CONTENT', pageContent));
|
|
220
|
-
}
|
|
221
218
|
|
|
222
219
|
//
|
|
223
220
|
// 6) PARSE PAGE
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* @typedef {import('
|
|
7
|
-
* @typedef {import('
|
|
6
|
+
* @typedef {import('../../types.js').environmentType} environmentType
|
|
7
|
+
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
export class ProcedureError extends Error {
|
|
@@ -9,7 +9,7 @@ import oracledb from 'oracledb';
|
|
|
9
9
|
import z from 'zod';
|
|
10
10
|
import {sanitizeProcName} from './procedureSanitize.js';
|
|
11
11
|
import {RequestError} from './requestError.js';
|
|
12
|
-
import {errorToString} from '
|
|
12
|
+
import {errorToString} from '../../util/errorToString.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @typedef {Record<string, string>} argsType
|
|
@@ -19,9 +19,9 @@ import {errorToString} from './error.js';
|
|
|
19
19
|
/**
|
|
20
20
|
* @typedef {import('oracledb').Connection} Connection
|
|
21
21
|
* @typedef {import('oracledb').Result<unknown>} Result
|
|
22
|
-
* @typedef {import('
|
|
23
|
-
* @typedef {import('
|
|
24
|
-
* @typedef {import('
|
|
22
|
+
* @typedef {import('../../types.js').configPlSqlHandlerType} configPlSqlHandlerType
|
|
23
|
+
* @typedef {import('../../types.js').argObjType} argObjType
|
|
24
|
+
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
const SQL_GET_ARGUMENT = [
|
|
@@ -4,18 +4,18 @@ const debug = debugModule('webplsql:procedureSanitize');
|
|
|
4
4
|
import oracledb from 'oracledb';
|
|
5
5
|
import z from 'zod';
|
|
6
6
|
import {RequestError} from './requestError.js';
|
|
7
|
-
import {errorToString} from '
|
|
7
|
+
import {errorToString} from '../../util/errorToString.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @typedef {import('express').Request} Request
|
|
11
11
|
* @typedef {import('express').Response} Response
|
|
12
12
|
* @typedef {import('oracledb').Connection} Connection
|
|
13
13
|
* @typedef {import('oracledb').Result<unknown>} Result
|
|
14
|
-
* @typedef {import('
|
|
15
|
-
* @typedef {import('
|
|
16
|
-
* @typedef {import('
|
|
17
|
-
* @typedef {import('
|
|
18
|
-
* @typedef {import('
|
|
14
|
+
* @typedef {import('../../types.js').argObjType} argObjType
|
|
15
|
+
* @typedef {import('../../types.js').fileUploadType} fileUploadType
|
|
16
|
+
* @typedef {import('../../types.js').environmentType} environmentType
|
|
17
|
+
* @typedef {import('../../types.js').configPlSqlHandlerType} configPlSqlHandlerType
|
|
18
|
+
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
const DEFAULT_EXCLUSION_LIST = ['sys.', 'dbms_', 'utl_', 'owa_', 'htp.', 'htf.', 'wpg_docload.', 'ctxsys.', 'mdsys.'];
|
|
@@ -11,9 +11,9 @@ import {sanitizeProcName} from './procedureSanitize.js';
|
|
|
11
11
|
/**
|
|
12
12
|
* @typedef {import('oracledb').Connection} Connection
|
|
13
13
|
* @typedef {import('oracledb').Result<unknown>} Result
|
|
14
|
-
* @typedef {import('
|
|
15
|
-
* @typedef {import('
|
|
16
|
-
* @typedef {import('
|
|
14
|
+
* @typedef {import('../../types.js').configPlSqlHandlerType} configPlSqlHandlerType
|
|
15
|
+
* @typedef {import('../../types.js').argObjType} argObjType
|
|
16
|
+
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|