Code Monkey home page Code Monkey logo

node-httpreq's Introduction

node-httpreq

node-httpreq is a node.js library to do HTTP(S) requests the easy way

Do GET, POST, PUT, PATCH, DELETE, OPTIONS, upload files, use cookies, change headers, ...

This module helps you fight TLS fingerprinting! See the shuffleCiphers option below.

Donate

If you've benefited from this module in any way, please consider donating!

Thank you for your support!

Install

You can install httpreq using the Node Package Manager (npm):

npm install httpreq

Simple example

var httpreq = require('httpreq');

httpreq.get('http://www.google.com', function (err, res) {
  if (err) return console.log(err);

  console.log(res.statusCode);
  console.log(res.headers);
  console.log(res.body);
  console.log(res.cookies);
});

Using await/async:

var httpreq = require('httpreq');

var res = await httpreq.get('http://www.google.com');

console.log(res.statusCode);
console.log(res.headers);
console.log(res.body);
console.log(res.cookies);

Use with async/await

This module has been updated to support async/await.

In the following examples, simply omit the callback parameter and prepend it with await.

Example:

var httpreq = require('httpreq');

var res = await httpreq.post('http://posttestserver.com/post.php', {
  parameters: {
    name: 'John',
    lastname: 'Doe'
  }
});

console.log(res.body);

How to use


httpreq.get(url, [options], callback)

Arguments

  • url: The url to connect to. Can be http or https.
  • options: (all are optional) The following options can be passed:
    • parameters: an object of query parameters
    • headers: an object of headers
    • cookies: an array of cookies
    • auth: a string for basic authentication. For example username:password
    • binary: true/false (default: false), if true, res.body will a buffer containing the binary data
    • allowRedirects: (default: true , only with httpreq.get() ), if true, redirects will be followed
    • maxRedirects: (default: 10 ). For example 1 redirect will allow for one normal request and 1 extra redirected request.
    • timeout: (default: none ). Adds a timeout to the http(s) request. Should be in milliseconds.
    • ciphers: Change the TLS ciphers if needed.
    • shuffleCiphers: Set to true if you want to shuffle the TLS ciphers to fight TLS fingerprinting.
    • proxy, if you want to pass your request through a http(s) proxy server:
      • host: eg: "192.168.0.1"
      • port: eg: 8888
      • protocol: (default: 'http' ) can be 'http' or 'https'
    • rejectUnauthorized: validate certificate for request with HTTPS. More here
  • callback(err, res): A callback function which is called when the request is complete. res contains the headers ( res.headers ), the http status code ( res.statusCode ) and the body ( res.body )

Example without options

var httpreq = require('httpreq');

httpreq.get('http://www.google.com', function (err, res){
  if (err) return console.log(err);

  console.log(res.statusCode);
  console.log(res.headers);
  console.log(res.body);
});

Example with options

var httpreq = require('httpreq');

httpreq.get('http://posttestserver.com/post.php', {
  parameters: {
    name: 'John',
    lastname: 'Doe'
  },
  headers:{
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:18.0) Gecko/20100101 Firefox/18.0'
  },
  cookies: [
    'token=DGcGUmplWQSjfqEvmu%2BZA%2Fc',
    'id=2'
  ]
}, function (err, res){
  if (err){
    console.log(err);
  }else{
    console.log(res.body);
  }
});

httpreq.post(url, [options], callback)

Arguments

  • url: The url to connect to. Can be http or https.
  • options: (all are optional) The following options can be passed:
    • parameters: an object of post parameters (content-type is set to application/x-www-form-urlencoded; charset=UTF-8)
    • json: if you want to send json directly (content-type is set to application/json)
    • files: an object of files to upload (content-type is set to multipart/form-data; boundary=xxx)
    • body: custom body content you want to send. If used, previous options will be ignored and your custom body will be sent. (content-type will not be set)
    • headers: an object of headers
    • cookies: an array of cookies
    • auth: a string for basic authentication. For example username:password
    • binary: true/false (default: false ), if true, res.body will be a buffer containing the binary data
    • allowRedirects: (default: false ), if true, redirects will be followed
    • maxRedirects: (default: 10 ). For example 1 redirect will allow for one normal request and 1 extra redirected request.
    • encodePostParameters: (default: true ), if true, POST/PUT parameters names will be URL encoded.
    • timeout: (default: none). Adds a timeout to the http(s) request. Should be in milliseconds.
    • proxy, if you want to pass your request through a http(s) proxy server:
      • host: eg: "192.168.0.1"
      • port: eg: 8888
      • protocol: (default: 'http' ) can be 'http' or 'https'
    • rejectUnauthorized: validate certificate for request with HTTPS. More here
  • callback(err, res): A callback function which is called when the request is complete. res contains the headers ( res.headers ), the http status code ( res.statusCode ) and the body ( res.body )

