I'm creating APIs with Express.js and SQL Server. I been posting an object which is easy and very simple, but now i have a new question: how to post an array?
Let's say i have a table which stores only two params:
Table_A
Id | CouponId
In fact, the only record that stores is CouponId, 'cause the Id is created by SQL Server on every record. So, the case is that i get a list of coupons from an api, and the idea is select from one to 'n' with a checkbox and save the selection.
This my code so far:
function getList(){
$http.get('/api/coupons')
.then(function(data){
$scope.infoCoupons = data.data.Response;
}
On the HTML view:
<div class="col-lg-12" align="center">
<input type="checkbox" ng-click="selectAll()"/> <a style="font-size:17px;color:black;text-decoration:none;">Select all coupons</a>
<ul class="coupon-list">
<li ng-repeat="coupon in infoCoupons">
<input type="checkbox" ng-model="coupon.Select" ng-click="checked"/> <a style="font-size:17px;color:black;text-decoration:none;">{{coupon.CodeCoupon}}</a>
</li>
</ul>
</div>
Then, to get the selected coupons:
$scope.selectAll = function(){
$scope.all = !$scope.all;
$scope.infoCoupons.forEach(function(o){
o.Select = $scope.all;
});
}
function chosenCoupons(){
var result = new Array();
var checked = 0;
$scope.infoCoupons.forEach(function(e){
if(e.Select === true){
result.push(e.Id);
checked +=1;
}
});
if($scope.all || checked > 0){
alert("Selected coupons!");
}
else if(checked === 0){
alert("Select at least one coupon");
}
}
Then, my code for the API:
const express = require('express');
const bodyParser = require('body-parser');
const sql = require('mssql');
const app = express();
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, contentType,Content-Type, Accept, Authorization");
next();
});
const dbConfig = {
user: "daUser",
password: "daPass",
server: "daServa",
database: "daDB"
};
const executeQuery = function (res, query, parameters) {
sql.connect(dbConfig, function (err) {
if (err) {
console.log(`There's an error: ${err}`);
res.send(err);
sql.close();
}
else {
var request = new sql.Request();
if (parameters && parameters.length > 0) {
parameters.forEach(function (p) {
request.input(p.name, p.sqltype, p.value);
});
}
request.query(query, function (err, result) {
if (err) {
console.log(`Theres an error: ${err}`);
res.send(err);
sql.close();
}
else {
res.send(result);
sql.close();
}
});
}
});
}
app.post("/api/testApi", function(req, res){
parameters = [
{ name: 'CouponId', sqltype: sql.VarChar, value: req.body.CouponId }
];
var query = "INSERT INTO [Table_A] VALUES(#CouponId)";
executeQuery(res, query, parameters);
});
const PORT = process.env.PORT || 8080
app.listen(PORT, () => {
console.log(`App running on port ${PORT}`)
});
This is the code that usually works for an object. My question is: how can i send result (where result is the obtained array) on the API. I need to change something on my code on parameters?
Hope you can help me. I'm using Javascript, Node, Express and SQL Server.
How to post an array to Express API
In angular you simply do $http.post(url, data).
If you assign data to an object that has an array, it will reach express.
Then express can parse the body since you have app.use(express.bodyParser()); so the object should be available to you on the body.
URL Query Params
If you are trying to use query parameters, to pass an array, lets say on attribute items so you simply declare it multiple times
items=1&items=2&items=3 should be parsed to req.query.items === [1,2,3]
Related
greeting kings
i have api request that have cors problem. I'm able to solve by using proxy setup using nodejs. Unfortunately im trying to pass certain query parameter from my main js to app.js(nodejs proxy) so my api can have certain value from main js. How to solve this or should point me where should i read more.below is my code
main js
const inputValue = document.querySelector('input').value
//this value is maybeline
app.js(node.js proxy)
const express = require('express')
const request = require('request');
const app = express()
app.use((req,res,next)=>{
res.header('Access-Control-Allow-Origin', '*');
next();
})
app.get('/api', (req, res) => {
request(
{ url: 'https://makeup-api.herokuapp.com/api/v1/products.json?brand=covergirl' },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: err.message });
}
res.json(JSON.parse(body));
}
)
});
const port = process.env.PORT || 5500
app.listen(5500,()=>console.log(`listening ${port}`))
I want to pass inputValue as query to api in app.js
as
https://makeup-api.herokuapp.com/api/v1/products.json?brand=${type}
How to do it or point me any direction?
note:this api work withour cors problem.This is an example api..tq
You can use stringify method from qs module.
const { stringify } = require("qs");
app.get("/api", (req, res) => {
request(
{
url: `https://makeup-api.herokuapp.com/api/v1/products.json?${stringify(
req.params
)}`,
}
/// Rest of the code
);
});
I am trying to build a web app that allows a user to press a button and translate a piece of text using the Bing translator api. I try to run a translator.js file through a script tag but I of course cannot run this node.js code through the client html page. What would be the proper way to design this app. Is my only choice to use something such as requirejs? I also have an app.js file built using express from which I run the app. Sorry for posting a lot of code, I want to give people an idea of the structure of my app. My experience is limited so I am feeling somewhat lost as to how to approach the design of this portion of the app. I don't expect anyone to write the code for me, but to just point in a direction of techniques that I could research so that I could build this properly.
Here is my Node.js translation request called translator.js
const request = require('request');
const uuidv4 = require('uuid/v4');
var key_var = 'TRANSLATOR_TEXT_SUBSCRIPTION_KEY';
if (!process.env[key_var]) {
throw new Error('Please set/export the following environment variable: ' + key_var);
}
var subscriptionKey = process.env[key_var];
var endpoint_var = 'TRANSLATOR_TEXT_ENDPOINT';
if (!process.env[endpoint_var]) {
throw new Error('Please set/export the following environment variable: ' + endpoint_var);
}
var endpoint = process.env[endpoint_var];
let options = {
method: 'POST',
baseUrl: endpoint,
url: 'translate',
qs: {
'api-version': '3.0',
'to': ['en']
},
headers: {
'Ocp-Apim-Subscription-Key': subscriptionKey,
'Content-type': 'application/json',
'X-ClientTraceId': uuidv4().toString()
},
body: [{
'text': 'hallo welt'
}],
json: true,
};
function displayBingTranslate() {
request(options, function(err, res, body){
document.querySelector("#bingTranslateOutput") = JSON.stringify(body, null, 4);
});
};
var accessBingTranslate = document.getElementById("accessBingTranslateButton");
accessBingTranslate.addEventListener("click", function() {
displayBingTranslate();
});
And here is my html
<!-- Section to view online translation -->
<div class="container">
<div class="row">
<div class="col-lg-12 p-0">
<button
class="btn btn-outline-dark btn-sm mb-1"
id = "accessBingTranslateButton">Translate Flashcard</button>
<div class="row m-0 p-0">
<div id="bingTranslateOutput" class="col-lg-12 m-0">
</div>
<script>
// Overall list of flashcards.
var flashcardList = {
flashcards: [],
// Adds a flashcard object to Flashcard array.
addFlashcard: function(fcTextQuestion, fcTextTranslated) {
this.flashcards.push({
fcTextQuestion: fcTextQuestion,
fcTextTranslated: fcTextTranslated
});
},
};
// Add flashcards on load.
var flashcardsDB = <%- JSON.stringify(flashcardsDB) %>;
console.log("the DB:", flashcardsDB);
flashcardsDB.forEach(function(fcardDbToAdd){
flashcardList.addFlashcard(fcardDbToAdd.question, fcardDbToAdd.translation);
});
document.querySelector("#displayFlashcardTotal").textContent = flashcardList.flashcards.length;
console.log("the rest:",flashcardList.flashcards);
var currentFlashcard = 0;
</script>
<script src="/scripts/translator.js"></script>
</body>
</html>
and here is my app.js
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var mongoose = require("mongoose");
var methodOverride = require("method-override");
// Fix mongoose deprecations
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('useUnifiedTopology', true);
// Connect to database.
var url = "///////";
mongoose.connect(url, {
useNewUrlParser: true,
useCreateIndex: true,
}).then(() => {
console.log("connected to mongoDB");
}).catch(err => {
console.log("Error:", err.message);
});
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(__dirname + '/public'));
// Set 'views' directory for any views
// being rendered res.render()
app.set("view engine", "ejs");
// Override HTTP verbs if necessary.
app.use(methodOverride("_method"));
var flashcardSchema = new mongoose.Schema ({
question: String,
translation: String
});
//creates model with above schema and has methods such as .find etc.
var Flashcard = mongoose.model("Flashcard", flashcardSchema);
app.get('/', (req, res) => {
Flashcard.find({}, function(err, allFlashcards){
if(err){
console.log(err);
} else {
res.render("home", {flashcardsDB: allFlashcards});
}
});
});
// Post to an input action
app.post("/flashcards", function(req, res) {
var question = req.body.question;
var translation = req.body.translation;
var newFlashcard = {question: question, translation: translation};
console.log(newFlashcard);
Flashcard.create(newFlashcard, function(err, newlyCreated){
if(err){
console.log(err);
} else {
res.redirect("/flashcards");
}
});
});
// Show info.
app.get("/info",function (req, res) {
res.render("info");
});
// Show all flashcards
app.get("/flashcards", function(req, res){
Flashcard.find({}, function(err, allFlashcards){
if(err){
console.log(err);
} else {
res.render("flashcards", {flashcards: allFlashcards});
}
});
});
// Show form to create new campground
app.get("/new", function(req, res){
res.render("new");
});
// Edit flashcard
app.get("/flashcards/:id/edit", function(req, res){
Flashcard.findById(req.params.id, function(err, selectedFlashcard){
if(err){
req.flash("error", "Flashcard not found!");
} else {
res.render("edit", {flashcard: selectedFlashcard});
}
});
});
// Update flashcard
app.put("/flashcards/:id", function(req, res){
Flashcard.findByIdAndUpdate(req.params.id, req.body.flashcard, function(err, updatedFlashcard){
if(err){
res.redirect("/flashcards");
} else {
res.redirect("/flashcards");
}
});
});
// Destroy Flashcard
app.delete("/flashcards/:id", function(req, res){
Flashcard.findByIdAndRemove(req.params.id, function(err){
if(err){
res.redirect("back");
} else {
//req.flash("success", "flashcard deleted.");
res.redirect("/flashcards");
}
});
});
app.listen(3000, () => console.log("Flashcard app is listening"));
I think the best aproach would be to pass the translator.js to the node.js server. Create a route on express for translations, and through that route you will call the translator.js and return the result. Then, on your html page, instead of running the translator.js directly, send a request to your server passing the necessary data.
On your app.js, you can do a route like this:
const translator = require('path_to_translator');
app.get('/translation', translator);
And then on your translator.js, you can export a function that will receive the parameters you need and return the result:
const bingTranslate = (req, res) => {
// YOUR CODE HERE
}
module.exports = bingTranslate
And then on your html you will make the button send a request to your server instead of calling translator.js, so you can change the value of the #bingTranslateOutput button based on the response you will receive from the server.
Introduction
I have a three functions, each one would feed data into then next. The objective is first to retrieve data then authenticate a API key then finally using the generated API key and data retrieve from the first function post to the API in the third function.
Order
First function function to retrieve data from a post.
Second function gets API key requested from a API.
Third function posts data to the API.
Needed functionality
I need the variables retried in the first function and the API key generated in the second function to be available for use in the third function.
Problems and questions
emailUser is not being found to use in the third function
api_key is not being found in the third function
also the functions need to run in order first, second then third
This all works if I was to insert the data manual but when input the variables it dose not work, I understand that it is because the variables being within the function but how do I fix this, also how do I set the order of the functions ?
Full code
// Grab the packages needs and sets server
//---------------------------------- Grab the packages we need and set variables --------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------
var express = require('express');
var request = require('request');
var nodePardot = require('node-pardot');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 8080;
// Varibles to use in second and third function
var password = 'password';
var userkey = '6767712';
var emailAdmin = 'admin#admin.com';
// start the server
app.listen(port);
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({extended: true})); // support encoded bodies
console.log('Server started! At http://localhost:' + port);
// First Retrieve posted data from Front-End
//---------------------------------- Retrieve posted data from Front-End -----------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------------
// POST http://localhost:8080/api/index
app.post('/api/data', function (req, res) {
console.log(req.body);
var Fname = req.body.fname;
var Lname = req.body.lname;
var emailUser = req.body.email;
res.send(Fname + ' ' + Lname + ' ' + emailUser);
});
app.get('/', function (req, res) {
res.send('hello world, Nothing to see here...');
});
// Second Get Posted variables
//---------------------------------- Now authenticate the api and get api_key -----------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------
nodePardot.PardotAPI({
userKey: userkey,
email: emailAdmin,
password: password,
// turn off when live
DEBUG: true
}, function (err, client) {
if (err) {
// Authentication failed
// handle error
console.error("Authentication Failed", err)
} else {
// Authentication successful
// gets api key
var api_key = client.apiKey;
console.log("Authentication successful !", api_key);
}
});
// Third Retrieve posted data from Front-End
//---------------------------------- Send all data to API -----------------------------------------------------
// ------------------------------------------------------------------------------------------------------------
// Set the headers
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded'
};
// Configure the request
var options = {
url: 'https://pi.pardot.com/api/prospect/version/4/do/create/email',
method: 'POST',
headers: headers,
form: {
'email': emailUser,
'user_key': userkey,
'api_key': api_key
}
};
// Start the request
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Print out the response body
console.log("error",body)
}
else {
console.log("Sent Data",body);
}
});
best way is using async package (install with npm install async) that is very famous and useful package in npm your functions will be something like this:
var async=require('async');
var handler = function (req,res) {
async.auto
(
{
getBody: function (cb, results) {
var body=req.body;
//prepare body here then send it to next function
cb(null, body)
},
getApi: ['getBody', function (results, cb) {
var preparedBody=results.getBody;
// get the api here and send it to next function
var apiKey=getApi()
cb(null, {apiKey:apiKey,preparedBody:preparedBody})
}],
third: ['getApi', function (results, cb) {
var preparedBody=results.getApi.preparedBody;
var apiKey=results.getApi.apiKey;
// now data are here
cb(null,true)
}]
},
function (err, allResult) {
// the result of executing all functions goes here
}
)
}
Another way to handle this problem is by allowing the express middleware flow to do those things for you on a separate Router.
I have setup a sample Glitch for your reference using stand in functions to simulate network calls HERE.
In your case, you would have to do something like:
//API route
var express = require('express');
var router = express.Router();
router.post('/data', function (req, res, next) {
console.log(req.body);
req.bundledData = {};
req.bundledData.fname = req.body.fname;
req.bundledData.lname = req.body.lname;
req.bundledData.emailUser = req.body.email;
next();
});
router.use(function(req, res, next){
nodePardot.PardotAPI({
userKey: userkey,
email: emailAdmin,
password: password,
// turn off when live
DEBUG: true
}, function (err, client) {
if (err) {
// Authentication failed
// handle error
console.error("Authentication Failed", err)
} else {
// Authentication successful
// gets api key
req.bundledData.api_key = client.apiKey;
console.log("Authentication successful !", api_key);
next();
}
});
});
router.use(function(req, res, next){
// Set the headers
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded'
};
// Configure the request
var options = {
url: 'https://pi.pardot.com/api/prospect/version/4/do/create/email',
method: 'POST',
headers: headers,
form: {
'email': emailUser,
'user_key': userkey,
'api_key': api_key
}
};
// Start the request
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Print out the response body
console.log("error",body)
}
else {
console.log("Sent Data",body);
//Processing is complete
res.json({
success:true,
body:body
});
}
});
});
I've been following this tutorial for data-binding using Node and Angular: https://codeforgeek.com/2014/09/two-way-data-binding-angularjs/
Here's my server code:
var express = require("express");
var mysql = require("mysql");
var app = express();
/*
* Configure MySQL parameters.
*/
var connection = mysql.createConnection({
host : "localhost",
user : "root",
password : "password",
database : "csflip"
});
/*Connecting to Database*/
var log = console.log;
jamesBug = function(txt) {
var d1 = new Date();
var logtxt = "["+d1.toUTCString()+"] "+txt;
console.log(logtxt);
}
connection.connect(function(error){
if(error)
{
jamesBug("Problem with MySQL"+error);
}
else
{
jamesBug("Connected with Database");
}
});
/*Start the Server*/
app.listen(3000,function(){
jamesBug("It's Started on PORT 3000");
});
app.get('/',function(req,res){
res.sendfile('index.php');
});
app.get('/loadcoinflips',function(req,res){
jamesBug("Got a load request for conflip listings from database.")
connection.query("SELECT * FROM coinflips WHERE accepted = '0'",function(err,rows){
if(err)
{
jamesBug("Problem with MySQL: "+err);
}
else
{
jamesBug("Recieved the data from the database.");
jamesBug("Data recieved stringified to JSON: ("+JSON.stringify(rows)+")");
res.end(JSON.stringify(rows));
jamesBug("Outputted the JSON data.");
}
});
});
This is my core.js file:
app.controller('two_way_control',function($scope,$http,$interval){
load_pictures();
$interval(function(){
load_pictures();
},300);
function load_pictures(){
$http.get('http://localhost:3000/loadcoinflips').success(function(data){
$scope.ids=data;
});
};
});
This is how I'm displaying the data:
<div id="container" ng-app='two_way' ng-controller='two_way_control'>
<div class="row" ng-repeat="data in ids">
<h2>{{data.id}}</h2>
<br />
</div>
</div>
However, when I load my page It's blank, am I being stupid or can somebody help me out...
Thanks,
James
Try using this:
app.all('/*', function(req, res, next) {
// CORS headers
res.header("Access-Control-Allow-Origin", "*");
// restrict it to the required domain
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
// Set custom headers for CORS
res.header('Access-Control-Allow-Headers', 'Authorization,Content-type,Accept,X-Access-Token,X-Key');
if (req.method === 'OPTIONS') {
res.status(200).end();
} else {
next();
}
});
I'm new to node.js. A project I'm working on requires that a large array (625 items) be stored in a MySQL database as a string and I'm using Node MySQL to accomplish that.
Right now I have it so that the row is updated when a request is made to "/(column name)?(value)". Unfortunately, it didn't take long to learn that passing 625 items as a string to node isn't the most efficient way of doing things.
Do you have any suggestions for alternate methods of passing a large array as a string besides querystrings?
var http = require('http'),
mysql = require("mysql"),
url = require("url"),
express = require("express");
var connection = mysql.createConnection({
user: "root",
database: "ballot"
});
var app = express();
app.use(express.bodyParser());
app.options('/', function (request, response)
{
response.header("Access-Control-Allow-Origin", "*");
response.end();
});
app.get('/', function (request, response)
{
connection.query("SELECT * FROM pathfind;", function (error, rows, fields) {
for(i=0;i<rows.length;i++)
{
response.send('<div id="layers">'+rows[i].layers+'</div> \
<div id="speed">'+rows[i].speed+'</div> \
<div id="direction">'+rows[i].direction+'</div>');
}
response.end();
});
});
app.post('/', function (request, response)
{
console.log(request.param('data', null));
var urlData = url.parse(request.url, true);
if(urlData.pathname = '/layers')
{
col = "layers";
}
else if(urlData.pathname = '/speed')
{
col = "speed";
}
else if(urlData.pathname = '/direction')
{
col = "direction";
}
req.addListener("data", function(data) {
connection.query("UPDATE pathfind SET "+col+"="+data+" WHERE num=0", function (error, rows, fields) {
if (error)
{
app.close();
}
});
});
});
app.listen(8080);**
EDIT: So now I know I need to use posts. I've rewritten the above code using express.js. Most examples that I look at online use posts with HTML forms, which is fine, but my project needs to post data via an AJAX request. Can someone show me how that data is parsed in node.js?
You can extract post data like this.
if (req.method == 'POST') {
var body = '';
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
var postData = body.toString();
console.log(postData);
});
}