Receiving Files with NodeJS using connect - node.js

I'd like to receive pictures, audio and video files with nodejs.
I send them via phonegap as a http-request.
With nodeJS I use the connect plugin. I really don't understand what it does and how to manipulate the location the files are getting stored.
var http = require('http');
var connect = require('connect');
var app = connect();
var server = http.createServer(app);
app.use(connect.bodyParser());
app.use(function(req, res) {
console.log(req.files); // Here is object with uploaded files
});
server.listen(8070);
How can I tell connect to store the files somewhere else as in the temp-directory.
And how can I read the requests options to decide where I want to store that file.
Here's what a file is about:
{ file:
{ fieldName: 'file',
originalFilename: 'VID_20131211_124140.mp4',
path: 'C:\\Users\\krause\\AppData\\Local\\Temp\\4120-1fx90bk.mp4',
headers:
{ 'content-disposition': 'form-data; name="file"; filename="VID_20131211_124140.mp4"',
'content-type': 'video/mp4' },
ws:
{ _writableState: [Object],
writable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
path: 'C:\\Users\\krause\\AppData\\Local\\Temp\\4120-1fx90bk.mp4',
fd: null,
flags: 'w',
mode: 438,
start: undefined,
pos: undefined,
bytesWritten: 7046598,
closed: true,
open: [Function],
_write: [Function],
destroy: [Function],
close: [Function],
destroySoon: [Function],
pipe: [Function],
write: [Function],
end: [Function],
setMaxListeners: [Function],
emit: [Function],
addListener: [Function],
on: [Function],
once: [Function],
removeListener: [Function],
removeAllListeners: [Function],
listeners: [Function] },
size: 7046598,
name: 'VID_20131211_124140.mp4',
type: 'video/mp4' } }

I am assuming you just want to use this app to store the POST'ed file in a path other than tmp.
You can set the default upload directory by setting bodyParser.
In Express we do it by
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/my/files' }));
You can try this is connect:
app.use(connect.multipart({ uploadDir: path }));
Check details here
Personally what I do is, I copy the file from temp directory and put it in a relevant place (if you have different directories for different uploads) using node fs.

Related

How to test getDerivedStateFromProps with jest

I have looked at How to test getDerivedStateFromProps with Jest and Enzyme but it is not working for me. here is my test
it('should be red processing only, routing, security grey while bg tasks are running', () => {
component = mount(
<ProcessingStatus store={store}/>
);
const instance = component.instance();
//console.log(instance)
component.setProps({ processing_status: {
header:{
error: true,
message: 'This comms matrix is currently processing flows',
statusCode: 200
},
body: {}
} });
console.log(component.state())
console.log(component.props())
expect(component.find(TrafficLight).length).toEqual(3);
expect(component.find(TrafficLight).at(0).props().RedOn).toEqual(true);
expect(component.find(TrafficLight).at(0).props().AmberOn).toEqual(false);
expect(component.find(TrafficLight).at(0).props().GreenOn).toEqual(false);
});
component.state() or instance.state is always empty {}.
This is the contents of component.props()
{ store:
{ getState: [Function: getState],
getActions: [Function: getActions],
dispatch:
{ [Function: mockConstructor]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockRestore: [Function],
mockReturnValueOnce: [Function],
mockResolvedValueOnce: [Function],
mockRejectedValueOnce: [Function],
mockReturnValue: [Function],
mockResolvedValue: [Function],
mockRejectedValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockName: [Function],
getMockName: [Function] },
clearActions: [Function: clearActions],
subscribe: [Function: subscribe],
replaceReducer: [Function: replaceReducer] },
processing_status:
{ header:
{ error: true,
message: 'This comms matrix is currently processing flows',
statusCode: 200 },
body: {} } }
I need this to be triggered as depending on my props values the state changes and renders other conditions.
If it is a connected component it needs to be retrieved differently.
component = mount(
<ProcessingStatus store={store}/>
);
const instance = component.find('ProcessingStatus').instance();
component.setProps({ processing_status: {
header:{
error: true,
message: 'This comms matrix is currently processing flows',
statusCode: 200
},
body: {}
} });
console.log(instance.state);
Provided me with
console.log tests/jest/components/common/ProcessingStatus/index.test.js:122
{ nextStep: 'This comms matrix is currently processing flows' }
What is not clear in previous answers is if there are connected or not and if shallow or mount is being used

unable to send file to express/multer backend

