Skip to content

Commit

Permalink
added cookie support for Node.js requests
Browse files Browse the repository at this point in the history
  • Loading branch information
VladimirHot committed Feb 5, 2025
1 parent c8586dd commit 8b8b517
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 21 deletions.
40 changes: 25 additions & 15 deletions scripts/stimulsoft.handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@ StiHandler.prototype.send = function (data, callback) {
request.open('post', this.url, true);
request.setRequestHeader('Cache-Control', 'max-age=0, no-cache, no-store, must-revalidate');
request.setRequestHeader('Pragma', 'no-cache');
let csrf_token = {csrf_token} || Stimulsoft.handler.getCookie('csrftoken');
if (csrf_token) {
request.setRequestHeader('X-CSRFToken', csrf_token);
request.setRequestHeader('X-CSRF-Token', csrf_token);

if (this.cookie)
request.setRequestHeader('Cookie', this.cookie);

if (this.csrfToken) {
request.setRequestHeader('X-CSRFToken', this.csrfToken);
request.setRequestHeader('X-CSRF-Token', this.csrfToken);
}

request.timeout = this.timeout * 1000;
request.onload = function () {
if (request.status === 200) {
Expand Down Expand Up @@ -99,15 +103,21 @@ StiHandler.prototype.https = function (data, callback) {
timeout: this.timeout * 1000,
headers: {
'Cache-Control': 'max-age=0, no-cache, no-store, must-revalidate',
'Pragma': 'no-cache'
'Pragma': 'no-cache',
'Cookie': this.cookie,
'X-CSRFToken': this.csrfToken,
'X-CSRF-Token': this.csrfToken
}
}

let responseText = '';
let request = require(uri.protocol.replace(':', '')).request(options, function (response) {
let module = uri.protocol.replace(':', '');
let request = require(module).request(options, function (response) {

response.on('data', function (buffer) {
responseText += buffer;
});

response.on('end', function () {
try {
let args = Stimulsoft.Report.Dictionary.StiSqlAdapterService.decodeCommandResult(responseText);
Expand All @@ -120,29 +130,27 @@ StiHandler.prototype.https = function (data, callback) {
callback(args);
}
catch (e) {
console.log('RequestError: ' + e.message);
console.log('ResponseError: ' + e.message);
console.log(responseText);
process.exit(1);
}
});
});

request.on('error', function (e) {
console.log('RequestError: ' + e.message);
})
process.exit(1);
});

request.on('timeout', function () {
console.log('RequestError: Timeout ' + this.timeout + 'ms');
})
process.exit(2);
});

request.write(data);
request.end();
}

StiHandler.prototype.getCookie = function (name) {
if (typeof document == 'undefined') return '';
let matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"));
return matches ? decodeURIComponent(matches[1]) : '';
}

StiHandler.prototype.setOptions = function () {
Stimulsoft.Report.StiOptions.WebServer.timeout = this.timeout;
Stimulsoft.Report.StiOptions.WebServer.encryptData = this.encryptData;
Expand Down Expand Up @@ -185,6 +193,8 @@ function StiHandler() {
this.escapeQueryParameters = {escapeQueryParameters};
this.databases = {databases};
this.frameworkType = {framework};
this.cookie = {cookie};
this.csrfToken = {csrfToken};
this.setOptions();
}

Expand Down
18 changes: 16 additions & 2 deletions src/classes/StiHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class StiHandler extends StiBaseHandler
/** @var bool Enables server-side file name checking for saving the report to eliminate dangerous values. */
public $checkFileNames = true;

/** @var string Contains a string with cookies that will be passed when requesting events. */
public $cookie = null;


### Events: Component

Expand Down Expand Up @@ -316,6 +319,17 @@ private function updateOptions()
StiFunctions::populateObject($this, $this->options);
}

private function getCsrfToken()
{
if (function_exists('csrf_token'))
return csrf_token();

if (array_key_exists('csrftoken', $_COOKIE))
return $_COOKIE['csrftoken'];

return null;
}


### Results

Expand Down Expand Up @@ -409,19 +423,19 @@ private function getJavaScript()
{
$result = StiResourcesHelper::getResult('stimulsoft.handler.js');
if ($result->success) {
$csrf_token = function_exists('csrf_token') ? csrf_token() : null;
$script = $result->data ?? '';

// Replace Handler parameters
$script = str_replace('{databases}', StiFunctions::getJavaScriptValue(StiDatabaseType::getValues()), $script);
$script = str_replace('{csrf_token}', StiFunctions::getJavaScriptValue($csrf_token), $script);
$script = str_replace('{url}', StiFunctions::getJavaScriptValue($this->getUrl()), $script);
$script = str_replace('{timeout}', StiFunctions::getJavaScriptValue($this->timeout), $script);
$script = str_replace('{encryptData}', StiFunctions::getJavaScriptValue($this->encryptData), $script);
$script = str_replace('{passQueryParametersToReport}', StiFunctions::getJavaScriptValue($this->passQueryParametersToReport), $script);
$script = str_replace('{checkDataAdaptersVersion}', StiFunctions::getJavaScriptValue($this->checkDataAdaptersVersion), $script);
$script = str_replace('{escapeQueryParameters}', StiFunctions::getJavaScriptValue($this->escapeQueryParameters), $script);
$script = str_replace('{framework}', StiFunctions::getJavaScriptValue('PHP'), $script);
$script = str_replace('{cookie}', StiFunctions::getJavaScriptValue($this->cookie), $script);
$script = str_replace('{csrfToken}', StiFunctions::getJavaScriptValue($this->getCsrfToken()), $script);

if (StiHandler::$legacyMode)
$script = str_replace(
Expand Down
27 changes: 23 additions & 4 deletions src/classes/StiNodeJs.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class StiNodeJs
/** @var array Full text of the last error as an array of strings. */
public $errorStack;

/** @var bool Enables automatic passing of cookies in HTTP requests. */
public $passCookies = true;


### Parameters

Expand Down Expand Up @@ -108,10 +111,24 @@ private static function getHandlerUrl($url): string {
return "$protocol://$host/$url";
}

private function getCookieString()
{
if ($this->passCookies) {
if (array_key_exists('HTTP_COOKIE', $_SERVER))
return $_SERVER['HTTP_COOKIE'];

if (count($_COOKIE) > 0)
return http_build_query($_COOKIE, '', '; ');
}

return null;
}

private function getHandlerScript(): string
{
$handler = $this->getHandler();
$handler->url = self::getHandlerUrl($handler->getUrl());
$handler->cookie = $this->getCookieString();
$script = $handler->getHtml(StiHtmlMode::Scripts);
return str_replace("Stimulsoft.handler.send", "Stimulsoft.handler.https", $script);
}
Expand All @@ -129,7 +146,7 @@ private function getNodeError($returnError, int $returnCode)
{
$lines = is_array($returnError) ? $returnError : explode("\n", $returnError ?? "");
$npmError = false;
$errors = ["npm ERR", "Error", "SyntaxError", "ReferenceError", "TypeError", "RequestError"];
$errors = ["npm ERR", "Error", "SyntaxError", "ReferenceError", "TypeError", "RequestError", "ResponseError"];
foreach ($lines as $line) {
if (!StiFunctions::isNullOrEmpty($line)) {
foreach ($errors as $error) {
Expand Down Expand Up @@ -472,10 +489,11 @@ public function run(string $script)

$errorText = !StiFunctions::isNullOrEmpty($error) ? $error : $output;
$this->error = $this->getNodeError($errorText, $result);
$this->errorStack = $this->getNodeErrorStack($errorText);

if (!StiFunctions::isNullOrEmpty($this->error))
if (!StiFunctions::isNullOrEmpty($this->error)) {
$this->errorStack = $this->getNodeErrorStack($errorText);
return false;
}

if (!StiFunctions::isNullOrEmpty($output)) {
try {
Expand All @@ -499,6 +517,7 @@ public function run(string $script)
}
catch (Exception $e) {
$this->error = "ParseError: " . $e->getMessage();
$this->errorStack = $this->getNodeErrorStack($errorText);
return false;
}
}
Expand All @@ -518,4 +537,4 @@ public function __construct(StiComponent $component = null)
$this->architecture = $this->getArchitecture();
$this->workingDirectory = getcwd();
}
}
}

0 comments on commit 8b8b517

Please sign in to comment.