I'm following this example here for a simple logging middleware setup. But I can't seem to get it to log my request information. I get the standard response when I hit /ping, but nothing is logged out to the console.
I try to register the middleware in two different locations. index.ts and application.ts.
// src/middleware/log.middleware.ts
import { Next } from '@loopback/core'
import { Middleware, MiddlewareContext } from '@loopback/rest'
export const testLoggingMiddleware: Middleware = async (
middlewareCtx: MiddlewareContext,
next: Next,
) => {
const { request } = middlewareCtx
console.log('Request: %s %s', request.method, request.originalUrl)
try {
// Proceed with next middleware
await next()
// Process response
console.log('Response received for %s %s', request.method, request.originalUrl)
} catch (err) {
// Catch errors from downstream middleware
console.error('Error received for %s %s', request.method, request.originalUrl)
throw err
}
}
// src/index.ts
import { ApplicationConfig, RemoteConfigurationsApplication } from './application'
import { testLoggingMiddleware } from './middleware/log.middleware'
import { NodeEnvironmentService } from './services'
export * from './application'
export async function main(
options: ApplicationConfig = {},
): Promise<RemoteConfigurationsApplication> {
const app = new RemoteConfigurationsApplication(options)
app.middleware(testLoggingMiddleware) // trying to add the middleware here as well
await app.boot()
await app.start()
const url = app.restServer.url
console.log(`Server is running at ${url}`)
console.log(`Try ${url}/ping`)
return app
}
if (require.main === module) {
// Run the application
const config = {
rest: {
port: +(process.env.PORT ?? 8081),
host: process.env.HOST,
// The `gracePeriodForClose` provides a graceful close for http/https
// servers with keep-alive clients. The default value is `Infinity`
// (don't force-close). If you want to immediately destroy all sockets
// upon stop, set its value to `0`.
// See https://www.npmjs.com/package/stoppable
gracePeriodForClose: 5000, // 5 seconds
openApiSpec: {
// useful when used with OpenAPI-to-GraphQL to locate your application
setServersFromRequest: true,
},
basePath: `/`,
cors: {
origin: '*',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
preflightContinue: false,
optionsSuccessStatus: 204,
credentials: true,
},
},
}
main(config).catch((err) => {
console.error('Cannot start the application.', err)
process.exit(1)
})
}
// src/application.ts
require('dotenv').config()
import { BootMixin } from '@loopback/boot'
import { ApplicationConfig } from '@loopback/core'
import { HealthComponent } from '@loopback/extension-health'
import { RestExplorerBindings, RestExplorerComponent } from '@loopback/rest-explorer'
import { RepositoryMixin } from '@loopback/repository'
import { RestApplication } from '@loopback/rest'
import { ServiceMixin } from '@loopback/service-proxy'
import * as path from 'path'
import { testLoggingMiddleware } from './middleware/log.middleware'
import { MySequence } from './sequence'
export { ApplicationConfig }
export class RemoteConfigurationsApplication extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
) {
constructor(options: ApplicationConfig = {}) {
super(options)
// Set up the custom sequence
this.sequence(MySequence)
// Set up default home page
this.static('/', path.join(__dirname, '../public'))
// Customize @loopback/http-explorer configuration here
this.configure(RestExplorerBindings.COMPONENT).to({
path: '/explorer',
})
this.component(RestExplorerComponent)
this.component(HealthComponent)
this.middleware(testLoggingMiddleware) // adding middleware in application
this.projectRoot = __dirname
// Customize @loopback/boot Booter Conventions here
this.bootOptions = {
controllers: {
// Customize ControllerBooter Conventions here
dirs: ['controllers'],
extensions: ['.controller.js'],
nested: true,
},
}
}
}
If anyone is still experiencing this problem, this is what worked for me:
import { MiddlewareSequence } from '@loopback/rest';
export class MySequence extends MiddlewareSequence {}
import { Next } from '@loopback/core'
import { Middleware, MiddlewareContext } from '@loopback/rest'
export const exampleMiddleware: Middleware = async (
middlewareCtx: MiddlewareContext,
next: Next,
) => {
const {request} = middlewareCtx
console.log('Request: %s %s', request.headers, request.method, request.originalUrl)
try {
// Proceed with next middleware
const result = await next()
// Process response
console.log('Response received for %s %s', request.method, request.originalUrl)
return result
} catch (err) {
// Catch errors from downstream middleware
console.error('Error received for %s %s', request.method, request.originalUrl)
throw err
}
}
import {ApplicationConfig} from '@loopback/core';
import {RestApplication} from '@loopback/rest';
import {exampleMiddleware} from './middleware/example.middleware';
export class MyApplication extends RestApplication {
constructor(config: ApplicationConfig) {
// register your middleware
this.middleware(exampleMiddleware);
}
}
Reference doc
As mentioned by @Rifa, you need to update MySequence class
Earlier It had the following content-
import { inject } from '@loopback/context';
import {
FindRoute,
InvokeMethod,
ParseParams,
Reject,
RequestContext,
RestBindings,
Send,
SequenceHandler,
InvokeMiddleware
} from '@loopback/rest';
const SequenceActions = RestBindings.SequenceActions;
export class MySequence implements SequenceHandler {
/**
* Optional invoker for registered middleware in a chain.
* To be injected via SequenceActions.INVOKE_MIDDLEWARE.
*/
@inject(SequenceActions.INVOKE_MIDDLEWARE, { optional: true })
protected invokeMiddleware: InvokeMiddleware = () => false;
constructor(
@inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
@inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams,
@inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
@inject(SequenceActions.SEND) public send: Send,
@inject(SequenceActions.REJECT) public reject: Reject
) {}
async handle(context: RequestContext) {
try {
const { request, response } = context;
// Invoke registered Express middleware
const finished = await this.invokeMiddleware(context);
if (finished) {
// The response been produced by the middleware chain
return;
}
const route = this.findRoute(request);
const args = await this.parseParams(request, route);
const result = await this.invoke(route, args);
this.send(response, result);
} catch (err) {
this.reject(context, err);
}
}
}
Replace it with-
import { MiddlewareSequence } from '@loopback/rest';
export class MySequence extends MiddlewareSequence {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With