diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6358a63 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) +Copyright (c) 2012 Sam Thompson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..868badf --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# http-post + +This utility extends the funcationlity of the 'http' library in stock node.js. +It returns a post request function in a very similar way to node's [http.get()](http://nodejs.org/api/http.html#http_http_get_options_callback). + +In the same style as `http.get()`, this function calls `req.end()` automatically + +## Installing + + npm install http-post + +## Usage + + http-post(options, data[, files[, callback]]) + +or + + http-post(options, data[, callback]) + +### options + +Options are the same as the ones for [http.request()](http://nodejs.org/api/http.html#http_http_request_options_callback) +except `method` will always be forced to `POST`. Note that `options` can be +replaced with the full URI of the request similar to `http.get` allowing for +even greater flexiblity in your post requests. + +### data + +Data should be key/value pairs of form data. This does not handle file data, +see the `files` option below for more information on uploading files. + + var data = { + name: "Sam", + email: "sam@emberlabs.org", + gender: "m", + languages: [ + "C", + "C++", + "Java", + "JavaScript", + "PHP", + "Python" + ] + } + +Pass it an empty array if you do not need to send any form data. + +### files + +TBA + +### callback + +Callback is the same from [http.request()](http://nodejs.org/api/http.html#http_http_request_options_callback). +It accepts an instance of [http.ClientResponce](http://nodejs.org/api/http.html#http_http_clientresponse) +that has been created during the time of the request. + +## Return + +Returns an instance of [http.ClientRequest](http://nodejs.org/api/http.html#http_class_http_clientrequest) + +## Examples + +`Setting up` + + var http = require('http'); + http.post = require('http-post'); + +`Posting data` + + http.post('http://localhost/postscript.php', { name: 'Sam', email: 'sam@emberlabs.org' }, function(res){ + response.setEncoding('utf8'); + res.on('data', function(chunk) { + console.log(chunk); + }); + }); + +## License + +[The MIT License](http://opensource.org/licenses/mit-license.php) diff --git a/index.js b/index.js new file mode 100644 index 0000000..5c86789 --- /dev/null +++ b/index.js @@ -0,0 +1,108 @@ +/** + * http-post + * + * (c) copyright 2012 Sam Thompson + * License: The MIT License - http://opensource.org/licenses/mit-license.php + */ + +module.exports = function(options, data, files, fn) { + if (typeof(files) == 'function' || typeof(files) == 'undefined') { + fn = files; + files = []; + } + + if (typeof(fn) != 'function') { + fn = function() {}; + } + + if (typeof(options) == 'string') { + var options = require('url').parse(options); + } + + var fs = require('fs'); + var endl = "\r\n"; + var length = 0; + var contentType = ''; + + // If we have files, we have to chose multipart, otherweise we just stringify the query + if (files.length) { + //var boundary = '-----' + Math.random(); + var boundary = '------WebKitFormBoundary7C9feEVvdkuBaezA'; + var toWrite = []; + + for(var k in data) { + toWrite.push(boundary + endl); + toWrite.push('Content-Disposition: form-data; name="' + k + '"' + endl); + toWrite.push(endl); + toWrite.push(data[k] + endl); + } + + var name = '', stats; + for (var k in files) { + if (fs.existsSync(files[k].path)) { + // Determine the name + name = (typeof(files[k].name) == 'string') ? files[k].name : files[k].path.replace(/\\/g,'/').replace( /.*\//, '' ); + + // Determine the size and store it in our files area + stats = fs.statSync(files[k].path); + files[k].length = stats.size; + + toWrite.push(boundary + endl); + toWrite.push('Content-Disposition: form-data; name="' + files[k].param + '"; filename="' + name + '"' + endl); + toWrite.push('Content-Type: image/png'); + toWrite.push(endl); + toWrite.push(files[k]); + } + } + + // The final multipart terminator + toWrite.push(boundary + '--' + endl); + + // Now that toWrite is filled... we need to determine the size + for(var k in toWrite) { + length += toWrite[k].length; + } + + contentType = 'multipart/form-data; boundary=' + boundary; + } + else { + data = require('querystring').stringify(data); + + length = data.length; + contentType = 'application/x-www-form-urlencoded'; + } + + options.method = 'POST'; + options.headers = { + 'Content-Type': contentType, + 'Content-Length': length + }; + + var req = require('http').request(options, function(responce) { + fn(responce); + }); + + // Multipart and form-urlencded work slightly differnetly for sending + if (files.length) { + var fp, buf, n; + for(var k in toWrite) { + if (typeof(toWrite[k]) == 'string') { + req.write(toWrite[k]); +// process.stdout.write(toWrite[k]); + } + else { +// process.stdout.write('FILE: ' + toWrite[k]); +// process.stdout.write(endl); + // @todo make it work better for larger files + req.write(fs.readFileSync(toWrite[k].path)); + req.write(endl); + } + } + } + else { + req.write(data); + } + req.end(); + + return req; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2dcd928 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "http-post", + "description": "Shortcut method similar to http.get() for HTTP POST request with support for data and files", + "author": { + "name": "Sam Thompson", + "email": "sam@emberlabs.org" + }, + "contributors": [ + { + "name": "Matthew Jones" + } + ], + "keywords": [ + "http", + "post", + "upload", + "file", + "url" + ], + "bugs": "https://github.com/samt/http-post/issues", + "version": "0.0.1", + "main": "index", + "repository": { + "type": "git", + "url": "https://github.com/samt/http-post.git" + } +}