What is popsicle?
Popsicle is a versatile HTTP request library for Node.js and the browser. It provides a simple and consistent API for making HTTP requests, handling responses, and managing various aspects of HTTP communication such as headers, query parameters, and request/response bodies.
What are popsicle's main functionalities?
Making HTTP Requests
This feature allows you to make HTTP requests to a specified URL. The example demonstrates a GET request to a JSON placeholder API, logging the status and body of the response.
const { request } = require('popsicle');
request('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log(response.status);
console.log(response.body);
})
.catch(error => {
console.error(error);
});
Handling Query Parameters
This feature allows you to include query parameters in your HTTP requests. The example demonstrates a GET request with a query parameter to filter posts by userId.
const { request } = require('popsicle');
request({
url: 'https://jsonplaceholder.typicode.com/posts',
query: { userId: 1 }
})
.then(response => {
console.log(response.status);
console.log(response.body);
})
.catch(error => {
console.error(error);
});
Setting Headers
This feature allows you to set custom headers for your HTTP requests. The example demonstrates setting the 'Content-Type' header to 'application/json'.
const { request } = require('popsicle');
request({
url: 'https://jsonplaceholder.typicode.com/posts',
headers: { 'Content-Type': 'application/json' }
})
.then(response => {
console.log(response.status);
console.log(response.body);
})
.catch(error => {
console.error(error);
});
Handling Request and Response Bodies
This feature allows you to handle request and response bodies. The example demonstrates a POST request with a JSON body to create a new post.
const { request } = require('popsicle');
request({
method: 'POST',
url: 'https://jsonplaceholder.typicode.com/posts',
body: { title: 'foo', body: 'bar', userId: 1 },
headers: { 'Content-Type': 'application/json' }
})
.then(response => {
console.log(response.status);
console.log(response.body);
})
.catch(error => {
console.error(error);
});
Other packages similar to popsicle
axios
Axios is a popular promise-based HTTP client for the browser and Node.js. It provides a simple API for making HTTP requests and handling responses, similar to Popsicle. Axios is known for its ease of use and wide adoption in the JavaScript community.
node-fetch
Node-fetch is a lightweight module that brings `window.fetch` to Node.js. It is a minimalistic library that provides a simple API for making HTTP requests, similar to the Fetch API in the browser. Node-fetch is often used for its simplicity and compatibility with the Fetch API standard.
superagent
Superagent is a small progressive client-side HTTP request library, and Node.js module with a similar API. It provides a flexible and powerful API for making HTTP requests and handling responses. Superagent is known for its extensive feature set and ease of use.
Popsicle is designed to be easiest way for making HTTP requests, offering a consistent and intuitive API that works on both node and the browser.
popsicle('/users.json')
.then(function (res) {
console.log(res.body)
})
Installation
npm install popsicle --save
bower install popsicle --save
You will need a promise polyfill for older browsers and node <= 0.11.12
.
npm install es6-promise --save
bower install es6-promise --save
Apply the polyfill.
require('es6-promise').polyfill()
window.ES6Promise.polyfill()
Usage
var popsicle = require('popsicle')
popsicle({
method: 'POST',
url: 'http://example.com/api/users',
body: {
username: 'blakeembrey',
password: 'hunter2'
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function (res) {
console.log(res.status)
console.log(res.body)
console.log(res.get('Content-Type'))
})
Handling Requests
- url The resource URI
- method The HTTP request method (default:
"GET"
) - headers An object of HTTP headers, header name to value (default:
{}
) - query An object or string to be appended to the URL
- body An object, string or form data to pass with the request
- timeout The number of milliseconds before cancelling the request (default:
Infinity
) - parse Optionally skip response parsing (default:
true
)
Node only
- jar An instance of a cookie jar (default:
null
) - agent Custom HTTP pooling agent (default: infinity-agent)
- maxRedirects Override the number of redirects to allow (default:
10
) - rejectUnauthorized Reject invalid SSL certificates (default:
true
) - stream Stream the HTTP response body (default:
false
)
Browser only
- withCredentials Send cookies with CORS requests (default:
false
)
Automatically Serializing Body
Popsicle can automatically serialize the request body to a string. If an object is supplied, it'll automatically stringify as JSON unless the Content-Type
header was set otherwise. If the Content-Type
is multipart/form-data
or application/x-www-form-urlencoded
, it can also be automatically serialized.
popsicle({
url: 'http://example.com/api/users',
body: {
username: 'blakeembrey'
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
Multipart Request Bodies
You can manually create a form data instance by calling popsicle.form
. When you pass a form data instance, it'll automatically set the correct Content-Type
- complete with boundary.
var form = popsicle.form({
username: 'blakeembrey',
profileImage: fs.createReadStream('image.png')
})
popsicle({
method: 'POST',
url: '/users',
body: form
})
Aborting Requests
All requests can be aborted before or during execution by calling Request#abort
.
var req = popsicle('http://example.com')
setTimeout(function () {
req.abort()
}, 100)
req.catch(function (err) {
console.log(err)
})
Progress
The request object can also be used to check progress at any time.
- req.uploadSize Current upload size in bytes
- req.uploadTotal Total upload size in bytes
- req.uploaded Total uploaded as a percentage
- req.downloadSize Current download size in bytes
- req.downloadTotal Total download size in bytes
- req.downloaded Total downloaded as a percentage
- req.completed Total uploaded and downloaded as a percentage
All percentage properties (req.uploaded
, req.downloaded
, req.completed
) will be a number between 0
and 1
. When the total size is unknown (no Content-Length
header), the percentage will automatically increment on each chunk of data returned (this will not be accurate). Aborting a request will automatically emit a completed progress event.
var req = popsicle('http://example.com')
req.uploaded
req.downloaded
req.progress(function (e) {
console.log(e)
})
req.then(function (res) {
console.log(req.downloaded)
})
Cookie Jar (Node only)
You can create a reusable cookie jar instance for requests by calling popsicle.jar
.
var jar = request.jar()
popsicle({
method: 'POST',
url: '/users',
jar: jar
})
Handling Responses
Promises and node-style callbacks are supported.
Promises
Promises are the most expressive interface. Just chain using Request#then
or Request#catch
and continue.
popsicle('/users')
.then(function (res) {
})
.catch(function (err) {
})
Callbacks
For tooling that expect node-style callbacks, you can use Request#exec
. This accepts a single function to call when the response is complete.
popsicle('/users')
.exec(function (err, res) {
if (err) {
}
})
Response Objects
Every Popsicle response will give a Response
object on success. The object provides an intuitive interface for requesting common properties.
- status An integer representing the HTTP response status code
- body An object (if parsable) or string that was the response HTTP body
- headers An object of lower-cased keys to header values
- statusType() Return an integer with the HTTP status type (E.g.
200 -> 2
) - get(key) Retrieve a HTTP header using a case-insensitive key
- name(key) Retrieve the original HTTP header name using a case-insensitive key
- type() Return the response type (E.g.
application/json
)
Error Handling
All response handling methods can return an error. The errors can be categorized by checking properties on the error instance.
- parse error Response body failed to parse - invalid body or incorrect type (
err.parse
) - abort error The request was aborted by user intervention (
err.abort
) - timeout error The request timed out (
err.timeout
) - unavailable error Unable to connect to the remote URL (
err.unavailable
) - blocked error The request was blocked (HTTPS -> HTTP) (browsers,
err.blocked
) - csp error Request violates the documents Content Security Policy (browsers,
err.csp
) - max redirects error Number of HTTP redirects exceeded (node,
err.maxRedirects
)
Plugins
A simple plugin interface is exposed through Request#use
.
Existing Plugins
- Server - Automatically mount servers with each request for testing
- Status - Reject responses on HTTP failure status codes
- No Cache - Prevent caching of HTTP requests
- Basic Auth - Add basic authentication to requests
- Prefix - Automatically prefix all HTTP requests
- Constants - Replace constants in the URL string
- Limit - Transparently handle API rate limits
Creating Plugins
Plugins must be a function that accepts configuration and returns another function. For example, here's a basic URL prefix plugin.
function prefix (url) {
return function (req) {
req.url = url + req.url
}
}
popsicle('/user')
.use(prefix('http://example.com'))
.then(function (res) {
console.log(res.request.url)
})
If you need to augment the request or response lifecycle, there are a number of functions you can register. All listeners accept an optional promise that will resolve before proceeding.
- before(fn) Register a function to run before the request is made
- after(fn) Register a function to receive the response object
- always(fn) Register a function that always runs on
resolve
or reject
Development and Testing
Install dependencies and run the test runners (node and browsers using Karma).
npm install && npm test
Related Projects
- Superagent - HTTP requests for node and browsers
- Fetch - Browser polyfill for promise-based HTTP requests
- Axios - HTTP request API based on Angular's $http service
License
MIT