Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@hapi/h2o2
Advanced tools
@hapi/h2o2 is a plugin for the hapi.js framework that provides proxying capabilities. It allows you to forward requests to other servers, making it useful for creating APIs that aggregate data from multiple sources or for implementing reverse proxies.
Basic Proxying
This code demonstrates how to set up a basic proxy using @hapi/h2o2. It forwards requests from the /proxy endpoint to example.com.
const Hapi = require('@hapi/hapi');
const H2o2 = require('@hapi/h2o2');
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
await server.register(H2o2);
server.route({
method: 'GET',
path: '/proxy',
handler: {
proxy: {
host: 'example.com',
protocol: 'http',
port: 80,
passThrough: true
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
Proxy with Custom Headers
This example shows how to add custom headers to the proxied response using @hapi/h2o2. The onResponse function allows you to modify the response before it is sent back to the client.
const Hapi = require('@hapi/hapi');
const H2o2 = require('@hapi/h2o2');
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
await server.register(H2o2);
server.route({
method: 'GET',
path: '/proxy-with-headers',
handler: {
proxy: {
host: 'example.com',
protocol: 'http',
port: 80,
passThrough: true,
onResponse: (err, res, request, h, settings, ttl) => {
res.headers['x-custom-header'] = 'my-custom-value';
return res;
}
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
Proxy with Query Parameters
This code demonstrates how to forward query parameters from the client request to the proxied request using the mapUri function.
const Hapi = require('@hapi/hapi');
const H2o2 = require('@hapi/h2o2');
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
await server.register(H2o2);
server.route({
method: 'GET',
path: '/proxy-with-query',
handler: {
proxy: {
host: 'example.com',
protocol: 'http',
port: 80,
passThrough: true,
mapUri: (request) => {
return {
uri: `http://example.com?${request.query}`
};
}
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
http-proxy-middleware is a popular middleware for Node.js that provides similar proxying capabilities. It is often used with Express.js and offers a wide range of customization options, including path rewriting, custom headers, and more. Compared to @hapi/h2o2, it is more commonly used in the Express.js ecosystem.
node-http-proxy is a full-featured HTTP proxy for Node.js. It provides a robust set of features for creating proxy servers, including support for WebSockets, custom headers, and load balancing. It is a lower-level library compared to @hapi/h2o2, offering more control but requiring more setup.
express-http-proxy is a simple and configurable proxy middleware for Express.js. It allows you to forward requests to other servers with minimal configuration. It is similar to @hapi/h2o2 but is designed specifically for use with Express.js.
Proxy handler plugin for hapi.js.
h2o2 adds proxying functionality to a hapi server.
const Hapi = require('@hapi/hapi');
const H2o2 = require('@hapi/h2o2');
const start = async function() {
const server = Hapi.server();
try {
await server.register(H2o2);
await server.start();
console.log(`Server started at: ${server.info.uri}`);
}
catch(e) {
console.log('Failed to load h2o2');
}
}
start();
The plugin can be registered with an optional object specifying defaults to be applied to the proxy handler object.
The proxy handler object has the following properties:
host
- upstream service host to proxy requests to. It will have the same path as the client request.port
- upstream service port.protocol
- protocol to use when making the request to the proxied host:
uri
- absolute URI used instead of host, port, protocol, path, and query. Cannot be used with host
, port
, protocol
, or mapUri
.httpClient
- an http client that abides by the Wreck interface. Defaults to wreck
.passThrough
- if set to true
, it forwards the headers from the client to the upstream service, headers sent from the upstream service will also be forwarded to the client. Defaults to false
.localStatePassThrough
- if set tofalse
, any locally defined state is removed from incoming requests before being sent to the upstream service. This value can be overridden on a per state basis via the server.state()
passThrough
option. Defaults to false
acceptEncoding
- if set to false
, does not pass-through the 'Accept-Encoding' HTTP header which is useful for the onResponse
post-processing to avoid receiving an encoded response. Can only be used together with passThrough
. Defaults to true
(passing header).rejectUnauthorized
- sets the rejectUnauthorized
property on the https agent making the request. This value is only used when the proxied server uses TLS/SSL. If set it will override the node.js rejectUnauthorized
property. If false
then ssl errors will be ignored. When true
the server certificate is verified and an 500 response will be sent when verification fails. This shouldn't be used alongside the agent
setting as the agent
will be used instead. Defaults to the https agent default value of true
.xforward
- if set to true
, sets the 'X-Forwarded-For', 'X-Forwarded-Port', 'X-Forwarded-Proto', 'X-Forwarded-Host' headers when making a request to the proxied upstream endpoint. Defaults to false
.redirects
- the maximum number of HTTP redirections allowed to be followed automatically by the handler. Set to false
or 0
to disable all redirections (the response will contain the redirection received from the upstream service). If redirections are enabled, no redirections (301, 302, 307, 308) will be passed along to the client, and reaching the maximum allowed redirections will return an error response. Defaults to false
.timeout
- number of milliseconds before aborting the upstream request. Defaults to 180000
(3 minutes).mapUri
- a function used to map the request URI to the proxied URI. Cannot be used together with host
, port
, protocol
, or uri
. The function signature is function (request)
where:
request
- is the incoming request object. The response from this function should be an object with the following properties:
uri
- the absolute proxy URI.headers
- optional object where each key is an HTTP request header and the value is the header content.onRequest
- a custom function which is passed the upstream request. Function signature is function (req)
where:
req
- the [wreck] (https://github.com/hapijs/wreck) request to the upstream server.onResponse
- a custom function for processing the response from the upstream service before sending to the client. Useful for custom error handling of responses from the proxied endpoint or other payload manipulation. Function signature is function (err, res, request, h, settings, ttl)
where:
err
- internal or upstream error returned from attempting to contact the upstream proxy.res
- the node response object received from the upstream service. res
is a readable stream (use the wreck module read
method to easily convert it to a Buffer or string).request
- is the incoming request object.h
- the response toolkit.settings
- the proxy handler configuration.ttl
- the upstream TTL in milliseconds if proxy.ttl
it set to 'upstream'
and the upstream response included a valid 'Cache-Control' header with 'max-age'.ttl
- if set to 'upstream'
, applies the upstream response caching policy to the response using the response.ttl()
method (or passed as an argument to the onResponse
method if provided).agent
- a node http(s) agent to be used for connections to upstream server.maxSockets
- sets the maximum number of sockets available per outgoing proxy host connection. false
means use the wreck module default value (Infinity
). Does not affect non-proxy outgoing client connections. Defaults to Infinity
.secureProtocol
- TLS flag indicating the SSL method to use, e.g. SSLv3_method
to force SSL version 3. The possible values depend on your installation of OpenSSL. Read the official OpenSSL docs for possible SSL_METHODS.ciphers
- TLS list of TLS ciphers to override node's default.
The possible values depend on your installation of OpenSSL. Read the official OpenSSL docs for possible TLS_CIPHERS.downstreamResponseTime
- logs the time spent processing the downstream request using process.hrtime. Defaults to false
.As one of the handlers for hapi, it is used through the route configuration object.
h.proxy(options)
Proxies the request to an upstream endpoint where:
options
- an object including the same keys and restrictions defined by the
route proxy
handler options.No return value.
The response flow control rules do not apply.
const handler = function (request, h) {
return h.proxy({ host: 'example.com', port: 80, protocol: 'http' });
};
host
, port
, protocol
optionsSetting these options will send the request to certain route to a specific upstream service with the same path as the original request. Cannot be used with uri
, mapUri
.
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
host: '10.33.33.1',
port: '443',
protocol: 'https'
}
}
});
uri
optionSetting this option will send the request to an absolute URI instead of the incoming host, port, protocol, path and query. Cannot be used with host
, port
, protocol
, mapUri
.
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
uri: 'https://some.upstream.service.com/that/has?what=you&want=todo'
}
}
});
uri
template valuesWhen using the uri
option, there are optional default template values that can be injected from the incoming request
:
{protocol}
{host}
{port}
{path}
server.route({
method: 'GET',
path: '/foo',
handler: {
proxy: {
uri: '{protocol}://{host}:{port}/go/to/{path}'
}
}
});
Requests to http://127.0.0.1:8080/foo/
would be proxied to an upstream destination of http://127.0.0.1:8080/go/to/foo
Additionally, you can capture request.params values and inject them into the upstream uri value using a similar replacment strategy:
server.route({
method: 'GET',
path: '/foo/{bar}',
handler: {
proxy: {
uri: 'https://some.upstream.service.com/some/path/to/{bar}'
}
}
});
Note The default variables of {protocol}
, {host}
, {port}
, {path}
take precedence - it's best to treat those as reserved when naming your own request.params
.
mapUri
and onResponse
optionsSetting both options with custom functions will allow you to map the original request to an upstream service and to processing the response from the upstream service, before sending it to the client. Cannot be used together with host
, port
, protocol
, or uri
.
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
mapUri: function (request) {
console.log('doing some additional stuff before redirecting');
return {
uri: 'https://some.upstream.service.com/'
};
},
onResponse: function (err, res, request, h, settings, ttl) {
console.log('receiving the response from the upstream.');
Wreck.read(res, { json: true }, function (err, payload) {
console.log('some payload manipulation if you want to.')
const response = h.response(payload);
response.headers = res.headers;
return response;
});
}
}
}
});
By default, h2o2
uses Wreck to perform requests. A custom http client can be provided by passing a client to httpClient
, as long as it abides by the wreck
interface. The two functions that h2o2
utilizes are request()
and parseCacheControl()
.
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
httpClient: {
request(method, uri, options) {
return axios({
method,
url: 'https://some.upstream.service.com/'
})
}
}
}
}
});
FAQs
Proxy handler plugin for hapi.js
The npm package @hapi/h2o2 receives a total of 227,690 weekly downloads. As such, @hapi/h2o2 popularity was classified as popular.
We found that @hapi/h2o2 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 7 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.