The Nile-JS SDK includes generated routes for all its operations.
These routes are used by the SDK methods to proxy requests to nile-auth, as well as directly from the React hooks and components in @niledatabase/react.
import "dotenv/config";import express from "express";import { Nile } from "@niledatabase/server";import { NileExpressHandler } from "@niledatabase/server/express";const startServer = async () => { try { const app = express(); const nile = await Nile(); // This is where the route handlers are imported const { paths, handler } = await NileExpressHandler(nile); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // This is where the routes are exposed in your express app app.get(paths.get, handler); app.post(paths.post, handler); app.put(paths.put, handler); app.delete(paths.delete, handler); // Your own routes go here const PORT = process.env.PORT || 3040; app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); } catch (error) { console.error("Error starting server:", error); process.exit(1); }};startServer();
You typically don’t need to use the routes directly.
The SDK methods and react/web components use the routes under the hood to communicate with nile-auth.
The generated routes are available via nile.api.paths. For reference, here are the paths for the default routes:
A case where you might want to use the routes directly is when these routes are exposed as a REST API of your application backend.
For example, if you use the @niledatabase/server/express package, the routes are exposed in the app object and
while you may have a frontend that uses @niledatabase/react to call these routes from the application UI,
you may want to also use them as a REST API for another backend or external service.
In this case, you need to use the routes directly. The key is to:
Include both the session cookie and the CRSF cookie in the request headers.
Include the CSRF token in the request body.
Here are a few examples of how to call the routes directly:
Copy
Ask AI
# This gets the CSRF token from an API exposed by your application, and also saves the cookies to a filecsrf_token=$(curl -s -X GET "http://localhost:3040/api/auth/csrf" -c "csrf_cookies.txt" | jq -r '.csrfToken')
Sometimes you might want to intercept or override the routes used by the SDK in order to inject your own logic.
For example, adding your own logging or metrics, adding debugging information, or perhaps injecting your own cookies during login.
There are three ways to override routes:
Route wrappers: Wrap the route in your own logic. This can be done in the routes file, and is useful for minor modifications or debugging.
Route overrides: Override the route for a specific operation.
In the examples below, we’ll use route wrappers to log the headers before every request and the body if it’s a POST request.
We’ll also log the status code of the response.
Copy
Ask AI
// app/api/[...nile]/route.tsimport { handlers } from "./nile";// Middleware function to log request and response detailsconst logRequestAndResponseDetails = (handler) => async (req, res) => { // Log the request method and URL console.log(`Request Method: ${req.method}, Request URL: ${req.url}`); // Log the request headers console.log('Request Headers:', req.headers); // Clone the request to safely read the body const clonedReq = req.clone(); // Log the request body if it's a POST or PUT request if (req.method === 'POST') { const body = await clonedReq.text(); console.log('Request Body:', body); } // Call the original handler and return its result const result = await handler(req, res); // Log the response status after the handler has executed console.log('Result Status:', result.status); return result;};// Wrap each handler with the logging middlewareexport const POST = logRequestAndResponseDetails(handlers.POST);export const GET = logRequestAndResponseDetails(handlers.GET);export const DELETE = logRequestAndResponseDetails(handlers.DELETE);export const PUT = logRequestAndResponseDetails(handlers.PUT);
In the examples below, we’ll add a new route that will override the default route for \auth\google\callback with
custom logic. We are using handlersWithContext to get the nile object in the route handler.
handlersWithContext returns a tuple with the nile object, configured based on the response from the route handler,
and the response from the route handler.
Copy
Ask AI
// app/api/auth/google/callback/route.tsimport { NextRequest } from "next/server";// make sure you export handlersWithContext from nile.apiimport { handlersWithContext } from "../../../[...nile]/nile"; import { registerTenants } from "@/lib/TenantRegistration";export async function GET(req: NextRequest) { // call the original route const {nile, response} = await handlersWithContext.GET(req); if (nile) { const me = await nile.api.users.me(); if ("id" in me) { // custom logic is here await registerTenants(me.id); } } // return the original response from the route return response;}