0

I've found this Q&A on loopback, but it doesn't work for 4.0: strongloop loopback how do I serve-static with a route?

I want to serve some basic static content. Or maybe even arbitrary content.

This is how things usually work with express apps:

export class SomeLoopbackApp extends RestApplication {

  constructor() {
    const app = this;
    app.static('/', path.join(__dirname, '../../public'));
    app.get('/hello', (req, res) => {
      res.send('Hello world!')
    });
  }
}

For reasons, neither of these work in Loopback 4. I've tried finding a way to access the actual express instance hidden somewhere in Loopback (I'm pretty sure it uses one), but I can't seem to find it.

How do I make loopback serve static content?

Seph Reed
  • 8,797
  • 11
  • 60
  • 125

2 Answers2

2

I am severing static content in loopback 4 the following way.

export class InstrideIdentityApiApplication extends BootMixin(
  ServiceMixin(RepositoryMixin(RestApplication))
) {
  this.static('/', path.join(__dirname, '../../public'));
}

However, you could run an express server and serve static content from express and then bing loopback 4 and express app together.

https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html

Clay Risser
  • 3,272
  • 1
  • 25
  • 28
  • Hmmm... this does not seem to be working. Is loopback not express based? Its documentation seems to imply it is. – Seph Reed Apr 17 '20 at 20:23
2

To serve static files, this.static() can be used:

import path from 'path';

export class TodoListApplication extends BootMixin(
  ServiceMixin(RepositoryMixin(RestApplication)),
) {
  constructor(options: ApplicationConfig = {}) {
    super(options);

    // ...

    this.static('/', path.join(__dirname, '../../public'));
  }
}

While LoopBack 4 does use Express.js internally to re-use some of its features, it does not expose the entire API under normal circumstances.

There are some bindings under RestBindings.Http that can be used to inject the Express.js RequestContext, Request, or Response objects into a controller. However, this should be considered a last resort.

If accessing these bindings are necessary, it is strongly recommended to inject them into a controller to take advantage of the lifecycle management and booters in LoopBack 4:

// /src/controllers/redirect.controller.ts
import {inject} from '@loopback/context';
import {get, Response, RestBindings} from '@loopback/rest';

export class RedirectController {
  constructor(@inject(RestBindings.Http.RESPONSE) private res: Response) {}

  // Map to `GET /redirect`
  @get('/redirect', {
    responses: {
      '302': {
        description: 'Redirect Response',
      },
    },
  })
  redirect(): void {
    this.res.setHeader('x-secret-sauce', 'Sugar, spice and everything nice.');
    this.res.redirect('https://www.example.com/');
  }
}

The above code snippet shows how to set a response header and return a redirect. Though any parts of the Express.js Response API can be used.

Further reading:

Rifa Achrinza
  • 1,555
  • 9
  • 19
  • I tried this, but it seems that returning html responses is not straight-forward. Put in an issue about it: https://github.com/strongloop/loopback/issues/4321 – Seph Reed Apr 20 '20 at 20:35
  • @SephReed FYI, `strongloop/loopback` is for LoopBack 3 which is going to EOL in December 2020. Issues related to LoopBack 4 must be opened in `strongloop/loopback-next`. Also, it is strongly recommended to use the CLI to scaffold the application. This would make the issue more easily solvable and reproducible. – Rifa Achrinza Apr 21 '20 at 02:46