I have this exact question, except I'm using the restify HttpClient:
node.js write http response to stream
For clarity, I'm trying to do this:
var client = restify.createClient({
url: "http://www.google.com"
});
client.get("/", function(err,res) {
res.pipe(process.stdout);
});
It hangs for a few seconds but never writes anything to stdout. Obviously I'm trying to fetch something other than google's homepage, but for example...
I would recommend you to user request for something like this:
var request = require('request'); // npm install request
request('http://www.google.com').pipe(process.stdout);
Looking at restify's docs it seems you need to wait for the 'result' event:
var client = restify.createClient({
url: "http://www.google.com"
});
client.get("/", function(err,req) {
req.on('result',function(err2,res) {
res.pipe(process.stdout);
res.on('end',function() {
process.exit(0);
});
});
});
Related
I have a requirement to access multiple devices over IP from an HTML5 web app.
My approach to working around the cross-domain impossibility of doing this all on the client side has been to "cook" requests from the client inside of express' middleware. A route receives a get or post from the client, and then performs a get or post to the 3rd party device identified by the payload from the client.
I'm using the code to get info from a device. It works just fine when I run it directly from file inside of a client I made for testing purposes. Running directly from file avoids the CORS difficulty because the client is also the server I guess.
When I run the same code from within an express route, I get a 500 error.
Am I trying to do something impossible? I'm only about a week into node, express etc so hopefully it's something dumb and easy to solve. I'm taking fact that I haven't been able to find any other questions quite like this as an indication that there's a proper way to achieve what I need.
// post to find a camera
router.post('/find', function(req, res) {
var url = 'http://' + req.body.addr + '/cgi-bin/aw_cam?cmd=QID&res=1';
console.log(url);
$.ajax({
type: 'GET',
url: url,
dataType: 'html',
success: function (result) {
console.log('success: ' + result);
res.send(result);
},
error: function (xhr, textStatus, err) {
console.log('error: ' + textStatus);
}
});
});
Here's what logged to the server console:
http://192.168.0.10/cgi-bin/aw_cam?cmd=QID&res=1
POST /cameras/find 500 126.593 ms - 1656
Thanks in advance!
ok I found how to do this. The trick is to use Node's built-in http messaging capabilities. I found a good article on how to do this here
The code below does exactly what I wanted from within my custom route middleware. I guess I just learned that I can only use AJAX how I wanted on the client side.
This lets me abstract the hairier details of the device control protocol into the server, leaving my client apps to use JSON/AJAX model to interact with them. Success!
var http = require('http');
// post to find a camera
router.post('/find', function(req, res) {
var url = 'http://' + req.body.addr + '/cgi-bin/aw_cam?cmd=QID&res=1';
console.log(url);
http.get(url, (response) => {
console.log(`Got response: ${response.statusCode}`);
var body = '';
response.on ('data', function(d) {
body += d;
});
response.on ('end', function () {
console.log('received: ' + body);
var reply = {};
if (body.indexOf('OID:') == 0) {
reply.msg = body.slice(4);
reply.ok = true;
} else {
reply.msg = body;
reply.ok = false;
}
res.send(reply);
});
// consume response body
response.resume();
}).on('error', (e) => {
console.log(`Got error: ${e.message}`);
});
});
I have my test.login.js:
it('calls login when there\'s a username present', () => {
React.findDOMNode(LoginElement.refs.username).value = 'foo';
TestUtils.Simulate.submit(form);
expect(LoginElement.state.errored).toEqual(false);
});
By submitting the form, it calls a login method:
login() {
let typedUsername = React.findDOMNode(this.refs.username).value;
if (!typedUsername) {
return this.setState({
errored: true
});
}
// we don't actually send the request from here, but set the username on the AuthModel and call the `login` method below
AuthModel.set('username', typedUsername);
AuthModel.login();
},
So I'm trying to test the functionality of Login.jsx, not AuthModel.js, however by calling AuthModel.login(), it sends a message over a WebSocket. However, the issue is that in my actual app, I don't load anything until the WebSocket has connected (I fire an event to then render the React app), however in my Jasmine test, I don't wait for this event, so I receive:
ERROR: null, DOMException{stack: 'Error: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
And my test fails, which, it shouldn't fail because it's encapsulated functionality does what I want it to. It just errors further up the dependency tree.
What is my best approach for either working around this, or to mitigate the WebSocket trying to connect in my test env? (I'm extremely new to testing, so these concepts are very alien to me right now)
I won't pretend to know a lot about this, but can't you dependency inject AuthModel so how and then mock it in your tests? Sorry this isn't a complete answer it's just what my first instinct would be.
If you need a library to assist this, angular/di (from angular2) is pretty great.
You could mock / stub the server request using Sinon JS. - http://sinonjs.org/
If you just want to know that Auth.login makes a request to the server, use sinon.stub (http://sinonjs.org/docs/#stubs), e.g.
var stub = sinon.stub($, 'ajax');
//Do something that calls $.ajax
//Check stub was called and arguments of first call:
console.log(stub.called)
console.log(stub.args[0])
stub.restore();
If your code requires a response, use sinon's fake server (http://sinonjs.org/docs/#server):
var server = sinon.fakeServer.create(),
myResults = [1, 2, 3];
//Set-up server response with correct selected tags
server.respondWith('POST', url, [200, {
'Content-Type': 'application/json'
},
JSON.stringify({
response: myResults
})
]);
//Do something which posts to the server...
sendToServer('abc').done(function(results) {
console.log('checking for results ', results);
})
server.restore();
You can get a lot more complicated with the server responses - using functions, etc. to handle multiple request types, e.g.
function initServer(respondOk) {
var server = sinon.fakeServer.create();
server.respondWith('POST', /.*\/endpoint\/.*/, function(request) {
var header = { 'Content-Type': 'application/json' };
if(!respondOk) {
var response = JSON.stringify([{
'error_code': '500',
'message': 'Internal server error'
}]);
request.respond(500, header, response);
} else {
var code = 200,
resources = JSON.parse(request.requestBody),
result = JSON.stringify({ customer: resources });
request.respond(code, header, result);
}
});
return server;
});
I'm in the process of evaluating hapi.js. All was going well until I started writing tests. Basically I'm trying to test the status code as the first step. however I cannot proceed further. Server.inject always returns 404. I tested the same code by running the server and sending http requests using fiddler ( an http request simulation tool like postman ). This is successful. I don't know what I'm doing wrong. I'm following the exact steps as in many tutorials online. The test code is as follows.
var Lab = require("lab");
var server = require("../server/index.js").server;
var lab = exports.lab = Lab.script();
var code = require("code");
lab.test("home", function (done) {
var options = {
method: "GET",
url: "/"
}
server.inject(options, function (response) {
var result = response.result;
code.expect(response.statusCode).to.equal(200);
done();
});
});
The assertion never seems to be passing successfully, I have made sure the routes are available.
EDIT: As Matt Harrison has correctly pointed out, I'm in fact loading the routes asynchronously.
How to test in these scenarios?
Everything looks ok with your test. To prove it, if you put this in your index.js file it should work:
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 4000 });
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('ok');
}
});
exports.server = server;
Without seeing what's happening in your index.js file I can only make an educated guess. But here goes anyway…
One possibility is that you're adding the GET / route asynchronously and it isn't in the routing table when your test gets run. Why might this happen? Some plugins don't call the register callback immediately because they need time to set themselves up. If you're registering your routes in this callback they're not loaded when your test gets run. For example this will fail with 404 for your test:
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 4000 });
var fakePlugin = function (server, options, next) {
setTimeout(next, 500);
};
fakePlugin.attributes = { name: 'fake' };
server.register(fakePlugin, function (err) {
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('ok');
}
});
});
exports.server = server;
SOLUTION:
To solve this issue, you just need to delay your tests until all plugins have finished loading. There's a few possible ways to do that. Here's one I like:
Add a before to your test that delays running tests until server emits a pluginsLoaded event:
...
lab.before(function (done) {
server.on('pluginsLoaded', done);
});
...
And you just need to make sure you emit that in your index.js:
server.register(..., function (err) {
server.route({
...
});
server.emit('pluginsLoaded');
});
I learned to make request with the XMPPserver by using node-xmpp library. Now i can make the request as mentioned in XMPP extensions documentations. But now i want to get the callback response for the each request (especially the XML response).
Here i have used the following code the make a request subscription (friend request) to a another user
var net = require("net");
var xmpp = require('node-xmpp');
var cl = new xmpp.Client({ jid: "one#localhost", password: "comet123$" })
cl.addListener('online', function(data) {
console.log('Connected as ' + data.jid.user + '#' + data.jid.domain + '/' + data.jid.resource)
//making subscription
var stanza = new xmpp.Element('presence',{
to: "hai#localhost",
from: "one#localhost",
type: "subscribe",
}).up
// making request
cl.send(stanza);
// nodejs has nothing left to do and will exit
cl.end()
})
I want to know, how to get the response result.
I tried with the callback functionality with as llike this,
cl.send(stanza, function(result){
console.log(result);
});
and also like this
var result = cl.send(stanza);
This returns only true,
So can anyone please tell me how do I get the callback result for the requests that we make by using the node-xmpp libarary
There is no callback or return for XMPP messages. You will have to have to set up an event listener to pick up messages coming back from the server. Add:
cl.on('stanza', function(stanza){
// Do something with the stanza
// If you want to end after the first message you get back, move this here
cl.end();
});
you can get raw data from connection
cl.connection.on("data", function (data) {
console.log('data', data.toString('utf8'));
});
I've been trying to use JSONP to get a JSON object from a server via a client-side call (on a different port). However, because my server is implemented in javascript using Node.js and Express, I haven't been able to find much on JSONP with Javascript on the server as most sites I found used php for server-side code.
I believe the issue is with how I set up the url with respect to the callback, which I'm a bit fuzzy on cause it's new to me.
On the server:
//Setting up server stuff
var express = require('express'),
app = express.createServer();
app.use(express.logger());
//Making a connection to the mongoDB to get the data that I want to display in the JSON object
new Db('prism',
new Server("127.0.0.1", 27017, {auto_reconnect: false}), {}).open(function(err, db) {
app.get('/getData', function(req, res) {
console.log('JSONPCALLBACK CALLED WITH RETURNDATA PASSED IN; SERVER SIDE');
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
}
});
And on the client:
$.ajaxSetup({ cache : false });
$.getJSON('http://127.0.0.1:1337/getData&callback=?', function(rtndata) {
console.log('SUCCESS');
console.log(rtndata);
});
embedded by the standard tags.
But I get the error:
GET http://127.0.0.1:1337/getData&callback=jQuery16108897686484269798_1311007334273?_=1311007334342 404 (Not Found)
The server is on port 1337 while the client is run through MAMP on localhost:8888. I'm not sure if its even a localhost related issue as I've been trying to get this setup running for a few days now.
I believe the issue has something to do with not writing this line, which is in php, into my server-side Javascript. Most of the JSONP examples I found had something like this. But I'm not sure.
if ($GET['callback'] != '')
$json = $GET['callback']."( $json )";
return $json;
Any help would be greatly appreciated. I apologize ahead of times for being super verbose.
Bests,
Cong
I think you have two problems. First is the 404. Completely separate from getting the client-side jQuery code to work, you need to make sure that you can issue a regular browser request (i.e. paste in that URL) and get back what you expect. I haven't used express, so it's hard for me to comment on why you'd be getting that, except to say that I don't see 1337 anywhere in your server-side code, just what appears to be the port number 27017.
The second problem is that you don't actually want to execute the callback on the server, just build the JSON response including the callback (string) prefixed to it.
So instead of this ...
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
try this:
if (callback) {
console.log('callback is defined');
res.write(callback + '(' + JSON.stringify(returnData) + ')');
}
else {
console.log('callback is not defined');
}
Hope this helps!
From http://api.jquery.com/jQuery.getJSON/ there is an example that includes 2 '?' in the URL.
you only have one, so try
$.getJSON('http://127.0.0.1:1337/getData?callback=?', function(rtndata) {
and see if that gets rid of your 404
then look #jimbojw suggestion for returning a proper jsonp formated responce.
Use this:
var express = require("express");
var server = express.createServer();
server.enable("jsonp callback");
server.get("/foo", function(req, res) {
// this is important - you must use Response.json()
res.json("hello");
});
jsonp with node.js express