Fortune HTTP

raw JSON →
1.2.28 verified Thu Apr 23 auth: no javascript

Fortune HTTP (`fortune-http`) provides the HTTP implementation for Fortune.js, a non-native graph database abstraction layer for Node.js and web browsers. Currently at version 1.2.28, this module is essential for exposing Fortune.js APIs over HTTP, including default serializers for JSON, HTML, form-encoded data, and form data. It acts as the networking layer, converting internal Fortune.js requests and responses into HTTP interactions. It is explicitly stated as being required for other HTTP serializers within the Fortune.js ecosystem. While a specific release cadence isn't defined, it typically evolves alongside the main Fortune.js project. Its key differentiator is its tight integration with Fortune.js, offering a structured, ad hoc JSON over HTTP API and an HTML interface, contrasting with other network protocols like WebSocket also supported by Fortune.js.

error TypeError: fortuneHTTP is not a function
cause Attempting to import `fortune-http` using an ESM `import` statement or incorrectly assuming it's a class, or if CommonJS `require` yields an unexpected value.
fix
Use CommonJS const fortuneHTTP = require('fortune-http') as the primary method of importing.
error UnhandledPromiseRejectionWarning: Unhandled promise rejection.
cause The `listener` function returned by `fortuneHTTP` is asynchronous and returns a Promise. If this Promise rejects and the rejection is not caught, Node.js will log this warning or crash the process in newer versions.
fix
Always append a .catch() block to the listener call, e.g., listener(request, response).catch(console.error).
error Error: Headers already sent
cause When using `fortune-http` within an Express.js or similar middleware stack, another middleware might be attempting to send a response after `fortune-http` has already done so, or vice-versa, due to incorrect ordering.
fix
Ensure that the fortune-http listener is positioned as the last middleware in the chain for the routes it is intended to handle, as it typically ends the response by default.
error Fortune HTTP Error: A Fortune instance is required.
cause The `fortuneHTTP` function was called without providing a valid Fortune.js instance as its first argument.
fix
Pass an initialized instance of Fortune.js to fortuneHTTP, like fortuneHTTP(myFortuneInstance, options).
error CSRF token mismatch
cause A request, particularly a form submission, was made to `fortune-http`'s form serializers without the required `CSRF_` prefixed cookie values.
fix
Include a cookie value prefixed with CSRF_ in your form submissions as required by the fortune-http form serializers for CSRF protection.
gotcha The `fortuneHTTP` function returns a Promise. All calls to the listener must explicitly handle promise rejections (e.g., with `.catch()`) to prevent unhandled promise errors from crashing the Node.js process.
fix Ensure all calls to the listener function are followed by a `.catch(error => { /* handle error */ })` block.
gotcha When used with middleware frameworks like Express, the `fortune-http` listener should typically be the last middleware in the stack for a given route, as it ends the response by default. Placing other middleware after it may lead to 'Headers already sent' errors.
fix Position `app.use(listener)` or similar at the end of your middleware chain for routes handled by Fortune HTTP.
gotcha Form serializers in `fortune-http` require all payloads to include cookie values prefixed with `CSRF_` for Cross-Site Request Forgery (CSRF) protection. Omitting these will result in failed form submissions.
fix Ensure that form submissions include appropriate CSRF cookie values prefixed with `CSRF_`.
gotcha The special field `__method__` can be used within form payloads to override the HTTP method. This is a specific mechanism for scenarios where standard HTTP methods cannot be used directly.
fix If HTTP method overriding is required for form submissions, include `__method__` field in the payload with the desired Fortune.js-accepted method.
deprecated Previous versions of Fortune.js (before 5.0.0) had HTTP capabilities directly within the core `fortune.net.http` namespace. `fortune-http` was extracted as a separate module in Fortune.js v5.0.0. Older applications may need to update their import paths.
fix For Fortune.js v5.0.0 and later, use `require('fortune-http')` directly instead of `fortune.net.http`.
npm install fortune-http
yarn add fortune-http
pnpm add fortune-http

Demonstrates setting up a basic Node.js HTTP server using `fortune-http` with a mock `Fortune.js` instance, showcasing how to handle requests and catch potential errors.

const http = require('http');
const fortuneHTTP = require('fortune-http');
// A mock Fortune.js instance for demonstration purposes.
// In a real application, you would initialize Fortune.js.
const mockFortuneInstance = {
  request: async (type, payload) => {
    console.log(`Fortune.js request: ${type}`, payload);
    // Simulate database operations
    if (type === 'create') return { records: [{ id: Math.random().toString(36).substring(7), ...payload.records[0] }] };
    if (type === 'find') return { records: [{ id: 'abc', message: 'Hello from Fortune!' }] };
    return { records: [] };
  }
};

// Pass in a Fortune instance and an optional options object.
const listener = fortuneHTTP(mockFortuneInstance, {
  // Example customization for HTML serializer (default prefix is empty string)
  prefix: '/api'
});

const server = http.createServer((request, response) =>
  listener(request, response)
    .catch(error => {
      console.error('Fortune HTTP Error:', error.stack);
      if (!response.headersSent) {
        response.writeHead(500, { 'Content-Type': 'application/json' });
        response.end(JSON.stringify({ error: error.message }));
      }
    })
);

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`Fortune HTTP server listening on http://localhost:${PORT}`);
  console.log(`Try: curl http://localhost:${PORT}/api/find/posts`);
  console.log(`Try: curl -X POST -H "Content-Type: application/json" -d '{"records": [{"message": "New post!"}]}' http://localhost:${PORT}/api/create/posts`);
});