Example without extra options

var httpreq = require('httpreq');

httpreq.post('http://posttestserver.com/post.php', {
  parameters: {
    name: 'John',
    lastname: 'Doe'
  }
}, function (err, res){
  if (err){
    console.log(err);
  }else{
    console.log(res.body);
  }
});

Example with options

var httpreq = require('httpreq');

httpreq.post('http://posttestserver.com/post.php', {
  parameters: {
    name: 'John',
    lastname: 'Doe'
  },
  headers:{
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:18.0) Gecko/20100101 Firefox/18.0'
  },
  cookies: [
    'token=DGcGUmplWQSjfqEvmu%2BZA%2Fc',
    'id=2'
  ]
}, function (err, res){
  if (err){
    console.log(err);
  }else{
    console.log(res.body);
  }
});

httpreq.put(url, [options], callback)

Same options as httpreq.post(url, [options], callback)


### httpreq.delete(url, [options], callback)

Same options as httpreq.post(url, [options], callback)


### httpreq.options(url, [options], callback)

Same options as httpreq.get(url, [options], callback) except for the ability to follow redirects.


### Uploading files

You can still use httpreq.uploadFiles({url: 'url', files: {}}, callback), but it's easier to just use POST (or PUT):

Example

var httpreq = require('httpreq');

httpreq.post('http://posttestserver.com/upload.php', {
  parameters: {
    name: 'John',
    lastname: 'Doe'
  },
  files: {
    myfile: __dirname + '/file1.jpg',
    myotherfile: __dirname + '/file2.jpg'
  }
}, function (err, res){
  if (err) throw err;
});

Example 2

In case you want to use the same form name for multiple files:

var httpreq = require('httpreq');

httpreq.post('http://posttestserver.com/upload.php', {
  parameters: {
    name: 'John',
    lastname: 'Doe'
  },
  files: {
    myfiles: [__dirname + '/file1.jpg', __dirname + '/file.jpg']
  }
}, function (err, res){
  if (err) throw err;
});

Downloading a binary file

To download a binary file, just add binary: true to the options when doing a get or a post.

Example

var httpreq = require('httpreq');

httpreq.get('https://ssl.gstatic.com/gb/images/k1_a31af7ac.png', {binary: true}, function (err, res){
  if (err){
    console.log(err);
  }else{
    fs.writeFile(__dirname + '/test.png', res.body, function (err) {
      if(err)
        console.log("error writing file");
    });
  }
});

Downloading a file directly to disk

To download a file directly to disk, use the download method provided.

Downloading is done using a stream, so the data is not stored in memory and directly saved to file.

Example

var httpreq = require('httpreq');

httpreq.download(
  'https://ssl.gstatic.com/gb/images/k1_a31af7ac.png',
  __dirname + '/test.png'
, function (err, progress){
  if (err) return console.log(err);
  console.log(progress);
}, function (err, res){
  if (err) return console.log(err);
  console.log(res);
});

When specifying the progress callback (3th parameter), you cannot use async/await.


Sending a custom body

Use the body option to send a custom body (eg. an xml post)

Example

var httpreq = require('httpreq');

httpreq.post('http://posttestserver.com/post.php',{
  body: '<?xml version="1.0" encoding="UTF-8"?>',
  headers:{
    'Content-Type': 'text/xml',
  }},
  function (err, res) {
    if (err){
      console.log(err);
    }else{
      console.log(res.body);
    }
  }
);

Using a http(s) proxy

Example

var httpreq = require('httpreq');

httpreq.post('http://posttestserver.com/post.php', {
  proxy: {
    host: '10.100.0.126',
    port: 8888
  }
}, function (err, res){
  if (err){
    console.log(err);
  }else{
    console.log(res.body);
  }
});

