I am trying to make an HTTP POST request using an iOS Swift app to an Express.js server. In the post request, I send JSON data, creating the JSON object using a dict and SwiftyJSON. However, the request continues to time out. I think it has something to do with 'body-parser', which is what I am using to parse the HTTP body. Here is my swift code:
override func viewDidLoad() {
super.viewDidLoad()
var dict = ["name": "FirstChannel", "verified": 0, "private": 1, "handle": "firstChannel", "subscribers": 0] as [String : Any]
var jsonData = JSON(dict)
do {
let post:NSData = try jsonData.rawData() as NSData
var postLength: NSString = String(post.length) as NSString
var url = URL(string: "http://10.0.0.220:3000/channel/createChannel")!
var request = NSMutableURLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = post as Data
request.setValue(postLength as String, forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main, completionHandler: { (resposne, data, error) in
if(error != nil) {
print(error)
}
else {
print(data)
}
})
}
catch {
print(error.localizedDescription)
}
}
And here is the code I use in my express.js router:
var express = require('express');
var router = express.Router();
var http = require('http');
var url = require('url');
var util = require('util');
var bodyParser = require('body-parser')
var ObjectID = require('mongodb').ObjectID;
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({extended: true}));
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');
var channelSchema = mongoose.Schema({
name: String,
verified: String,
private: String,
channelID: String,
handle: String,
subscribers: String
});
var Channel = mongoose.model("Channel", channelSchema);
router.post('/createChannel', bodyParser, function(req, res, next) {
req.body = true;
if(!req.body) return res.sendStatus(400);
var objID = new ObjectID();
var newChannel = new Channel({
name: req.body["name"],
verified: req.body["verified"],
private: req.body["private"],
channelID: objID,
handle: req.body["handle"],
subscribers: (req.body["subscribers"])
});
newChannel.save(function(err, point){
if(err) console.log(err);
else res.end();
});
});
If anybody could help me out and help this POST request succeed, I would greatly appreciate it. Thanks!
It doesn't look like you're sending back an HTTP 200 on success of your route - you only handle an error. Add a res.end(); at the end of your route (probably in the callback from the DB call) and try again.
Related
I know this has been gone over before but I've spent hours on this and can't seem to figure out how to post data to a node.js server... I've started the project using cloud9 and node.js so I know I have a good install and that I'm starting with a working site.
In swift I'm sending a post request like
func post (){
let url = URL(string: "https://the-game-stevens-apps.c9users.io/index.html/")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Accept")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "name=henry&message=HelloWorld"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
}
task.resume()
}
Then in my server.js file I have
var router = express();
router.use(express.urlencoded());
router.post('/index.html', function(req, res) {
var obj = {name:req.body.name,text:req.body.message};
});
I have plenty of experience with javascript but I'm a noob when it comes to node.js and have just been poking around with it, any help is really appreciated
The only part I can correct in your node.js code is
To get router you need to call express.Router();
const express = require('express');
const router = express.Router();
router.use((req,res,next) => {
console.log("/" + req.method, "host"+ req.host, "Params" + req.params);
next();
});
router.post('/index.html', (req, res) => {
const obj = {name:req.body.name,text:req.body.message};
//insert obj into database
});
Hi then I have a problem like this: I have an application written in swift that sends values with a json array to node.js! Should I extrapolate the Username and Password parameters? how can I do?
Swift Code:
// prepare json data
let json: [String: Any] = ["Username": ""+UsernameTextBox.text!,"Password": ""+PasswordTextBox.text!]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// create post request
let url = URL(string: "http://localhost:3000/login")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
Node.js Code:
var express = require("express");
var myParser = require("body-parser");
var app = express();
//Login
app.use(myParser.urlencoded({extended : true}));
app.post("/login", function(request, response) {
console.log(request.body);
});
//Application Listen on Port
app.listen(3000,function(){
console.log("Application Server Start on Port: 3000");
})
Log of Body:
New JavaScript Code Image:
Why using JSON.stringify on a string, remove it and your code should work:
var data = JSON.parse(Object.keys(request.body)[0]);
var username = data.Username;
var password = data.Password;
var body = {'{"Password":"dsdsd","Username":"dsdsdsds"}':''};
var data = JSON.parse(Object.keys(body)[0]);
var username = data.Username;
var password = data.Password;
console.log(username, password);
Change extended to false and try this one and you will get json object in request body.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
To extend to #edkeveked,
var data = JSON.parse(Object.keys(request.body)[0]);
var username = data.Username;
var password = data.Password;
The output of :
console.log(request.body);
is
{{"username": "something", "password": "somethingElse"}: ""}
You can change the form of the data to something you can easily access like this one :
{"Username": "something", "Password": "somethingElse"}
But, if for some reasons, you prefer to stick to the way the data is sent in your question, you can extract your user credentials with:
var data = JSON.parse(Object.keys(request.body)[0]);
var username = data.Username;
var password = data.Password;
I had a problem in req.body at server as i received req.body as {} empty, here is the code at service
addEmployeeCollection(addArray: EmployeeSchema) {
let url: string = Constants.DOMAIN + Constants.CREATE_EMPLOYEE_ROUTE;
console.log('addArray at employee service', addArray)
var body = addArray;
return this._httpService.post(url, body).map(res => res.json()).catch(this._errorHandler);
}
this._httpService.post(url, body) will go to the interceptor, there the http.post method returned, here is the interceptor code,
post(url: string, body: Object, options ? : RequestOptionsArgs): Observable < Response > {
this.headers.append('Content-Type', 'application/json');
let token = localStorage.getItem('realtoken');
console.log('http token', token);
if (typeof url === 'string') {
if (!options) {
options = {
headers: this.headers
};
}
options.headers.set('Authorization', ` ${token}`);
}
return super.post(url, body, options).catch(this.catchAuthError(this));
}
now here the request payload at headers contains the information,
The response from the server side is
{"__v":0,"_id":"58ba4969ed69821fd6f7e573"}// details of employee is not saved
here the server side code
var mongoose = require('mongoose');
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
//schema-models
var employeeCollection = require('../../model/employee.model.js');
router.post('/new', function(req, res) {
var employee_data = req.body;
console.log('req.body=====> ', req.body)
var addcontent = new employeeCollection(employee_data);
console.log('addcontent--->', addcontent);
addcontent.save(function(err, data) {
if (err) {
res.send(err);
} else {
console.log('data', data);
res.json(data);
}
});
});
module.exports = router;
At terminal, req.body=====> {}, the employee details are sent correctly in the request, but at server side am getting as empty req.body
As a beginner to this concepts,i could not figure out where i am getting wrong, please help me out
I am writing a url shortener service in Node JS using mongo to connect to mLab.
Right now the user can send a request to the service with a url to shorten, and it returns a shortened url. However, if the user then sends the shortened url as a request, the redirect does not happen. Rather, the service goes into a loop.
1) How do I see what exactly is getting grabbed from the db? (Knowing how to do this would help out in trouble-shooting)
2) And what may be the cause of the looping issue?
var express = require('express')
var app = express()
var path = require('path');
var port = process.env.PORT || 8080;
var crypto = require("crypto");
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({ // this schema is used for writing to the db
url : String,
key : String
});
var urlcntrctr = new Schema( // this schema is used for reading from the db
{ key: String, url : String, _id: String },
{ collection: 'urlcntrctr'}
);
const SchemaName = mongoose.model('SchemaName', urlcntrctr); // for reading from the db
app.get('/', (req, res, next) => res.sendFile(path.join(__dirname, '/index.html')) ) ;
app.set('port', (process.env.PORT || 5000));
app.get('/new/:url(*)', function(req, res) {
var shortenme = req.params[0];
var showme = req.params[0];
console.log("User's request: " +shortenme);
var amItrue = validateURL(shortenme);
if (amItrue){
connectmongoviamongoose();
var shortenmeObj = yncryptyyn(shortenme);
shortenme = shortenmeObj.key;
writeToDb(shortenmeObj); b
closetheconnection();
var contractedurl = 'http://firstappever-olddognewtrix123.c9users.io/' + shortenme;
var responseObject = ({"Original url: ": showme, "Contracted url: ": shortenme });
res.send(responseObject);
}
else{console.log("You need to enter a url, beginning with 'http' or 'https' and ending in '.com' or '.org' or whatever!");};
})
app.get('/:tag(*)', function(req, res) {
var targetnumber = req.params.tag;
sendforRedirect(req, res);
sendforRedirect(req, res);
})
function sendforRedirect(req, res){
var target = req.params.tag;
console.log("The value of target is " + target)
; var options = { server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } } };
var mongodbUri = 'mongodb://<dbusername>:<dbuserpassword>#ds159988.mlab.com:59988/urlcntrctr';
mongoose.connect(mongodbUri, options);
mongoose.Promise = global.Promise;
var conn = mongoose.connection;
conn.on('error', console.error.bind(console, 'connection error:'));
conn.once('open', function() {
console.log("OK, you are connected for the redirect. ")
var query = {
key: {
$eq: target
}
}
SchemaName.find(query, function (err, doc) {
if(err){
console.log(err);
conn.close();
};
if(doc){
res.redirect(doc.url); // rather than redirecting, it is looping *****************
conn.close();
} else {
res.send("Sorry, we don't recognize that url");
conn.close();
}
});
});
}
function writeToDb(dataObject){
mongoose.model('Document', UserSchema);
var urlFromUser = mongoose.model('Document');
var urlfromuser = new urlFromUser();
urlfromuser.url = dataObject.url;
urlfromuser.key = dataObject.key;
urlfromuser.save();
};
function validateURL(textval) { //copied from http://stackoverflow.com/questions/1303872/trying-to-validate-url-using-javascript
var urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*#)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
return urlregex.test(textval);
}
function connectmongoviamongoose(){
var mongoose = require('mongoose');
var options = { server: { socketOptions: { keepAlive: 300000, connectTimeoutMS: 30000 } },
replset: { socketOptions: { keepAlive: 300000, connectTimeoutMS : 30000 } } };
var mongodbUri = 'mongodb://<dbusername>:<dbuserpassword>#ds159988.mlab.com:59988/urlcntrctr';
mongoose.createConnection(mongodbUri, options);
var conn = mongoose.connection;
conn.on('error', console.error.bind(console, 'connection error:'));
conn.once('open', function() {
console.log("OK, you are connected. ")
});
}
function closetheconnection(){
var mongoose = require('mongoose');
mongoose.connection.close();
}
function yncryptyyn(incryptme){
var ulimit = 6;
var key = crypto.createHash('md5').update(incryptme).digest("base64");
key = key.slice(0,ulimit);
var obj = {
url: incryptme,
key: key
};
return obj;
}
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
Better than console.log statements, you can use the package node-inspector to actually set breakpointsnin your code via chrome devtools and step through the code Much more robust process.
I would note that it is not clear to me what kind of urls you are shortening (internal to your site or external), but at present it looks like you're calling the redirect function twice, which should cause an error unto itself, and second if you are redirecting to internal urls your routes are probably going to match a lot that you don't want them to.
Finally, your code is kind of a jumble right now, which will make debugging harder no matter what you do. Try and break it out into different files based on what they do and test bits independently as much as possible.
For question 1: just put in a console.log, for example like this:
if(doc){
console.log(doc);
res.redirect(doc.url);
....
Even better put the whole functionality of the look up of the url into an own function, so you can check the working of the lookup and the working of the redirect independently.
Using express middleware fetching user information from mongodb on page request.
Try to set userInfo in request but I am not getting userinfo in request please check the below code and suggest me.
app.js
app.use(userManager.userManager);
userManager.js
"use strict";
var USERModel = require("./user_schema");
module.exports.userManager = function(req, res, next) {
var assoString = "US";
var options = {
limit: 1
};
USERModel.textSearch(assoString, options, function (err, output) {
if (err) {
console.error("USERModel.textSearch:" ,err);
}
else if (output && output.results && output.results.length > 0) {
req.userInfo = output.results[0].obj.userDetail;
}
else {
console.warn("Empty USERModel for ", assoString);
}
});
};
user_schema.js
"use strict";
var db = require('../lib/db_connect');
var textSearch = require("mongoose-text-search");
var userSchema = new db.Schema({
associatedwith : String,
userDetail: {
userId : {type: String},
cId : {type: String},
device : {type: String},
contentType : {type: String},
isCompression : {type: Boolean},
renderType : {type: String}
}
}
);
userSchema.plugin(textSearch);
var USERModel = module.exports = db.mongoose.model('users', userSchema);
You need or reply the http request (with res.send, res.json, res.end and family) or invoke the callback to pass the request to the next middleware or route handler:
app.use(function(req,res,next){
// Rest of the logic
res.send(200,'Everything went OK'); // The request is replied here
});
app.use(function(req,res,next){
// Rest of the logic
next(); // To the next middleware/route logic
});