I have the following code listing the files in the folder. Then trying to send them to the post/upload in the express backend. But the files is always undefined. However it seems like size and other info get through.
Client send
const axios = require('axios');
var FormData = require('form-data');
//requiring path and fs modules
const path = require('path');
const fs = require('fs');
//joining path of directory
const directoryPath = path.join(__dirname, '');
//passsing directoryPath and callback function
fs.readdir(directoryPath, function (err, files) {
//handling error
if (err) {
return console.log('Unable to scan directory: ' + err);
}
//listing all files using forEach
var postInfo = files.forEach(async function (file) {
const form_data = new FormData();
form_data.append('file', fs.createReadStream(file));
const request_config = {
method: "post",
url: 'http://localhost:8080/upload',
port: 8080,
headers: {
"Content-Type": "multipart/form-data; boundary=form_data._boundary"
},
data: form_data
};
try {
var req = await axios(request_config);
// Do whatever you want to do with the file
console.log("Request: ", req);
} catch (e) {
console.error(e);
}
});
console.log(postInfo);
});
receiving code in the backend
const http = require('http')
const port = 8080
const express = require('express');
const app = express();
const multer = require('multer');
const server = http.createServer(app)
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({ storage }).single('file');
app.post('/upload', upload, (req, res) => {
console.log(req.files) // this does log the uploaded image data.
})
// bind the server on port
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
Log:
node file-receive.js
server is listening on 8080
undefined
undefined
undefined
response: undefined,
isAxiosError: true,
toJSON: [Function] }
{ Error: socket hang up
at createHangUpError (_http_client.js:323:15)
at Socket.socketOnEnd (_http_client.js:426:23)
at Socket.emit (events.js:194:15)
at endReadableNT (_stream_readable.js:1103:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
code: 'ECONNRESET',
config:
{ url: 'http://localhost:8080/upload',
method: 'post',
data:
FormData {
_overheadLength: 169,
_valueLength: 0,
_valuesToMeasure: [Array],
writable: false,
readable: true,
dataSize: 0,
maxDataSize: 2097152,
pauseStreams: true,
_released: true,
_streams: [],
_currentStream: null,
_insideLoop: false,
_pendingNext: false,
_boundary: '--------------------------046964089061111513973474',
_events: [Object],
_eventsCount: 1 },
headers:
{ Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'axios/0.19.2' },
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
port: 8080 },
request:
Writable {
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: false,
errorEmitted: false,
emitClose: true,
bufferedRequestCount: 0,
corkedRequestsFree: [Object] },
writable: true,
_events:
[Object: null prototype] {
response: [Function: handleResponse],
error: [Function: handleRequestError] },
_eventsCount: 2,
_maxListeners: undefined,
_options:
{ protocol: 'http:',
maxRedirects: 21,
maxBodyLength: 10485760,
path: '/upload',
method: 'POST',
headers: [Object],
agent: undefined,
agents: [Object],
auth: undefined,
hostname: 'localhost',
port: '8080',
nativeProtocols: [Object],
pathname: '/upload' },
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 983,
_requestBodyBuffers: [ [Object], [Object], [Object] ],
_onNativeResponse: [Function],
_currentRequest:
ClientRequest {
_events: [Object],
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: true,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Socket],
connection: [Socket],
_header:
'POST /upload HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: axios/0.19.2\r\nHost: localhost:8080\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
timeout: undefined,
method: 'POST',
path: '/upload',
_ended: false,
res: null,
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable: [Circular],
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]: [Object] },
_currentUrl: 'http://localhost:8080/upload' },
response: undefined,
isAxiosError: true,
toJSON: [Function] }
I was able to reproduce the issue and was able to fix the code with the following ajdustments (note that I'm uploading a single file for sake of simplicty).
On the client side you basically just provide the form-data to axios and call getHeaders() to get the already set up header - also you need to adjust the file-name in the form.
// client.js
...
const form_data = new FormData();
form_data.append('file', fs.createReadStream(__dirname + '/file-you-want-to-upload'));
const request_config = {
method: "post",
url: 'http://localhost:8080/upload',
port: 8080,
data: form_data,
headers: form_data.getHeaders()
};
...
On the backend side you need to make sure to access file not files as you're using upload.single and actually send a response in your handler as the resposse would hang otherwise:
//server.js
...
const upload = multer({storage}).single('file');
app.post('/upload', upload, (req, res) => {
console.log(req.file) // this does log the uploaded image data.
res.send("File uploaded");
});
...

MongoDB error while retrieving collection

I'm having a problem getting collection from the database in my Node.js application. I'm using Mongodb 3.6.
That's how I set it up:
var moment = require('moment');
var MongoClient = require('mongodb').MongoClient;
/*
===========================================================================
DB setup
===========================================================================
*/
var state = {
db: null,
}
function get() {
return state.db;
}
exports.connect_database = function(done) {
if (state.db) return done()
MongoClient.connect(process.env.DATABASE_URL, function(err, db) {
if (err) return done(err)
state.db = db
done()
})
}
/* some other functions ... */
exports.return_collection = function(collection_name, callback) {
var result_array = [];
var collection = get().getCollection(collection_name);
var result = collection.find()
result.forEach(function(res) {
result_array.push(res);
}, function(error) {
console.log("error: ")
console.log(error);
if (!error)
callback(result_array);
});
}
In the main file I do:
'use strict';
// LIB IMPORTS
var env = require('node-env-file');
env(__dirname + '/.env');
// LOCAL IMPORTS
var aux = require('./modules/aux.js');
var scheduler = require('./modules/scheduler.js');
var Bot = require('./modules/bot.js');
/*
===========================================================================
DB setup
===========================================================================
*/
aux.connect_database((err) => {
if (err) {
console.log('Unable to connect to Mongo.')
process.exit(1)
} else {
console.log('Connected to db.');
}
})
I can see in the log the Connected to db. prompt, so the connection works fine. After that I try to call some function to add/retrieve data from the db and i get the error:
TypeError: get(...).getCollection is not a function
at Object.exports.return_collection
If I try to print the state.db variable I get the following result:
MongoClient {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
s:
{ url: 'mongodb://localhost:27017/BotDb',
options:
{ socketOptions: {},
read_preference_tags: null,
readPreference: [Object],
dbName: 'slackBotDb',
servers: [Object],
server_options: [Object],
db_options: [Object],
rs_options: [Object],
mongos_options: [Object],
socketTimeoutMS: 360000,
connectTimeoutMS: 30000,
promiseLibrary: [Function: Promise] },
promiseLibrary: [Function: Promise],
dbCache: {},
sessions: [] },
topology:
Server {
domain: null,
_events:
{ serverOpening: [Function],
serverDescriptionChanged: [Function],
serverHeartbeatStarted: [Function],
serverHeartbeatSucceeded: [Function],
serverHeartbeatFailed: [Function],
serverClosed: [Function],
topologyOpening: [Function],
topologyClosed: [Function],
topologyDescriptionChanged: [Function],
joined: [Function],
left: [Function],
ping: [Function],
ha: [Function],
authenticated: [Function],
error: [Function],
timeout: [Function],
close: [Function],
parseError: [Function],
open: [Object],
fullsetup: [Object],
all: [Object],
reconnect: [Function] },
_eventsCount: 22,
_maxListeners: undefined,
clientInfo:
{ driver: [Object],
os: [Object],
platform: 'Node.js v7.10.0, LE' },
s:
{ coreTopology: [Object],
sCapabilities: null,
clonedOptions: [Object],
reconnect: true,
emitError: true,
poolSize: 5,
storeOptions: [Object],
store: [Object],
host: 'localhost',
port: 27017,
options: [Object],
sessionPool: [Object],
promiseLibrary: [Function: Promise] } } }
What am I missing? In the mongo console everything looks fine:
> db.getCollection("users");
BotDb.users
I can't find any function named getCollection in the API documentation for the Node.js MongoDB native driver. Collections are usually fetched with collection('mycoll'). So you can rewrite this line:
var collection = get().getCollection(collection_name);
to
var collection = get().collection(collection_name);
Note that if you use v3.0 or later of the driver you have to modify the connect function as well. There were some changes done to the connection functions (see here). The callback now returns a client object rather than the db object. So you'll have to change your function to:
exports.connect_database = function(done) {
if (state.db) return done()
MongoClient.connect(process.env.DATABASE_URL, function(err, client) {
if (err) return done(err);
state.db = client.db('database_name');
done();
})
}
Note the 'database_name' string. It should be the name of your database.

azure blob storage node.js backend

I'm following this article on how to upload a blob into a container. This is what I've have
var azure = require('azure-storage');
var blobSvc = azure.createBlobServiceAnonymous('https://<storage-name>.blob.core.windows.net/');
exports.post = function(request, response) {
console.log(request.files); // [1]
blobSvc.createBlockBlobFromLocalFile('dubfiles', 'myblob', request.files.file.name, function(error, result, response){
if(!error){
// file uploaded
console.log(response); //[2]
console.log(result); // [3]
}
});
};
[1] Logs this
{ file:
{ domain: null,
_events: null,
_maxListeners: 10,
size: 859552,
path: 'D:\\local\\Temp\\155976e3a6b8e0aa871c5deee05af9f2',
name: 'heuristic-serch.pdf',
type: 'application/pdf',
hash: false,
lastModifiedDate: Tue Jun 23 2015 08:43:55 GMT+0000 (Coordinated Universal Time),
_writeStream: {
domain: null,
_events: null,
_maxListeners: 10,
path: 'D:\\local\\Temp\\155976e3a6b8e0aa871c5deee05af9f2',
fd: 3,
writable: false,
flags: 'w',
encoding: 'binary',
mode: 438,
bytesWritten: 859552,
busy: false,
_queue: [],
_open: [Function],
drainable: true,
flush: [Function],
write: [Function],
end: [Function],
destroy: [Function],
destroySoon: [Function],
pipe: [Function],
setMaxListeners: [Function],
emit: [Function],
addListener: [Function],
on: [Function],
once: [Function],
removeListener: [Function],
removeAllListeners: [Function],
listeners: [Function] },
open: [Function],
toJSON: [Function],
write: [Function],
end: [Function],
setMaxListeners: [Function],
emit: [Function],
addListener: [Function],
on: [Function], once: [Function],
removeListener: [Function],
removeAllListeners: [Function],
listeners: [Function]
}
}
[2] Logs no response to logs
[3] Logs no result to logs
The container is empty when I check on the azure management portal.
How can this be done correctly?
I'm now able to upload a blob to a container. This is what I have
var azure = require('azure-storage');
exports.post = function(request, response) {
var accountName = request.service.config.appSettings.STORAGE_ACCOUNT_NAME; // storage account name at appSettings
var accountKey = request.service.config.appSettings.STORAGE_ACCOUNT_ACCESS_KEY; //storage account key at appSettings
var host = accountName + '.blob.core.windows.net';
var container = 'container_name';
var blobSvc = azure.createBlobService(accountName, accountKey, host);
blobSvc.createContainerIfNotExists(container, {publicAccessLevel : 'blob'}, function(error, result, response){
if(!error){
console.log('no error occurred!'); // logs if no error occurred
console.log(result); // logs false if container already exists
console.log(response); // logs response including the etag
//Container exists and allows
//anonymous read access to blob
//content and metadata within this container
blobSvc.createBlockBlobFromLocalFile(container, request.files.file.name, request.files.file.path, function(error, result, response){
if(!error){
// file uploaded
// console.log(error);
console.log(response); // logs response
console.log(result); // logs result
}
});
}
});
};

Form is undefined when using connect-form module

I have an express app that I want to use the connect-form module on to handle some file upload forms. I followed the examples in the express GitHub repo and on the connect-form but when I call req.form.complete(function(){}) I get an error that I Cannot call method 'complete' of undefined. Here is the code that I have:
var express = require('express'),
knox = require('knox'),
form = require('connect-form')/*,
controller = require('controller').Controller*/;
var app = module.exports = express.createServer();
// Configuration
var port = process.env.PORT || 3000;
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
form({ keepExtensions: true });
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', function(req, res){
res.render('index', {
title: 'Express'
});
});
app.get('/manage/new', function(req, res){
res.render('manage/new', {
title: 'Create a new widget'
});
});
app.post('/manage/new', function(req, res, next){
if(!req.form){
res.send('Form not submitted.', {'Content-Type': 'text/plain'}, 500);
console.log(req);
}
else{
req.form.complete(function(err, fields, files){
if(err) next(err);
else {
console.log('\nuploaded %s to %s', files.download.filename, files.download.path);
res.redirect('back');
}
});
console.log(req.form);
}
});
app.listen(port);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
And my Jade template:
h1= title
#wrapper
#main
form(method="post", enctype="multipart/form-data", name="create-widget")
.errors
fieldset
legend Band / Album Information
p
label.tooltip(for="txtTitle", data-tooltip="Band name or title to use on widget.") Band Name
br
input#txtTitle.input_full(name="title", placeholder="The Beatles")
p
label.tooltip(for="txtAlbum", data-tooltip="Album title shown on widget") Album
br
input#txtAlbum.input_full(name="album", placeholder="Magical Mystery Tour")
p
label.tooltip(for="fileDownload", data-tooltip="File to be downloaded after submitting form on Widget") Download
br
input#fileDownload.input_full(name="download", type="file")
#actions
input(type="submit", value="Generate Widget")
Is there something I've done wrong with my code? Also when uploading the download field, I actually want to upload the file straight to an S3 bucket. Do I have access to the stream as it is being uploaded so as to have the upload run faster?
Edit
Here is the contents of the req object when I submit the form:
{ socket:
{ bufferSize: 0,
fd: 6,
type: 'tcp4',
allowHalfOpen: true,
_readWatcher:
{ socket: [Circular],
callback: [Function: onReadable] },
destroyed: false,
readable: true,
_writeQueue: [],
_writeQueueEncoding: [],
_writeQueueFD: [],
_writeQueueCallbacks: [],
_writeWatcher:
{ socket: [Circular],
callback: [Function: onWritable] },
writable: true,
_writeImpl: [Function],
_readImpl: [Function],
_shutdownImpl: [Function],
remoteAddress: '127.0.0.1',
remotePort: 51588,
server:
{ stack: [Object],
connections: 1,
allowHalfOpen: true,
watcher: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: {},
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true,
type: 'tcp4',
fd: 7 },
ondrain: [Function],
_idleTimeout: 120000,
_idleNext:
{ repeat: 120,
_idleNext: [Circular],
_idlePrev: [Circular],
callback: [Function] },
_idlePrev:
{ repeat: 120,
_idleNext: [Circular],
_idlePrev: [Circular],
callback: [Function] },
_idleStart: Fri, 21 Oct 2011 16:08:07 GMT,
_events:
{ timeout: [Function],
error: [Function],
close: [Function] },
ondata: [Function],
onend: [Function],
_httpMessage: null },
connection:
{ bufferSize: 0,
fd: 6,
type: 'tcp4',
allowHalfOpen: true,
_readWatcher:
{ socket: [Circular],
callback: [Function: onReadable] },
destroyed: false,
readable: true,
_writeQueue: [],
_writeQueueEncoding: [],
_writeQueueFD: [],
_writeQueueCallbacks: [],
_writeWatcher:
{ socket: [Circular],
callback: [Function: onWritable] },
writable: true,
_writeImpl: [Function],
_readImpl: [Function],
_shutdownImpl: [Function],
remoteAddress: '127.0.0.1',
remotePort: 51588,
server:
{ stack: [Object],
connections: 1,
allowHalfOpen: true,
watcher: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: {},
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true,
type: 'tcp4',
fd: 7 },
ondrain: [Function],
_idleTimeout: 120000,
_idleNext:
{ repeat: 120,
_idleNext: [Circular],
_idlePrev: [Circular],
callback: [Function] },
_idlePrev:
{ repeat: 120,
_idleNext: [Circular],
_idlePrev: [Circular],
callback: [Function] },
_idleStart: Fri, 21 Oct 2011 16:08:07 GMT,
_events:
{ timeout: [Function],
error: [Function],
close: [Function] },
ondata: [Function],
onend: [Function],
_httpMessage: null },
httpVersion: '1.1',
complete: false,
headers:
{ host: '127.0.0.1:5000',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:6.0) Gecko/20100101 Firefox/6.0',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-us,en;q=0.5',
'accept-encoding': 'gzip, deflate',
'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
connection: 'keep-alive',
referer: 'http://127.0.0.1:5000/manage/new',
'content-type': 'multipart/form-data; boundary=---------------------------20072377098235644401115438165',
'content-length': '247075' },
trailers: {},
readable: true,
url: '/manage/new',
method: 'POST',
statusCode: null,
client:
{ bufferSize: 0,
fd: 6,
type: 'tcp4',
allowHalfOpen: true,
_readWatcher:
{ socket: [Circular],
callback: [Function: onReadable] },
destroyed: false,
readable: true,
_writeQueue: [],
_writeQueueEncoding: [],
_writeQueueFD: [],
_writeQueueCallbacks: [],
_writeWatcher:
{ socket: [Circular],
callback: [Function: onWritable] },
writable: true,
_writeImpl: [Function],
_readImpl: [Function],
_shutdownImpl: [Function],
remoteAddress: '127.0.0.1',
remotePort: 51588,
server:
{ stack: [Object],
connections: 1,
allowHalfOpen: true,
watcher: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: {},
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true,
type: 'tcp4',
fd: 7 },
ondrain: [Function],
_idleTimeout: 120000,
_idleNext:
{ repeat: 120,
_idleNext: [Circular],
_idlePrev: [Circular],
callback: [Function] },
_idlePrev:
{ repeat: 120,
_idleNext: [Circular],
_idlePrev: [Circular],
callback: [Function] },
_idleStart: Fri, 21 Oct 2011 16:08:07 GMT,
_events:
{ timeout: [Function],
error: [Function],
close: [Function] },
ondata: [Function],
onend: [Function],
_httpMessage: null },
httpVersionMajor: 1,
httpVersionMinor: 1,
upgrade: false,
originalUrl: '/manage/new',
query: {},
app:
{ stack:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
connections: 1,
allowHalfOpen: true,
watcher: { host: [Circular], callback: [Function] },
_events:
{ request: [Function],
connection: [Function: connectionListener],
listening: [Function] },
httpAllowHalfOpen: false,
cache: {},
settings:
{ env: 'development',
hints: true,
views: '/Users/davejlong/Workspace/Node/Widget/views',
'view engine': 'jade' },
redirects: {},
isCallbacks: {},
_locals: { settings: [Object], app: [Circular] },
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes:
{ app: [Circular],
routes: [Object],
params: {},
_params: [],
middleware: [Function] },
router: [Getter],
__usedRouter: true,
type: 'tcp4',
fd: 7 },
res:
{ output: [],
outputEncodings: [],
writable: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
_hasBody: true,
_trailer: '',
finished: true,
socket: null,
connection: null,
_events: { finish: [Function] },
_headers:
{ 'x-powered-by': 'Express',
'content-type': 'text/plain; charset=utf-8',
'content-length': 19 },
_headerNames:
{ 'x-powered-by': 'X-Powered-By',
'content-type': 'Content-Type',
'content-length': 'Content-Length' },
app:
{ stack: [Object],
connections: 1,
allowHalfOpen: true,
watcher: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: {},
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true,
type: 'tcp4',
fd: 7 },
req: [Circular],
charset: 'utf-8',
statusCode: 500,
_header: 'HTTP/1.1 500 Internal Server Error\r\nX-Powered-By: Express\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 19\r\nConnection: keep-alive\r\n\r\n',
_headerSent: true },
next: [Function: next],
originalMethod: 'POST',
_route_index: 0,
route:
{ path: '/manage/new',
method: 'post',
callbacks: [ [Function] ],
keys: [],
regexp: /^\/manage\/new\/?$/i,
params: [] },
params: [] }
Guess the form is not submitted from brower side, see example provided on http://visionmedia.github.com/connect-form/
var form = require('connect-form');
var server = connect.createServer(
form({ keepExtensions: true }),
function(req, res, next){
// Form was submitted
if (req.form) {
// Do something when parsing is finished
// and respond, or respond immediately
// and work with the files.
req.form.onComplete = function(err, fields, files){
res.writeHead(200, {});
if (err) res.write(JSON.stringify(err.message));
res.write(JSON.stringify(fields));
res.write(JSON.stringify(files));
res.end();
};
// Regular request, pass to next middleware
} else {
next();
}
}
);
"if (req.form)" in the example makes sure that form is indeed submitted ! You ought to do that as well as you may not be able to control what is getting posted to your APIs !!
I'm not sure why connect-form didn't work, but I found that it was written on top of the Formidable module, so I took that and just used that in my router instead and it properly picked up the form:
var sys = require('sys'),
express = require('express'),
knox = require('knox'),
formidable = require('formidable'),
controller = require('./controller').Controller;
var app = module.exports = express.createServer();
/* ================================================================ */
/* Configuration */
/* ================================================================ */
var port = process.env.PORT || 3000;
var hostName = 'http://download.comeandlive.com';
controller.setup(hostName, 80);
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
/* ================================================================ */
/* Routes */
/* ================================================================ */
app.get('/', function(req, res){
res.redirect('http://comeandlive.com', 301);
});
/* ================================ */
/* Administration Routes */
/* ================================ */
app.get('/manage', function(req, res){
res.render('manage/index', {
title: 'Widget Administration'
});
})
app.get('/manage/new', function(req, res){
res.render('manage/new', {
title: 'Create a new widget'
});
});
app.post('/manage/new', function(req, res, next){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files){
res.header('Content-Type', 'text/plain');
res.send('Received upload:\n\n' + sys.inspect({fields:fields, files:files}));
});
});
app.listen(port);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);

Resources