I'm looking at using NodeJS to act as the server to build an API.
Ideally I'd love for there to be an API endpoint to send a set of information as well as a file which can be saved to the files system.
Most examples I've seen are for sending a file via a form, however I'd like to do this through a post request.
Does anyone know how I could achieve this (if it's at all possible)?
At the moment what I'd like to achieve is something along the following lines:
app.post('/Some/Endpoint/', controller.handleSomeEndpoint, function(request, response) {
response.send('Finished Request');
});
exports.handleSomeEndpoint = function(request, response, next) {
var bodyarr = []
request.on('data', function(chunk){
bodyarr.push(chunk);
})
request.on('end', function(){
console.log( bodyarr.join('') );
})
}
But the data and end never get called if I run a curl command along the lines of:
curl http://127.0.0.1:5000/Some/Endpoint/ -F 'test=#test_file'
Cheers,
Matt
The answer seems to be that expressJS doesn't use the same method of handling a post file as the http module in nodejs.
All that was needed was including a directory for the files to be written to:
app.use(express.bodyParser({uploadDir:'./uploads'}));
Which I found here:
http://www.hacksparrow.com/handle-file-uploads-in-express-node-js.html
I would suggest you to use Formidable to avoid anonymous file uploading.
Your code should work fine; it's the curl usage that's wrong. Try this instead:
$ curl -X POST --data-binary #test_file http://localhost:8080
Related
I'm trying to consume a tone analyzer service from a nodejs app. I get unauthorized access problem, but these credentials work fine when I use them in a curl.
Running locally, in my app.js file I've included the data of the tone analyzer as follows:
var ToneAnalyzerV3 = require('watson-developer-cloud/tone-analyzer/v3');
var toneAnalyzer = new ToneAnalyzerV3({
version: '2017-09-21',
iam_apikey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
});
Then I've added this, so my app listens for post requestes in the /tone url:
app.post('/tone', function(req, res, next) {
var params = {'tone_input': req.body}
toneAnalyzer.tone(params, function(err, data) {
if (err) {
return next(err);
}
return res.json(data);
});
});
But when I call it I get "Unauthorized: Access is denied due to invalid credentials".
The thing is that these credentials work fine in curl:
curl -X POST -u "apikey:XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" --header "Content-Type: application/json" --data-binary #tone.json "https://gateway-lon.watsonplatform.net/tone-analyzer/api/v3/tone?version=2017-09-21&sentences=false"
{"document_tone":{"tones":[{"score":0.6165,"tone_id":"sadness","tone_name":"Sadness"},{"score":0.829888,"tone_id":"analytical","tone_name":"Analytical"}]}}
The reason you are getting unauthorised errors when running locally is that your service is hosted in https://gateway-lon.watsonplatform.net. If you don't specify an endpoint / url in your ToneAnalyzerV3 constructor then the API / SDK defaults to Dallas. So although your credentials may be correct for London, they are not correct for Dallas.
When you deployed your app to the cloud (which I guess was to the London location), you probably bound the service into your application. This sets environment variables allowing the SDK to determine the endpoint.
You constructor should look like:
var toneAnalyzer = new ToneAnalyzerV3({
version: '2017-09-21',
iam_apikey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
url: 'https://gateway-lon.watsonplatform.net/tone-analyzer/api',
});
I don't see problem with code (also never used watson stuff), but you may check the following point :
How the request you really send is formated : Because I see that you send param that is not present in your curl request.
Is your function using POST aswell (you don't provide much detail on what the call to toneAnalyzer.tone does exactly) ? Maybe it's a conflict of headers or Content-Type.
Do you use a proxy (enterprise settings or stuff like that) ? If you do, you may check that node is correctly using it.
You should also provide a bit more details on what exactly your tone object do, and try to find where the call to the IBM API is done.
I have a specific task: I need to download an image from the source URL and upload it to another host via POST request as multipart/form-data. I'm trying to use node.js request library but never succeed.
The following code doesn't send anything in the request body.
request.post({
url: uploadUrl,
formData: {
photo: request(imageUri)
}
}, function (err) {
if (err) console.error(err.stack)
});
I have tried posting directly through the form-data library, but it doesn't seem to work neither. How do I solve this without the creation of temp files?
As i said in my comment, you need to wait until you have the image to make the post request. If you wanted to pipe the streams, you could try something like this...
request.get(imageUri).pipe(request.post(uploadUri));
Hope that helps.
The problem turned out to be that my imageUri had query parameters in it. I think this is a bug in form-data library. Removing query parameters solved the problem.
Okay so what I am trying to achieve here is that I have made an PHP script with a bunch of $_GET's.
So I would like to go to a website without actually visiting it with NodeJS. Basically to trigger this script with parameters.
I hope that explains what I am trying to do. I really have no idea how to make it trigger a site or whatever you can call it - hence why not posting anything that I have tried before posting this.
Thanks in advance.
To make an HTTP request from node, you may use the standard http package. You'll find examples in the standard documentation.
To make them in a simpler way, you may also use the request module. Using it, a http request is as simple as that :
var request = require('request');
request("https://yourwebsite.com/page.php?a=b", function(error, res, body){
if (error) console.log("error:", error);
else console.log('body of the response :', body);
})
I try to write a server which will manage some get requests like this:
GET http://some-server.aa:1337/action?param1=1000¶m2=1000
But I can't parse param1 and param2 from url because param2 not appear on server part.
app.get('/action', function(req, res) {
var parts = url.parse(req.url, true);
var query = parts.query;
console.log('keys: '+Object.keys(query)); //output: keys: caller
console.log('url: '+parts.path); // output: url:/action?param1=1000
});
I use express, url, and path modules. if I'l be able to receive on server full url, then
But before this, I need to be able to receive full path from req. Have any ideas?
UPD
how it's look from my side:
https://dl.dropboxusercontent.com/u/12720156/nodejsbug.png
Problem was not in node.js. It was in CURL request which I use. From browser it works fine.
Solution was found here: How to pass multiple parameters to cron job with curl?
with request: curl -sS 'http://server.aa:1337/action?param1=1¶m2=2' it works fine.
I am using Mikeal's request module to talk to the CouchDB HTTP API from an Express app. I can't use any other modules (such as nano) as this an academic project.
What I would like to do is get an image file, that has been uploaded from a form in a web app, and save it to my Couch as an attachment. To do this using curl is very simple:
curl -vX PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg?rev=2-2739352689
--data-binary #artwork.jpg -H "Content-Type: image/jpg"
What I can't wrap my head around is how to structure the PUT request using the request module. Express stores the file temporarily in the directory
/tmp/{doc._id}.jpg
How do I get the file from there to my couch? Pretty desperate here.
I haven't verified this, but you might be able to do this:
var
fs = require('fs'),
request = require('request'),
url = 'http://admin:password#127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg?rev=2-2739352689';
var requestStream = request.put(url);
requestStream.on('response', function (response) {
console.log(response);
});
fs.createReadStream('image.jpg').pipe(requestStream);