Azure Function connecting SQL server with blank page in browser - node.js

I am new to Azure Function and nodejs.
I have a very simple azure function which connects to SQL server by using Azure Function with nodejs. I use the package named "tedious" to connection to SQL server which hosted in Azure. The connection works fine as I can see the result in my Terminal panel in Visual Studio Code by using "context.log" when put the URL "http://localhost:7071/api/Company" into my browser. However, i see nothing in my browser.
I suspect that the "return" called before the function "queryDatabase" is completed but i have no clue how to do this. Any advice?
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var rows = [];
var config = {
userName: 'xxx',
password: 'xxx',
server: 'xxx',
options: {encrypt: true, database: 'xxx'}
};
var res = {};
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var str = "";
var connection = new Connection(config);
var querystatus = "";
connection.on('connect', function(err) {
if(err) {
context.log(err);
//context.res = {body : err};
} else {
context.log("************Connected*****************");
//context.res = {body : "Hello!"};
queryDatabase(connection);
// context.res = {
// body: "Connected"
// };
//context.done();
}
});
context.log("************BEFORE context.res*****************");
return {
body:rows.toString()
};
function queryDatabase(connection) {
context.log("queryDatabase....started!");
var request = new Request(
"SELECT [id],[CompanyName] ,[CreatedDate] FROM [dbo].[Company]",
function(err, rowCount, rows)
{
context.log(rowCount + ' row(s) returned');
//context.log("Final Result:" + str);
}
);
request.on('row', function(columns) {
var row = {};
columns.forEach(function(column) {
context.log("%s\t%s", column.metadata.colName, column.value);
row[column.metadata.colName] = column.value;
});
rows.push(row);
});
connection.execSql(request);
}
};

Finally, I remove the "async " and add a context.done after the result is returned from sql server.

Related

Lambda NodeJS works intermittent with async method

I have a lambda function written in node.js. The lambda logic is to extract secrets from aws secret manager and pass the params to another module with a token to make a soap call.This lambda was working as expected without async method to get secreats when secreats hardcoded.
But after adding an async getsecrets method the lambda works intermittently while testing in aws console. The getsecreats returns params every time. But the lambda terminates without the intended output. It doesn't make any soap call.
The logic of the lambda code is
Get the secret
Pass the secret to the CallServicewithToken()
get XML data from soap and populate it into the database.
Why it works intermittently when introducing async calls? I have tried introducing async to all methods. still the same issue. Appreciate any input/help.
The code is as below
'use strict';
var soap = require('strong-soap').soap;
const aws = require("aws-sdk");
const request = require('request');
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
var rfcUrl = process.env.rfcser_url;
var testUrl = process.env.faccser_url;
var region = process.env.region;
var secretName = process.env.secretName;
var oauthurl = process.env.oauthurl;
var rfcRequestArgs;
var parsedResult;
var tokenrequest;
exports.handler = async function(event, context,callback) {
const secret = await getSecrets();
CallServicewithToken();
};
async function getSecrets() {
const config = { region : region, apiVersion: 'latest' };
let secretManager = new aws.SecretsManager(config);
const Result = await secretManager.getSecretValue({ SecretId: secretName }).promise();
parsedResult = JSON.parse(Result.SecretString);
tokenrequest = {
url: oauthurl,
form: {
client_id: parsedResult.client_id,
client_secret: parsedResult.client_secret,
grant_type:'client_credentials',
scope:parsedResult.scope
}
};
console.log('client_id: ' + parsedResult.client_id);
console.log('client_secret: ' + parsedResult.client_secret);
console.log('testservice_userid: ' + parsedResult.testservice_userid);
}
function CallServicewithToken() {
console.log('Calling CallServicewithToken ');
request.post(tokenrequest, (err, res, body) => {
if (err) {
console.log(' error2: ' + err);
return;
}
rfcRequestArgs = {
UserName: parsedResult.service_username
};
var tokenobj = JSON.parse(body);
var token = 'Bearer '+ tokenobj.access_token;
var credentials = {
Authorization:{
AuthToken: token
}
}
var options = {};
console.log('Calling Service.');
soap.createClient(rfcUrl, options, function(err, client) {
client.addSoapHeader(
`<aut:Authorization xmlns:aut="http://soap.xyznet.net">
<aut:AuthToken>${token}</aut:AuthToken>
</aut:Authorization>`
);
var method = client['GetSourceLocationData'];
method(RequestArgs, function(err, result, envelope, soapHeader) {
if (err) {
console.log('error3: ' + err);
return;
}
else
{
console.log('Received response from GetSourceLocationData().');
CallTESTService(JSON.stringify(result));
}
});
function CallTESTService(LocData)
{
var testRequestArgs = {
UserID: parsedResult.testservice_userid,
AuthorizationKey: parsedResult.testservice_authorizationkey,
LocationData: LocData
};
console.log('Calling test Service.');
options = {};
soap.createClient(testUrl, options, function(err, client) {
client.addSoapHeader(
`<Authorization xmlns="testWebService">
<AuthToken>${token}</AuthToken>
</Authorization>`
);
var test_method = client['UpdateLocationData'];
console.log('Called UpdateLocationData service method.');
test_method(testRequestArgs, function(err, result, envelope, soapHeader) {
if(err) {
console.log('test error: ' + err);
return;
}
else
{
console.log('Response: \n' + JSON.stringify(result));
console.log('Data updated through test service method.');
}
});
});
}
});
});
}