httpreq.doRequest(options, callback)

httpreq.doRequest is internally used by httpreq.get() and httpreq.post(). You can use this directly. Everything is stays the same as httpreq.get() or httpreq.post() except that the following options MUST be passed:

  • url: the url to post the files to
  • method: 'GET', 'POST', 'PUT' or 'DELETE'

Run tests

Install all depedencies with

npm install

Install mocha with

npm install mocha -g

Run tests:

mocha test/tests.js

Run the async/await tests:

mocha test/tests-async.js

node-httpreq's People

Contributors

come2daddy avatar davepreston avatar fvdm avatar jpricket avatar mjj2000 avatar russellbeattie avatar samdecrock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

node-httpreq's Issues

Added 'head' support

Hi there. Not really an issue but I couldn't see a nice way to contact you - I added in support for http HEAD request as I needed it, and it was handy to have it for consistency. Modified httpreq is here. Would be great if you could drop it into master so we don't end up maintaining multiple versions (assuming you're happy with the code obviously!).

Also, thanks for a great a package!

httpreq.js.txt

corrupt binary uploads - headers inserted at top of file on the target

Using post to upload an mp4, once on the target, about 230 bytes of extra stuff appearing at head and tail of the file..

Extra bytes at Head...

-----------------------------uVaomvfVmZtjdNpVRQRGm1iSnxKwc
Content-Disposition: file; name="myfile"; filename="my-movie.mp4"
Content-Type: application/octet-stream

Extra bytes at Tail...

-----------------------------uVaomvfVmZtjdNpVRQRGm1iSnxKwc--

noticed similar issue here

my code....

`var httpreq = require('httpreq');

httpreq.post('https://api.parse.com/1/files/'+postfile, {
headers:{
'X-Parse-Application-Id': 'Mrc7',
'X-Parse-REST-API-Key': 'Kw7',
'Content-Type': 'video/mp4'
},
files:{
myfile: __dirname + "/" +postfile
},
binary: true
},
`

-rw-rw-r-- 1 rob rob 209156 Sep 25 19:11 my-movie-corrupted.mp4

-rw-rw-r-- 1 rob rob 208923 Sep 25 18:59 my-movie.mp4

Downloaded files can end truncated

The code here is incorrect since it is listening to the source stream "end" event which may trigger much sooner than the target stream has actually completed the writing to disk:

res.on ('end', function (err) {

Instead you must listen to the "finish" event on the downloadStream, to make sure the file is completely stored and closed in disk. You may have not noticed this problem since as long as the process is still alive the file will eventually complete, but if the process closes before, you end with a truncated file. Use case: "electron-simple-updater" will close after downloading the latest version of an app and most likely end with a truncated file that will end with the end-user having a broken electron app.

Possible EventEmitter memory leak detected.

Getting

(node:3393) Warning: Possible EventEmitter memory leak detected. 11 timeout listeners added. Use emitter.setMaxListeners() to increase limit
Warning: Possible EventEmitter memory leak detected. 11 timeout listeners added. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:259:19)
    at Socket.addListener (events.js:275:10)
    at Socket.Readable.on (_stream_readable.js:687:35)
    at ClientRequest.<anonymous> (/Users/samdecrock/projects/awesomproject/app/node_modules/httpreq/lib/httpreq.js:420:14)
    at emitOne (events.js:101:20)
    at ClientRequest.emit (events.js:188:7)
    at tickOnSocket (_http_client.js:568:7)
    at onSocketNT (_http_client.js:580:5)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Seems like the timeout handlers keep adding up. I'm using a keep-alive agent, so that might cause the problem.

@fvdm I saw that you switched to socket.on('timeout'), any reason why: 1428f5f ?

I'm going to switch back to using the request.setTimeout() handler.

Clean up the code

Hi Sam,

I'd like to clean up the code to make sure the style is consistent everywhere. It's a bit of a mess now.

Do you have a certain style or even styleguide in mind you'd like the code to follow?

Support for the OPTIONS method

Hi Sam. Thanks for the node-httpreq package (it's simple and easy to use)!

I'm using your httpntlm package and would like support for the OPTIONS method (I'm adding NTLM support to an existing REST client). I'll provide a pull request for httpreq to add the OPTIONS method and another for httpntlm to expose it.

I'd appreciate your consideration. Thanks!

Cipher Shuffling as implemented can end up sending old, slow, or insecure ciphers as top preference

https://httptoolkit.com/blog/tls-fingerprinting-node-js/

'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'TLS_AES_128_GCM_SHA256',

Those first 3 TLS_ prefixed ciphers are all modern and strongly recommended TLS v1.3 ciphers with no known current issues, and all modern clients will include those 3 first as their first three options, in some order. While Node.js picks the order above, any order of those is a pretty safe & reasonable bet. In a quick test on my machine, it seems like:

cURL 7.68 uses the same order as Node.js
Firefox uses TLS_AES_128_GCM_SHA256 (#3) then TLS_CHACHA20_POLY1305_SHA256 (#2) then TLS_AES_256_GCM_SHA384 (#1)
Chrome uses TLS_AES_128_GCM_SHA256 (#3) then TLS_AES_256_GCM_SHA384 (#1) then TLS_CHACHA20_POLY1305_SHA256 (#2)
The specific order has various performance & security trade-offs, and if you're writing extremely security or performance sensitive software you should absolutely investigate that in more detail, but in most software any ordering of these 3 is totally fine, secure, and performant. That means we can shuffle them up!

Post parameters with multiple values.

Hello,
I'm wondering if there's a way to assign multiple values to POST parameters. I'm working with a server that requires this formatting.

I've tried the following:
parameters: { ajaxfunc: 'ajax_writemodule', ajaxretfunc: 'writemodule', ajaxrnd: new Date().getTime(), ajaxargs: ['editmanufacturingnotes', 'manufacturingnotesmod', '31110', 'THIS IS A TEST'] }

It doesn't work. I've captured the form data and this is the raw information:
'ajaxfunc=ajax_writemodule&ajaxretfunc=writemodule&ajaxrnd=1477430594267&ajaxargs[]=editmanufacturingnotes&ajaxargs[]=manufacturingnotesmod&ajaxargs[]=31110&ajaxargs[]=THIS IS A TEST'

I can't add the brackets after the ajaxargs parameter. Is there a way to use the raw form data with this library?

node-httpreq exception

        var responsebody = Buffer.concat(chunks);
                         ^

TypeError: Object function Buffer(subject, encoding, offset) {
if (!(this instanceof Buffer)) {
return new Buffer(subject, encoding, offset);
}

var type;

// Are we slicing?
if (typeof offset === 'number') {
this.length = coerce(encoding);
this.parent = subject;
this.offset = offset;
} else {
// Find the length
switch (type = typeof subject) {
case 'number':
this.length = coerce(subject);
break;

  case 'string':
    this.length = Buffer.byteLength(subject, encoding);
    break;

  case 'object': // Assume object is an array
    this.length = coerce(subject.length);
    break;

  default:
    throw new Error('First argument needs to be a number, ' +
                    'array or string.');
}

if (this.length > Buffer.poolSize) {
  // Big buffer, just alloc one.
  this.parent = new SlowBuffer(this.length);
  this.offset = 0;

} else {
  // Small buffer.
  if (!pool || pool.length - pool.used < this.length) allocPool();
  this.parent = pool;
  this.offset = pool.used;
  pool.used += this.length;
}

// Treat array-ish objects as a byte array.
if (isArrayIsh(subject)) {
  for (var i = 0; i < this.length; i++) {
    this.parent[i + this.offset] = subject[i];
  }
} else if (type == 'string') {
  // We are a string
  this.length = this.write(subject, 0, encoding);
}

}

SlowBuffer.makeFastBuffer(this.parent, this, this.offset, this.length);
} has no method 'concat'
at IncomingMessage. (C:\Documents and Settings\david wilson\WebstormProjects\angular-socket-io\node_modules\httpreq\httpreq.js:125:30)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.parserOnMessageComplete as onMessageComplete
at Socket.socketOnData as ondata
at TCP.onread (net.js:374:27)

File handles not closed when there are redirects during the download of a file

In requestResponse the 'end' event for the response never calls downloadStream.end() if a redirect is encountered. On each redirect, a new downloadStream is created and the old file handles are orphaned. If you try access the file after downloading it, you get a "file open by another process" error until node.exe is shutdown.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.