web_plsql 0.5.0 → 0.6.0
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 +123 -110
- package/examples/server_apex.js +28 -0
- package/examples/server_sample.js +30 -0
- package/examples/sql/{doc_table.sql → doctable.sql} +1 -1
- package/examples/sql/install.sql +6 -9
- package/examples/sql/sample_package.sql +27 -0
- package/examples/sql/sample_package_body.sql +245 -0
- package/examples/static/sample.css +11 -10
- package/package.json +90 -83
- package/src/cgi.js +127 -0
- package/src/error.js +24 -0
- package/src/errorPage.js +296 -0
- package/src/file.js +77 -0
- package/src/handlerLogger.js +21 -0
- package/src/handlerMetrics.js +46 -0
- package/src/handlerPlSql.js +65 -0
- package/src/handlerUpload.js +32 -0
- package/src/index.js +17 -0
- package/src/oracle.js +80 -0
- package/src/parsePage.js +193 -0
- package/src/procedure.js +260 -0
- package/src/procedureError.js +40 -0
- package/src/procedureNamed.js +233 -0
- package/src/procedureSanitize.js +215 -0
- package/src/procedureVariable.js +57 -0
- package/src/request.js +103 -0
- package/src/{requestError.ts → requestError.js} +8 -4
- package/src/sendResponse.js +104 -0
- package/src/server.js +106 -0
- package/src/shutdown.js +53 -0
- package/src/stream.js +28 -0
- package/src/trace.js +74 -0
- package/src/tty.js +48 -0
- package/src/types.js +146 -0
- package/src/upload.js +92 -0
- package/src/version.js +23 -0
- package/types/cgi.d.ts +4 -0
- package/types/error.d.ts +1 -0
- package/types/errorPage.d.ts +10 -0
- package/types/file.d.ts +5 -0
- package/types/handlerLogger.d.ts +2 -0
- package/types/handlerMetrics.d.ts +4 -0
- package/types/handlerPlSql.d.ts +8 -0
- package/types/handlerUpload.d.ts +7 -0
- package/types/index.d.ts +10 -0
- package/types/oracle.d.ts +5 -0
- package/types/parsePage.d.ts +3 -0
- package/types/procedure.d.ts +10 -0
- package/types/procedureError.d.ts +23 -0
- package/types/procedureNamed.d.ts +14 -0
- package/types/procedureSanitize.d.ts +14 -0
- package/types/procedureVariable.d.ts +9 -0
- package/types/request.d.ts +7 -0
- package/types/requestError.d.ts +8 -0
- package/types/sendResponse.d.ts +4 -0
- package/types/server.d.ts +7 -0
- package/types/shutdown.d.ts +2 -0
- package/types/stream.d.ts +1 -0
- package/types/trace.d.ts +5 -0
- package/types/tty.d.ts +4 -0
- package/types/types.d.ts +251 -0
- package/types/upload.d.ts +5 -0
- package/types/version.d.ts +7 -0
- package/.editorconfig +0 -8
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -347
- package/CHANGELOG.md +0 -127
- package/examples/apex.js +0 -70
- package/examples/credentials.js +0 -22
- package/examples/oracledb_example.js +0 -30
- package/examples/sample.js +0 -101
- package/examples/sql/sample.pkb +0 -223
- package/examples/sql/sample.pks +0 -24
- package/jest.config.js +0 -204
- package/src/cgi.ts +0 -95
- package/src/config.ts +0 -97
- package/src/errorPage.ts +0 -286
- package/src/fileUpload.ts +0 -126
- package/src/index.ts +0 -65
- package/src/page.ts +0 -275
- package/src/procedure.ts +0 -360
- package/src/procedureError.ts +0 -27
- package/src/request.ts +0 -139
- package/src/stream.ts +0 -26
- package/src/trace.ts +0 -194
- package/test/.eslintrc.json +0 -5
- package/test/__tests__/cgi.ts +0 -96
- package/test/__tests__/config.ts +0 -41
- package/test/__tests__/errorPage.ts +0 -101
- package/test/__tests__/oracledb_mock.ts +0 -98
- package/test/__tests__/server.ts +0 -495
- package/test/__tests__/stream.ts +0 -21
- package/test/mock/oracledb.ts +0 -85
- package/test/static/static.html +0 -1
- package/tsconfig.json +0 -24
- package/tsconfig.src.json +0 -23
package/src/fileUpload.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Process file uploads
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import express from 'express';
|
|
8
|
-
import oracledb from 'oracledb';
|
|
9
|
-
|
|
10
|
-
export type fileUploadType = {
|
|
11
|
-
fieldValue: string;
|
|
12
|
-
filename: string;
|
|
13
|
-
physicalFilename: string;
|
|
14
|
-
encoding: string;
|
|
15
|
-
mimetype: string;
|
|
16
|
-
size: number;
|
|
17
|
-
};
|
|
18
|
-
export type filesUploadType = Array<fileUploadType>;
|
|
19
|
-
|
|
20
|
-
let sequencialID = 0;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get the files
|
|
24
|
-
*
|
|
25
|
-
* @param {express.Request} req - The req object represents the HTTP request.
|
|
26
|
-
* @returns {Promise<filesUploadType>} - Promise that resolves with an array of files to be uploaded.
|
|
27
|
-
*/
|
|
28
|
-
export function getFiles(req: express.Request): filesUploadType {
|
|
29
|
-
interface TCustomRequest extends express.Request {
|
|
30
|
-
files: Array<any>;
|
|
31
|
-
}
|
|
32
|
-
const customRequest = req as TCustomRequest;
|
|
33
|
-
const files: filesUploadType = [];
|
|
34
|
-
|
|
35
|
-
// are there any files
|
|
36
|
-
/* istanbul ignore next */
|
|
37
|
-
if (typeof customRequest.files !== 'object') {
|
|
38
|
-
return files;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// process the files
|
|
42
|
-
for (const key in customRequest.files) {
|
|
43
|
-
const file = customRequest.files[key];
|
|
44
|
-
|
|
45
|
-
/* istanbul ignore else */
|
|
46
|
-
if (typeof file.originalFilename === 'string' && file.originalFilename.length > 0) {
|
|
47
|
-
// get a temporary filename
|
|
48
|
-
const filename = getRandomizedFilename(file.originalFilename);
|
|
49
|
-
|
|
50
|
-
// Add the field
|
|
51
|
-
file.filename = filename;
|
|
52
|
-
|
|
53
|
-
// Add the file to upload
|
|
54
|
-
files.push({
|
|
55
|
-
fieldValue: file.fieldName,
|
|
56
|
-
filename: file.originalFilename,
|
|
57
|
-
physicalFilename: path.normalize(path.resolve(file.path)),
|
|
58
|
-
encoding: '',
|
|
59
|
-
mimetype: file.type,
|
|
60
|
-
size: file.size
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return files;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Upload the given array of files and return a promise that resolves when all uploads have been finished.
|
|
70
|
-
*
|
|
71
|
-
* @param {Array<string>} files - array of file path's.
|
|
72
|
-
* @param {string} docTableName - name of the oracle table holding the uploaded files.
|
|
73
|
-
* @param {oracledb.Connection} databaseConnection - Database connection.
|
|
74
|
-
* @returns {Promise<void>} - Promise that resolves when the request has been fullfilled.
|
|
75
|
-
*/
|
|
76
|
-
export async function uploadFiles(files: filesUploadType, docTableName: string, databaseConnection: oracledb.Connection): Promise<void> {
|
|
77
|
-
await Promise.all(files.map(file => uploadFile(file, docTableName, databaseConnection)));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/*
|
|
81
|
-
* Upload the given file and return a promise.
|
|
82
|
-
*/
|
|
83
|
-
export function uploadFile(file: fileUploadType, docTableName: string, databaseConnection: oracledb.Connection): Promise<void> {
|
|
84
|
-
return new Promise((resolve, reject) => {
|
|
85
|
-
/* istanbul ignore next */
|
|
86
|
-
if (typeof docTableName !== 'string' || docTableName.length === 0) {
|
|
87
|
-
reject(new Error('The option "docTableName" has not been defined or the name is empty'));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
let blobContent;
|
|
91
|
-
try {
|
|
92
|
-
blobContent = fs.readFileSync(file.physicalFilename);
|
|
93
|
-
} catch (err) {
|
|
94
|
-
/* istanbul ignore next */
|
|
95
|
-
reject(new Error(`Unable to read file "${file.physicalFilename}"\n${err instanceof Error ? err.toString() : ''}`));
|
|
96
|
-
/* istanbul ignore next */
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const sql = `INSERT INTO ${docTableName} (name, mime_type, doc_size, dad_charset, last_updated, content_type, blob_content) VALUES (:name, :mime_type, :doc_size, 'ascii', SYSDATE, 'BLOB', :blob_content)`;
|
|
101
|
-
const bind = {
|
|
102
|
-
name: file.fieldValue,
|
|
103
|
-
mime_type: file.mimetype,
|
|
104
|
-
doc_size: file.size,
|
|
105
|
-
blob_content: {
|
|
106
|
-
val: blobContent,
|
|
107
|
-
type: oracledb.BUFFER
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
databaseConnection.execute(sql, bind, {autoCommit: true})
|
|
112
|
-
.then(() => {
|
|
113
|
-
resolve();
|
|
114
|
-
}).catch(/* istanbul ignore next */(e: any) => {
|
|
115
|
-
reject(new Error(`Unable to insert file "${file.physicalFilename}"\n` + e.toString()));
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/*
|
|
121
|
-
* get a randomized filename
|
|
122
|
-
*/
|
|
123
|
-
function getRandomizedFilename(filename: string): string {
|
|
124
|
-
++sequencialID;
|
|
125
|
-
return 'F' + (Date.now() + sequencialID).toString() + '/' + path.basename(filename);
|
|
126
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Express middleware for Oracle PL/SQL
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import url from 'url';
|
|
6
|
-
import express from 'express';
|
|
7
|
-
import oracledb from 'oracledb';
|
|
8
|
-
import {processRequest} from './request';
|
|
9
|
-
import {validate, oracleExpressMiddleware$options} from './config';
|
|
10
|
-
import {RequestError} from './requestError';
|
|
11
|
-
import {errorPage} from './errorPage';
|
|
12
|
-
import {Trace} from './trace';
|
|
13
|
-
const version = require('../package.json').version; // eslint-disable-line @typescript-eslint/no-var-requires
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Express middleware.
|
|
17
|
-
*
|
|
18
|
-
* @param {Promise<oracledb.Pool>} databasePoolPromise - The promise that will be fullfilled when the database pool has been allocated.
|
|
19
|
-
* @param {Object} options - The configuration options.
|
|
20
|
-
* @returns {Function} - The request handler.
|
|
21
|
-
*/
|
|
22
|
-
const webplsql = function (databasePoolPromise: Promise<oracledb.Pool>, options: oracleExpressMiddleware$options) {
|
|
23
|
-
// validate the configuration options
|
|
24
|
-
const validOptions = validate(options);
|
|
25
|
-
|
|
26
|
-
// instantiate trace object
|
|
27
|
-
const trace = new Trace(validOptions.trace);
|
|
28
|
-
|
|
29
|
-
return function handler(req: express.Request, res: express.Response/*, next: () => void*/) {
|
|
30
|
-
requestHandler(req, res, databasePoolPromise, validOptions, trace);
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
webplsql.version = version;
|
|
35
|
-
exports = module.exports = webplsql;
|
|
36
|
-
|
|
37
|
-
/*
|
|
38
|
-
* express.Request handler
|
|
39
|
-
*/
|
|
40
|
-
function requestHandler(req: express.Request, res: express.Response, databasePoolPromise: Promise<oracledb.Pool>, options: oracleExpressMiddleware$options, trace: Trace) {
|
|
41
|
-
try {
|
|
42
|
-
trace.start(req);
|
|
43
|
-
|
|
44
|
-
// should we switch to the default page if there is one defined
|
|
45
|
-
if (typeof req.params.name !== 'string' || req.params.name.length === 0) {
|
|
46
|
-
if (typeof options.defaultPage === 'string' && options.defaultPage.length > 0) {
|
|
47
|
-
const newUrl = url.resolve(req.originalUrl + '/' + options.defaultPage, '');
|
|
48
|
-
trace.write(`Redirect to the url "${newUrl}"`);
|
|
49
|
-
res.redirect(newUrl);
|
|
50
|
-
} else {
|
|
51
|
-
/* istanbul ignore next */
|
|
52
|
-
errorPage(req, res, options, trace, new RequestError('No procedure name given and no default page has been specified'));
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
processRequest(req, res, options, databasePoolPromise, trace)
|
|
56
|
-
.catch(e => {
|
|
57
|
-
/* istanbul ignore next */
|
|
58
|
-
errorPage(req, res, options, trace, e);
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
} catch (err) {
|
|
62
|
-
/* istanbul ignore next */
|
|
63
|
-
errorPage(req, res, options, trace, err);
|
|
64
|
-
}
|
|
65
|
-
}
|
package/src/page.ts
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Page the raw page content and return the content to the client
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {Trace} from './trace';
|
|
6
|
-
import express from 'express';
|
|
7
|
-
|
|
8
|
-
type cookieType = {
|
|
9
|
-
name: string;
|
|
10
|
-
value: string;
|
|
11
|
-
path?: string;
|
|
12
|
-
domain?: string;
|
|
13
|
-
secure?: string;
|
|
14
|
-
expires?: Date;
|
|
15
|
-
httpOnly?: boolean;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
type pageType = {
|
|
19
|
-
body: string;
|
|
20
|
-
head: {
|
|
21
|
-
cookies: Array<cookieType>;
|
|
22
|
-
contentType?: string;
|
|
23
|
-
contentLength?: number;
|
|
24
|
-
statusCode?: number;
|
|
25
|
-
statusDescription?: string;
|
|
26
|
-
redirectLocation?: string;
|
|
27
|
-
otherHeaders: Record<string, unknown>;
|
|
28
|
-
server?: string;
|
|
29
|
-
};
|
|
30
|
-
file: {
|
|
31
|
-
fileType: any;
|
|
32
|
-
fileSize: any;
|
|
33
|
-
fileBlob: any;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Parse the header and split it up into the individual components
|
|
39
|
-
*
|
|
40
|
-
* @param {string} text - The text returned from the PL/SQL procedure.
|
|
41
|
-
* @returns {Object} - The parsed page.
|
|
42
|
-
*/
|
|
43
|
-
export function parse(text: string): pageType {
|
|
44
|
-
const page: pageType = {
|
|
45
|
-
body: '',
|
|
46
|
-
head: {
|
|
47
|
-
cookies: [],
|
|
48
|
-
otherHeaders: {}
|
|
49
|
-
},
|
|
50
|
-
file: {
|
|
51
|
-
fileType: null,
|
|
52
|
-
fileSize: null,
|
|
53
|
-
fileBlob: null
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
// 1) Split up the text in header and body
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
// Find the end of the header identified by \n\n
|
|
62
|
-
let head = '';
|
|
63
|
-
const headerEndPosition = text.indexOf('\n\n');
|
|
64
|
-
if (headerEndPosition === -1) {
|
|
65
|
-
head = text;
|
|
66
|
-
} else {
|
|
67
|
-
head = text.substring(0, headerEndPosition + 2);
|
|
68
|
-
page.body = text.substring(headerEndPosition + 2);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
//
|
|
72
|
-
// 2) parse the headers
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
head.split('\n').forEach(line => {
|
|
76
|
-
const header = getHeader(line);
|
|
77
|
-
|
|
78
|
-
if (header) {
|
|
79
|
-
switch (header.name.toLowerCase()) {
|
|
80
|
-
case 'set-cookie':
|
|
81
|
-
{
|
|
82
|
-
const cookie = parseCookie(header.value);
|
|
83
|
-
/* istanbul ignore else */
|
|
84
|
-
if (cookie !== null) {
|
|
85
|
-
page.head.cookies.push(cookie);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
|
|
90
|
-
case 'content-type':
|
|
91
|
-
page.head.contentType = header.value;
|
|
92
|
-
break;
|
|
93
|
-
|
|
94
|
-
case 'x-db-content-length':
|
|
95
|
-
{
|
|
96
|
-
const contentLength = parseInt(header.value, 10);
|
|
97
|
-
/* istanbul ignore else */
|
|
98
|
-
if (!Number.isNaN(contentLength)) {
|
|
99
|
-
page.head.contentLength = contentLength;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
break;
|
|
103
|
-
|
|
104
|
-
case 'status':
|
|
105
|
-
{
|
|
106
|
-
const statusCode = parseInt(header.value, 10);
|
|
107
|
-
/* istanbul ignore else */
|
|
108
|
-
if (!Number.isNaN(statusCode)) {
|
|
109
|
-
page.head.statusCode = statusCode;
|
|
110
|
-
const index = header.value.indexOf(' ');
|
|
111
|
-
/* istanbul ignore else */
|
|
112
|
-
if (index !== -1) {
|
|
113
|
-
page.head.statusDescription = header.value.substr(index + 1);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
break;
|
|
118
|
-
|
|
119
|
-
case 'location':
|
|
120
|
-
page.head.redirectLocation = header.value;
|
|
121
|
-
break;
|
|
122
|
-
|
|
123
|
-
case 'x-oracle-ignore':
|
|
124
|
-
break;
|
|
125
|
-
|
|
126
|
-
default:
|
|
127
|
-
page.head.otherHeaders[header.name] = header.value;
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
return page;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/*
|
|
137
|
-
* get a header line
|
|
138
|
-
*/
|
|
139
|
-
function getHeader(line: string): {name: string; value: string} | null {
|
|
140
|
-
const index = line.indexOf(':');
|
|
141
|
-
|
|
142
|
-
if (index !== -1) {
|
|
143
|
-
return {
|
|
144
|
-
name: line.substr(0, index).trim(),
|
|
145
|
-
value: line.substr(index + 1).trim()
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/*
|
|
153
|
-
* Send "default" response to the browser
|
|
154
|
-
*/
|
|
155
|
-
export function send(req: express.Request, res: express.Response, page: {body: string; head: any; file: any}, trace: Trace): void {
|
|
156
|
-
trace.write('send: ENTER');
|
|
157
|
-
|
|
158
|
-
// Send the "cookies"
|
|
159
|
-
page.head.cookies.forEach((cookie: Record<string, unknown>) => {
|
|
160
|
-
const name = cookie.name as string;
|
|
161
|
-
const value = cookie.value as string;
|
|
162
|
-
|
|
163
|
-
delete cookie.name;
|
|
164
|
-
delete cookie.value;
|
|
165
|
-
|
|
166
|
-
res.cookie(name, value, cookie);
|
|
167
|
-
trace.append(`send: res.cookie("${name}", "${value}")\n`);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// If there is a "redirectLocation" header, we immediately redirect and return
|
|
171
|
-
if (typeof page.head.redirectLocation === 'string' && page.head.redirectLocation.length > 0) {
|
|
172
|
-
res.redirect(302, page.head.redirectLocation);
|
|
173
|
-
trace.append(`send: res.redirect(302, "${page.head.redirectLocation}")\n`);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Send all the "otherHeaders"
|
|
178
|
-
for (const key in page.head.otherHeaders) {
|
|
179
|
-
res.set(key, page.head.otherHeaders[key]);
|
|
180
|
-
trace.append(`send: res.set("${key}", "${page.head.otherHeaders[key]}")\n`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// If this is a file download, we eventually set the "Content-Type" and the file content and then return.
|
|
184
|
-
if (page.file.fileType === 'B' || page.file.fileType === 'F') {
|
|
185
|
-
if (typeof page.head.contentType === 'string' && page.head.contentType.length > 0) {
|
|
186
|
-
res.writeHead(200, {'Content-Type': page.head.contentType});
|
|
187
|
-
trace.append(`sendFile: res.writeHead("Content-Type", "${page.head.contentType}")\n`);
|
|
188
|
-
}
|
|
189
|
-
res.end(page.file.fileBlob, 'binary');
|
|
190
|
-
trace.append('send: res.end()\n');
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Is the a "contentType" header
|
|
195
|
-
if (typeof page.head.contentType === 'string' && page.head.contentType.length > 0) {
|
|
196
|
-
res.set('Content-Type', page.head.contentType);
|
|
197
|
-
trace.append(`send: res.set("Content-Type", "${page.head.contentType}")\n`);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// If we have a "Status" header, we send the header and then return.
|
|
201
|
-
if (typeof page.head.statusCode === 'number') {
|
|
202
|
-
res.status(page.head.statusCode).send(page.head.statusDescription);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Send the body
|
|
207
|
-
res.send(page.body);
|
|
208
|
-
trace.append(`send: res.send\n${'-'.repeat(30)}${page.body}\n${'-'.repeat(30)}\n`);
|
|
209
|
-
|
|
210
|
-
trace.write('send: EXIT');
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/*
|
|
214
|
-
* Parses a cookie string
|
|
215
|
-
*/
|
|
216
|
-
function parseCookie(text: string): cookieType | null {
|
|
217
|
-
// validate
|
|
218
|
-
/* istanbul ignore next */
|
|
219
|
-
if (typeof text !== 'string' || text.trim().length === 0) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// split the cookie into it's parts
|
|
224
|
-
let cookieElements = text.split(';');
|
|
225
|
-
|
|
226
|
-
// trim cookie elements
|
|
227
|
-
cookieElements = cookieElements.map(element => element.trim());
|
|
228
|
-
|
|
229
|
-
// get name and value
|
|
230
|
-
const index = cookieElements[0].indexOf('=');
|
|
231
|
-
/* istanbul ignore next */
|
|
232
|
-
if (index <= 0) {
|
|
233
|
-
// if the index is -1, there is no equal sign and if it's 0 the name is empty
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
const cookie: any = {};
|
|
237
|
-
cookie.name = cookieElements[0].substring(0, index).trim();
|
|
238
|
-
cookie.value = cookieElements[0].substring(index + 1).trim();
|
|
239
|
-
|
|
240
|
-
// remove the fisrt element
|
|
241
|
-
cookieElements.shift();
|
|
242
|
-
|
|
243
|
-
// get the other options
|
|
244
|
-
cookieElements.forEach(element => {
|
|
245
|
-
if (element.indexOf('path=') === 0) {
|
|
246
|
-
cookie.path = element.substring(5);
|
|
247
|
-
} else if (element.toLowerCase().indexOf('domain=') === 0) {
|
|
248
|
-
cookie.domain = element.substring(7);
|
|
249
|
-
} else if (element.toLowerCase().indexOf('secure=') === 0) {
|
|
250
|
-
/* istanbul ignore next */
|
|
251
|
-
cookie.secure = element.substring(7);
|
|
252
|
-
} else if (element.toLowerCase().indexOf('expires=') === 0) {
|
|
253
|
-
const date = tryDecodeDate(element.substring(8));
|
|
254
|
-
if (date) {
|
|
255
|
-
cookie.expires = date;
|
|
256
|
-
}
|
|
257
|
-
} else if (element.toLowerCase().indexOf('httponly') === 0) {
|
|
258
|
-
cookie.httpOnly = true;
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
return cookie;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/*
|
|
266
|
-
* Decode a date
|
|
267
|
-
*/
|
|
268
|
-
function tryDecodeDate(value: string): Date | null {
|
|
269
|
-
try {
|
|
270
|
-
return new Date(value);
|
|
271
|
-
} catch (err) {
|
|
272
|
-
/* istanbul ignore next */
|
|
273
|
-
return null;
|
|
274
|
-
}
|
|
275
|
-
}
|