The Simple, Secure Framework Developers Trust

Overview

@hapi/hapi

The Simple, Secure Framework Developers Trust

Build powerful, scalable applications, with minimal overhead and full out-of-the-box functionality - your code, your way.

Visit the hapi.dev Developer Portal for tutorials, documentation, and support

Useful resources

Technical Steering Committee (TSC) Members

Comments
  • Cannot Parse form-encoded arrays

    Cannot Parse form-encoded arrays

    I am sending this:

    curl http://localhost:3000/test
    -d "test[foo]=Ukelele"
    -d "test[bar]=123"

    Getting some crazy errors when I try to "request.payload". Looks like it is not getting parsed correctly.

    { "------WebKitFormBoundaryhbKwt7XdcdFwx2vE\r\nContent-Disposition: form-data; name": ""name"\r\n\r\nhello\r\n------WebKitFormBoundaryhbKwt7XdcdFwx2vE--\r\n" }

    feature 
    opened by leore 51
  • Got hapi?

    Got hapi?

    We are compiling a list of companies or products using hapi for a few reasons:

    • showcase logos and user stories of successful hapi development for the new site
    • create a private hapi security notification list for high risk alerts
    • solicit private feedback about making hapi better
    • potential hapi developer event in the coming months
    • help companies to hire experienced hapi developers
    • identify new hapi core contributors from other companies

    What we need from you:

    • Company name
    • Product name or use case
    • Is it in production or development?
    • Contact information for further questions
    • Contact information for security alerts
    • Link to logo if we can showcase your company on the new site
    • User quote (with attribution) about your hapi user experience (up to 300 characters)

    Please reply to this thread if the information is public, or email [email protected].

    opened by hueniverse 38
  • Joi validation error does not provide detailed information in response

    Joi validation error does not provide detailed information in response

    What are you trying to achieve or the steps to reproduce?

    When Joi validation fails, I expect the server response to contain message and validation properties with detailed error information.

    What was the result you received?

    {
      "statusCode": 400,
      "error": "Bad Request",
      "message": "Invalid request payload input"
    }
    

    What did you expect?

    {
      "statusCode": 400,
      "error": "Bad Request",
      "message": "child \"metadata\" fails because [child \"title\" fails because [\"title\" is not allowed to be empty]]",
      "validation": {
        "source": "payload",
        "keys": [
          "metadata.title"
        ]
      }
    }
    

    I traced this down to validation.js internals.input which creates defaultError. Then later on in toolkit.js internals.Manager failAction(), defaultError is thrown, which is used as the server response body.

    validation.js line 102:

    const defaultError = validationError.isBoom ? validationError : Boom.badRequest(`Invalid request ${source} input`);
    

    Context

    • node version: v8.9.1
    • hapi version: 17.1.1
    • boom version: 7.1.0
    • joi version: 13.0.2
    • os: macOS High Sierra
    non issue 
    opened by nickrobillard 35
  • Major performance issue with hapi.js 15.x

    Major performance issue with hapi.js 15.x

    What are you trying to achieve or the steps to reproduce?

    Under higher concurrency Hapi 15.x memory usage spikes and fails, where Hapi 14.x had no problem

    'use strict';
    
    const Hapi = require('hapi');
    const hoek = require('hoek');
    
    const server = new Hapi.Server({
        connections: {
            router: {
                stripTrailingSlash: true
            }
        }
    });
    
    server.connection({
        port: process.env.NODE_PORT || 8080,
        host: process.env.HOSTNAME || '0.0.0.0',
        routes: {
            response: {
                emptyStatusCode: 204
            }
        }
    });
    
    server.route([
        {
            method: 'GET',
            path: '/validate',
            handler: function handle(request, reply) {
                return reply({
                    validate: true
                });
            }
        }
    ]);
    
    server.start(function handleServerStart(serverStartErr) {
        hoek.assert(!serverStartErr, serverStartErr);
        console.log(`Server running at: ${server.info.uri}`);
    });
    
    artillery quick --duration 60 --rate 100 -n 100 http://localhost:8080/validate
    

    What was the result you received?

    With Hapi 15.x, you will see a "JavaScript heap out of memory" and it will fail. With Hapi 14.x, you will have a successful test and have zero errors.

    What did you expect?

    No major failures and zero errors.

    Context

    • node version: 6.5.0 & 4.5.0
    • hapi version: 15.0.3
    • os: OSX & Centos
    • any other relevant information: I am aware this is a very high RPS to push through a server. But it is an attack vector. I also was able to replicate this with JMeter, so the load tool isn't important in this case. Just high concurrency and RPS.
    bug security dependency 
    opened by lostthetrail 32
  • Return explicit error when trying to stream a non-Readable stream

    Return explicit error when trying to stream a non-Readable stream

    Fix #2368 & #2301 by returning an explicit error for nonReadable streams instead of throwing.

    This also fixes buggy behavior introduced in #2302, where a Writable only stream can be accepted as long as it contains a socket._readableState object.

    bug 
    opened by kanongil 29
  • Provide cover for unhandled rejections

    Provide cover for unhandled rejections

    This small change allows an extra degree of protection for those who might be using promises in their handlers.

    Problem Statement

    Developers who are using promises in their handlers will often write handlers which look like this:

    function handler(request, reply) {
      doSomething
        .then((interimResult) => {
          return somethingElse(interimResult);
        })
        .then((result) => {
          reply(result.whatever);
        });
    

    The challenge is that this opens up lots of opportunities for exceptions at different points to lead to uncaught promise rejections. For example:

    function handler(request, reply) {
      doSomething
        .then((interimResult) => {
          throw new Error('whoops...');
        })
        .then((result) => {
          reply(result.whatever);
        });
    

    will lead to a timeout of the request.

    Suggested Change

    Rather than attempting some kind of large scale change which adds more support for promises (which is not needed, as reply can take a promise), I propose allowing the handler to return a promise. If the promise is returned, then hapi can register a catch and reply with any error. This means that if the developer goofs up and forgets to catch (all to easy with the promise spec), hapi at least will attempt to deal with the error in the same way it would as if an exception was thrown.

    This PR adds the support, updates the docs and tests.

    Questions

    Do we need this?

    It is possible to rewrite the dodgy code as:

    function handler(request, reply) {
      reply(doSomething
        .then((interimResult) => {
          return somethingElse(interimResult);
        })
        .then((result) => {
          return result.whatever;
        }));
    

    However this tends to feel a little unnatural, as the natural reading order is more 'do work, reply with the result'. Fairly subjective but I've seen quite a few devs on teams default to doing it the way described in the problem statement, rather than this. It also makes doing things like changing the status code conditionally based on the result near impossible. (CMIIW!)

    Of course, people could just avoid promises (which might not be a bad idea given some of the issues around how they can swallow exceptions), but at least an appreciable proportion of people are using them heavily.

    Should we ever have 'partial promise' support

    Really, if you are returning a promise in the handler it might make more sense to simply not even have the reply function used, and change the spec to say if you return a promise, hapi with reply with the result or if there is an error, wrap it in Boom and then reply with that.

    This would perhaps be cleaner in some cases:

    function handler(req, reply) {
      return doSomething().then(r = doSomethingElse(r));
    }
    

    But is a larger structural change. Also, it still means we cannot easily change status codes, add headers etc.

    I think this is a happier middle group - hapi's API stays the same, but it has a 'safety net' for promises.

    That's It!

    I'd love to get any feedback on this as a potential feature. It would certainly help myself and my colleagues on some of the projects we're on at the moment, I believe it allows us to provide a safety net for potentially nasty issues (promise black holes are a pain) but am happy to take any input for changes!

    Related Issues

    • https://github.com/hapijs/hapi/issues/2097
    • https://github.com/hapijs/hapi/issues/2771
    • https://github.com/hapijs/hapi/issues/3242
    • https://github.com/hapijs/hapi/issues/3429
    feature bug 
    opened by dwmkerr 27
  • Assert when server.start() is called before server.register() is done

    Assert when server.start() is called before server.register() is done

    As far as I can tell, server.register doesn't wait for the previous plugin to call the next callback. This is pretty confusing since next() seems to imply it's safe to run async code in a plugin that a later plugin would be dependent on.

    feature breaking changes 
    opened by hulbert 26
  • Joi 2.0 integration feedback

    Joi 2.0 integration feedback

    Please try adding Hapi.joi.version('v2') when you first load hapi and see how your validation rules work with the new joi 2.0 module. Any issues or feedback would be greatly appreciated. At some point we'll publish a hapi 2.0 with joi 2.0 as the default based on this feedback.

    support 
    opened by hueniverse 26
  • how to use payload for auth check ?

    how to use payload for auth check ?

    scheme:

    scheme = {
        authenticate: (request, reply) => {
          return reply(null, {
            credentials: {
              user: {}
            }
          });
        },
        payload: (request, reply) => {
          return reply.continue({
            credentials: {
              user: { uid: 1 }
            }
          });
        },
        options: { payload: true }
      };
    

    config:

    server.auth.strategy('standard', 'test',options);
    server.auth.default({
        strategy: 'standard',
        scope: ['user'],
        payload: true
      });
    

    route:

    {
      method: 'post',
      path: '/',
      config: {
        auth: {
          payload: true
        },
        validate: {
          payload: {
            auth: joi.string().length(32).required().description('Auth Token')
          },
          failAction: (req, reply) => {
            return reply(boom.unauthorized('Invalid Auth Token.'));
          }
        },
        handler: homeHandler
      }
    }
    

    Result always:

    {
        "credentials": {
            "user": {}
        }
    }
    

    why?

    how to use payload for auth check ?

    non issue 
    opened by willin 24
  • Getting Started Tutorial Contest - Win an iPad Air

    Getting Started Tutorial Contest - Win an iPad Air

    Hello fellow hapi travelers!

    We share your frustration about the lack of awesome developer website for hapi.js. The old site was all about v1.x and was taken down for causing too much confusion. We have started working on a brand new developer site with our friends at &yet. We hope to have something to show you around May.

    Meanwhile, to get some awesome hapi.js tutorials out there using v3.0, we are having a little contest. We are looking for the best Getting Started with hapi.js Tutorial. It can be a gist, a blog post, a new issue, an npm module, or whatever. It may contain videos but should be as helpful without them.

    The rules are simple:

    1. Submit your tutorial by commenting on this thread by April 1st noon PT with a link.
    2. You can post your tutorial link as early as you want and keep changing the content until the deadline.
    3. You can submit as many tutorials as you want, each counting as one submission.
    4. A panel of judges will review the submissions and a winner will be announced by April 10th.

    The winner will receive an Apple iPad Air 16Gb WiFi or another item from walmart.com of equal value.

    Got questions? Post a comment!

    Walmart and &yet employees cannot participate. Open to anyone in any country (as long as we can legally ship to you from the US and you take full responsibility for any local taxes charged).

    documentation 
    opened by hueniverse 23
  • The future of the hapi project

    The future of the hapi project

    👋 Hey all— I'm here to represent this crew that Eran has been referring to (see also #4111). We're here to carry hapi into 2021 and beyond, and we want to share our vision with you. Let me first say that we are feeling very positive about the future of the framework and are energized to work on it, in some cases with material backing by our employers.

    Our group consists principally of core team members (former lead maintainers of hapi's direct dependencies), and members of the original team that built hapi at Walmart. It is heartening to see so much support pouring out right now— many folks have made it clear that they are interested in spending time contributing to the framework. We want to enable that: this is completely in line with our plans and we look forward to making hapi more of a community effort, but more on that later.

    Within this small group you will find a former hapi Community Lead and Chief Architect at npm; a member of the Node.js TSC and libuv maintainer; several engineers working on major projects at Joyent; the finger that famously pressed "the button" on Walmart's Black Friday hapi deployment; several who provide B2B services utilizing the framework; and the creator of hapi pal, an entire sub-ecosystem of hapi. We lived hapi's history, we are aware of the pain points and blind spots, we understand all that there is to love about the framework, and we know you. Perhaps more importantly, if you've been active in the community then you probably know us! Here we are:

    • Devin Ivy (@devinivy)
    • Jonas Pauthier (@nargonath)
    • Lloyd Benson (@lloydbenson)
    • Nathan LaFreniere (@nlf)
    • Wyatt Lyon Preul (@geek)
    • Colin Ihrig (@cjihrig)

    This group of seven constitutes hapi's initial Technical Steering Committee (TSC). Yes that's right, we're going to have a TSC! That means that for the first time hapi is going to be taking a more distributed, community-driven approach to governance, in a similar vein to the Node.js organization. It is the TSC's job to provide technical direction, onboard collaborators, and facilitate consensus-seeking within the community. For practical reasons there is a smaller leadership team with exclusive rights to publishing new module versions: Colin, Nathan, and myself.

    It's not all about making changes, though. To begin our focus will be to establish stability in maintenance and governance, making only minor adjustments along the way to achieve that goal. We'll be working closely with Eran leading up to the moment he steps away from hapi maintenance, and at that point we will release a new major version, more so to signal to the community this change in leadership than to make any significant API adjustments. Here are some things that we intend to keep, not necessarily an exhaustive list:

    • Stability: no, we're not here for a rewrite.
    • No external dependencies: this organization remains a safe haven from the broader node ecosystem.
    • 100% code coverage: we aim to hit all code branches with integration-style tests.
    • Security disclosure policy: we will continue to encourage and practice responsible disclosure.
    • Close following of semver: if there is a breaking change, we'll make sure you know about it.
    • Quality of release notes and migration guides: when there are changes, we won't leave you hanging.

    We want to keep what's making hapi what it is today but we also have visions for the future for what hapi could become. We're looking forward to all the cool stuff we'll be adding to the project and we're excited for you to help us with that.

    And for now that is the "short" of it. Hopefully this gives you a much better sense of who is working to carry hapi forward and what to expect. We understand that there are likely lots of questions coming our way. It is still relatively early in this process and there are still many details to work out, but we will try to speak to those to the best of our ability at this time! Please bear in mind this is still open source, and while we will have some employer support in the near future, this is still a community effort with lots of personal time invested as well.

    That is all for now! Expect to hear more in the coming weeks and months— we hope you'll be there with us.

    Note: you can find more information about legacy commercial support here.

    breaking changes 
    opened by devinivy 22
  • jest testing hapijs -> how to mock a decorated method call or override it during testing

    jest testing hapijs -> how to mock a decorated method call or override it during testing

    Support plan

    • is this issue currently blocking your project? (yes/no): yes.
    • is this issue affecting a production system? (yes/no): no.

    Context

    • node version: node v14.19.1 (npm v6.14.17)
    • module version: "@hapi/hapi": "20.1.5",
    • environment (e.g. node, browser, native): node
    • used with (e.g. hapi application, another framework, standalone, ...): reactJS
    • any other relevant information:

    How can we help?

    Objective: trying to figure out a way to mock return value of a decorated (server.decorate) function.

    Example use-case:

    simple plugin; uses server.decorate to define a function isUserSessionValid to return true or false value.

    NEED HELP WITH: how to make this decorated isUserSessionValid (which would be like request.isUserSessionValid) in the jest test file to return true or false based on test case needs!

    Sample code:

    // user-session.ts
    
    const isUserSessionValid = () => {
     // logic to return true if user session valid; else false
    }
    
    export const plugin = {
      name: 'session',
      register(server: Server) {
        // TODO: figure out a way to jest test mock this decorated method: isUserSessionValid return value to be true or false based on test cases
        server.decorate('request', 'isUserSessionValid', isUserSessionValid);
    
        // REST API endpoint to validate whether the received request contains valid user session or not; returns true if valid; else false. 
        server.route({
          method: 'GET',
          path: '/api/user-session-validate',
          async handler(request: Request, h: ResponseToolkit): Promise<boolean> {
            return await request.isUserSessionValid();
          },
        });
      },
    };
    
    

    in test file, trying to do

    // user-session.spec.ts
    ...
    
    import { plugin } from '../user-session';
    
    describe('User session', () => {
      let server: Hapi.Server;
    
      beforeEach(async () => {
        server = Hapi.server();
        await server.initialize();
    
        server.register({
          plugin,
        });
      });
    
      afterEach(async () => {
        jest.clearAllMocks();
        await server.stop();
      });
    
      describe('GET /api/user-session-validate', () => {
        it('when session is valid, returns true', async () => {
          
          // doing this would result in expected error: "Request decoration already defined: isUserSessionValid"
          // HOW TO MOCK THIS TO RETURN "true" or "false" based on my needs?
          server.decorate('request', 'isUserSessionValid', () => Promise.resolve(true));
    
          await server
            .inject({
              method: 'GET',
              url: '/api/user-session-validate',
            })
            .then((res) => {
               // do some logic to validate.... 
            });
        });
      });
    ....
    
    

    Can someone please help me on this? Been trying to tackle this for long time with no solid success. am also new to this framework & trying to learn..

    support 
    opened by vivekVells 0
  • server is throwing 504 gateway timeout after 1 minute

    server is throwing 504 gateway timeout after 1 minute

    React.js application is hitting the Node.js api to generate the report, API is processing the client's request but in between execution api is throwing 504 error after 60 seconds of execution. seems like timeout issue

    support 
    opened by Mohd-Farhaan 3
  • Issue with authentication option on Routes from an external module

    Issue with authentication option on Routes from an external module

    Support plan

    • is this issue currently blocking your project? (yes/no): no
    • is this issue affecting a production system? (yes/no): no

    Context

    • node version: 16.18.1
    • module version with issue: Hapi 21.1.0
    • last module version without issue: Unsure
    • environment (e.g. node, browser, native): Node
    • used with (e.g. hapi application, another framework, standalone, ...): TypeScript
    • any other relevant information: I can get this to currently work by defining the auth parameter as such false as const but I'm not sure if that's the right thing to do or not.

    What are you trying to achieve or the steps to reproduce?

    Define multiple routes in an external module via an array of ServerRoute-like objects and disable authentication on specific routes

    index.ts

    import * as Hapi from '@hapi/hapi';
    import Routes from './Routes';
    
    const hapi = Hapi.server({port: 5000});
    hapi.route(Routes);
    hapi.start();
    

    routes.ts

    export default [
        {
            method: 'GET',
            path: '/users',
            handler: () => {}
        },
        {
            method: 'POST',
            path: '/users/login',
            handler: () => {},
            options: {
                auth: false
            }
        },
    ];
    

    What was the result you got?

    When compiling the TypeScript to JavaScript, TSC gives this error:

    Types of property 'auth' are incompatible.
    Type 'boolean' is not assignable to type 'string | false | RouteOptionsAccess'.
    

    image

    What result did you expect?

    No type issue. The routes setup successfully.

    support 
    opened by tomcphr 3
  • How do I separate between integration testing and unit testing using Hapi in Node.js?

    How do I separate between integration testing and unit testing using Hapi in Node.js?

    How do I separate between integration testing and unit testing using Hapi in Node.js?

    I am trying to reduce the testing time in our automations for every time we update a unit within our API.

    I was wondering can I just create two new folders test/unit and test/int to separate the scripts and what would the update to the package.json require?

    I have the following in the package.json which runs the .labrc.js package.json

    "test": "npm run version-stamp && lab --bail -t 80 -r html -o coverage.html -r console -o stdout -r junit -o TestResult.xml -r lcov -o coverage.dat",
    "simple-test": "npm run version-stamp && lab",
    "test-int": "not sure what to put here",
    

    labrc.js

    module.exports = {
        verbose: true,
        timeout: 7500,
        lint: true,
        paths: [
            "test/init/aws",
            "test/unit/plugins",
            "test/unit/utils",
            "test/unit/routes"
        ],
    
    support 
    opened by dcrays08 0
  • Updates to TypeScript definitions

    Updates to TypeScript definitions

    • Fix table type definition. See https://github.com/hapijs/call/blob/f4adca38ae29852fa5f990b13a0abbc36a53b924/lib/index.js#L325 and https://github.com/hapijs/hapi/blob/9c17cc0dc99570939a449b623fbd58aca3ecac92/test/core.js#L1489
    • More updates to type definitions. These were found by checking WebStorm's list of type mismatches. Most of them involve updating the type definitions to match API.md or to match the tests' usage.
    opened by joshkel 1
Releases(v21.0.0)
Owner
hapi.js
The Simple, Secure Framework Developers Trust
hapi.js
The React Framework

Next.js Getting Started Visit https://nextjs.org/learn to get started with Next.js. Documentation Visit https://nextjs.org/docs to view the full docum

Vercel 98.6k Jan 5, 2023
Fast, unopinionated, minimalist web framework for node.

Fast, unopinionated, minimalist web framework for node. const express = require('express') const app = express() app.get('/', function (req, res) {

null 59.5k Jan 5, 2023
The Intuitive Vue Framework

Build your next Vue.js application with confidence using Nuxt: a framework making web development simple and powerful. Links ?? Documentation: https:/

Nuxt 41.8k Jan 9, 2023
A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications on top of TypeScript & JavaScript (ES6, ES7, ES8) 🚀

A progressive Node.js framework for building efficient and scalable server-side applications. Description Nest is a framework for building efficient,

nestjs 53.2k Dec 31, 2022
Realtime MVC Framework for Node.js

Website Get Started Docs News Submit Issue Sails.js is a web framework that makes it easy to build custom, enterprise-grade Node.js apps. It is design

Balderdash 22.4k Dec 31, 2022
Fast and low overhead web framework, for Node.js

An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users. How can you efficiently handle the

Fastify 26k Jan 2, 2023
A framework for real-time applications and REST APIs with JavaScript and TypeScript

A framework for real-time applications and REST APIs with JavaScript and TypeScript Feathers is a lightweight web-framework for creating real-time app

Feathers 14.3k Jan 1, 2023
🚀 The Node.js Framework highly focused on developer ergonomics, stability and confidence

Sponsored by FOSS United is a non-profit foundation that aims at promoting and strengthening the Free and Open Source Software (FOSS) ecosystem in Ind

AdonisJS Framework 13.4k Dec 31, 2022
:rocket: Progressive microservices framework for Node.js

Moleculer Moleculer is a fast, modern and powerful microservices framework for Node.js. It helps you to build efficient, reliable & scalable services.

MoleculerJS 5.5k Jan 4, 2023
MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers

Derby The Derby MVC framework makes it easy to write realtime, collaborative applications that run in both Node.js and browsers. Derby includes a powe

DerbyJS 4.7k Dec 23, 2022
Node.js framework

Node.js framework Total.js framework is a framework for Node.js platfrom written in pure JavaScript similar to PHP's Laravel or Python's Django or ASP

Total.js 4.2k Jan 2, 2023
:evergreen_tree: Modern Web Application Framework for Node.js.

Trails is a modern, community-driven web application framework for Node.js. It builds on the pedigree of Rails and Grails to accelerate development by

Trails 1.7k Dec 19, 2022
Marble.js - functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS.

Functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS. Ecosystem Name Description @marblejs/core F

Marble.js 2.1k Dec 16, 2022
🦄 0-legacy, tiny & fast web framework as a replacement of Express

tinyhttp âš¡ Tiny web framework as a replacement of Express ?? tinyhttp now has a Deno port (work in progress) tinyhttp is a modern Express-like web fra

v 1 r t l 2.4k Jan 3, 2023
Catberry is an isomorphic framework for building universal front-end apps using components, Flux architecture and progressive rendering.

Catberry What the cat is that? Catberry was developed to help create "isomorphic/Universal" Web applications. Long story short, isomorphic/universal a

Catberry.js 801 Dec 20, 2022
A serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gateway, Lambda)

---- Sorry, this project is not maintained anymore. ---- dawson is a serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gate

dawson 717 Dec 30, 2022
Framework for setting up RESTful JSON APIs with NodeJS.

Restberry works with both Express and Restify! Framework for setting up RESTful JSON APIs with NodeJS. Define your models and setup CRUD API calls wit

Restberry 117 Jul 5, 2021
Component based MVC web framework for nodejs targeting good code structures & modularity.

Component based MVC web framework for nodejs targeting good code structures & modularity. Why fortjs Based on Fort architecture. MVC Framework and fol

Ujjwal Gupta 47 Sep 27, 2022
Proof of concept for the Quark.js web framework

Quark.js Proof of Concept Proof of concept for the Quark.js web framework. Examples Express.js Implimentation using express.js as a web server: im

Quark.js 3 Feb 18, 2022