Node js writing bulk xml data to SQL Server

Need some assistance in node.js. Trying to update about 6000+ records into SQL Server. The records size maybe 5 to 10 MB. The xml records will be sent to the stored procedure which has a nvarchar(max) parameter. I am fetching records from a soap API call and push to SQL Server via a stored procedure.
I get an error when I run the below code if the record size is beyond 2000 in xml object. What is best way to send large xml objects of 5 to 10k to a SQL Server stored procedure?
Any nodejs library to handle this? Can nodejs handle such large records update ?
Note: this code will run inside aws lambda
var soap = require("strong-soap").soap;
var rfcUrl = https://xxxxxxxx/xxxx/xxxxx/xxxxx.asmx?WSDL;
var rfcRequestArgs = {
UserName:
Password:
};
var options = {};
console.log("Calling ervice...\n");
soap.createClient(rfcUrl, options, function(err, client) {
var method = client["GetLocationData"];
method(rfcRequestArgs, function(err, result, envelope, soapHeader) {
if(err) {
console.log('error: ' + err);
return;
}
else
{
//'result' is the response body
console.log('RFC Result: \n');
InitializeSQLConnection(JSON.stringify(result));
}
});
});
var connection = null;
function InitializeSQLConnection(LocData)
{
var Connection = require('tedious').Connection;
var config = {
server: 'ddddddddd', //update me
authentication: {
type: 'default',
options: {
userName: 'xxxxxxx', //update me
password: 'xxxxxxx' //update me
}
} ,
options: {
// If you are on Microsoft Azure, you need encryption:
encrypt: false,
database: 'DBName' //update me
}
};
connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log('SQL Connection Failed!');
console.log(err);
throw err;
}
// If no error, then good to proceed.
console.log("SQL Server Connected");
executeStoredProcedure(LocData);
});
connection.connect();
}
function executeStoredProcedure(LocData)
{
console.log("calling executeStoredProcedure");
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
var loadTestState = 0;
var request = new Request('spname_new', function(err) {
connection.close();
});
request.addParameter('parameterrecords', TYPES.NVarChar, LocData);
request.addOutputParameter('returnVal', TYPES.Int);
request.on('returnValue', (paramName, value, metadata) => {
console.log(paramName + ' : ' + value);
});
connection.callProcedure(request);
console.log("Called SP");
}
'''

Accessing Azure Synapse Analytics from Node.js Function

I am trying to access an Azure Synapse SQL Pool out of a Node.js Function. I took this article as a foundation and switch the authentication method to 'azure-active-directory-msi-app-service'.
If I run the function I can see the queryText context.log in the Function cmd but unfortunately nothing else happens. It runs without any kind of output.
I cant see any other context.log or get any response from the function.
const Request = require('tedious').Request;
const TYPES = require('tedious').TYPES;
const test = require('lodash')
module.exports = function (context, req) {
//get the Query Parameter
// Create connection to database
const config = {
authentication: {
type: "azure-active-directory-msi-app-service"
},
server: "database.sql.azuresynapse.net",
options: {
database: "database",
encrypt: true,
port: 1433
}
};
const connection = new Connection(config);
// Create array to store the query results
let result = [];
let rowData = {};
// req.query.color will be passed as a query variable in the URL
//const payload = [req.query.color];
// Create query to execute against the database
const queryText = "SELECT TOP (10) [id],[column1],[column2] FROM [dbo].[Table]";
context.log(queryText);
// Create Request object
request = new Request(queryText, function(err) {
context.log("Request")
if (err) {
// Error in executing query
context.log.error(err);
context.res.status = 500;
context.res.body = "Error executing the query";
} else {
context.res = {
status: 200,
isRaw: true,
body: result,
headers: {
'Content-Type': 'application/json'
}
}
}
context.done();
});
// Manipulate the results and create JSON
request.on('row', function(columns) {
rowData = {};
columns.forEach(function(column) {
// IMPORTANT: Change the conversion logic here to adjust JSON format
rowData[column.metadata.colName] = column.value;
});
result.push(rowData);
});
connection.on('connect', function(err) {
if (err) {
// Error in connecting
context.log.error(err);
context.res.status = 500;
context.res.body = "Error connecting to Azure Synapase";
context.done();
} else {
// Connection succeeded
connection.execSql(request);
}
});
}```
This should work...
const Connection = require('tedious').Connection;
const Request = require('tedious').Request;
const TYPES = require('tedious').TYPES;
const config = {
server: "SQL pool endpoint goes here",
authentication: {
type: "azure-active-directory-msi-app-service"
},
options: {
encrypt: true,
database: "pool name goes here",
port: 1433
}
}
var connection = new Connection(config);
This assumes that you appropriately assigned managed identities as external users in the SQL pool. I also have a PR for this change which you can track here

SQL select all statement in a node.js application returns a tedious deprecated error

So I went to the Microsoft documentation for node.js and trying to connect to a database and I went through step by step, installed tedious and when I try to run my code it's throwing an error saying:
tedious deprecated In the next major version of tedious, creating a new Connection instance will no longer establish a connection to the server automatically. Please use the new connect helper function or call the .connect method on the newly created Connection object to silence this message. internal\process\task_queues.js:79:11.
Does anyone know what this means?
CODE:
const Discord = require('discord.js');
const bot = new Discord.Client();
const token = 'HIDDEN';
bot.on('ready', () => {
console.log('This bot is online!');
var Connection = require('tedious').Connection;
var config = {
server: '', //update me
authentication: {
type: 'default',
options: {
userName: '', //update me
password: '' //update me
}
},
options: {
// If you are on Microsoft Azure, you need encryption:
encrypt: true,
database: '' //update me
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
// If no error, then good to proceed.
if(!err)
{
console.log("Connected");
executeStatement();
}
});
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement() {
request = new Request("SELECT * from tblCustomer;", function(err) {
if (err) {
console.log(err);}
});
var result = "";
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
result+= column.value + " ";
}
});
console.log(result);
result ="";
});
request.on('done', function(rowCount, more) {
console.log(rowCount + ' rows returned');
});
connection.execSql(request);
}
})
bot.login(token);

How to connect with SQL Server in windows authentication mode using node.js

I want to connect SQL Server in a windows authentication mode using node.js with "mssql" package. Below code is working fine with SQL Server authentication by providing username & password.
var sql = require("mssql");
// config for your database
var config = {
server: XXXX',
database: 'XXX' ,
options: {
trustedconnection:true,
encrypt: false, // Use this if you're on Windows Azure
}
};
function GetDatatable()
{
return new Promise( (resolve, reject) => {
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
var query='select Id,statusCode,from test';
request.query(query, function (err, recordset) {
var recordSetItem = recordset.recordset;
for(var i=0;i<recordSetItem.length;i++) {
var row=recordSetItem[i];
var basePath=row['baseUri'];
if(fullPath.lastIndexOf(basePath) > -1)
{
operationId=row['Id'];
}
}
if(operationId)
{
query='select * from tbltest';
request.query(query, function (err, scenarioRecordset) {
var subRecordSet = scenarioRecordset.recordset;
var xmlResponse= validateScenario (subRecordSet,fullPath,bodyRequest);
console.log(xmlResponse);
// let responseObject = {
// "id": "1",
// "statusCode": "200"
// };
resolve('responseObject');
});
}
});
});
});
Getting error message "login failed"
I believe you'll need to use the msnodesqlv8 module, you must install with
npm install msnodesqlv8
Then (for example):
const sql = require('mssql/msnodesqlv8')
const pool = new sql.ConnectionPool({
database: 'database',
server: 'localhost',
options: {
trustedConnection: true
}
})
async function testConnection() {
await pool.connect();
let result = await pool.request().query("select 42 as the_answer_to_life_the_universe_and_everything");
console.log("Result: ", result);
}
testConnection();
See here for more: mssql v8driver

Resources