Koa.js - serving static files and REST API

22,294

Solution 1

It was a little hard for me to follow what you were doing in your example code... Here is a simple example that does everything your wanting:

'use strict';
let koa     = require('koa'),
    send    = require('koa-send'),
    router  = require('koa-router')(),
    serve   = require('koa-static');

let app = koa();
// serve files in public folder (css, js etc)
app.use(serve(__dirname + '/public'));

// rest endpoints
router.get('/api/whatever', function *(){
  this.body = 'hi from get';
});
router.post('/api/whatever', function *(){
  this.body = 'hi from post'
});

app.use(router.routes());

// this last middleware catches any request that isn't handled by
// koa-static or koa-router, ie your index.html in your example
app.use(function* index() {
  yield send(this, __dirname + '/index.html');
});

app.listen(4000);

Solution 2

const root = require('path').join(__dirname, 'client', 'build');
app.use(serve(root));

app.use(async ctx => {
    await send(ctx, `/index.html`, {
        root
    });
});

Solution 3

From @Nurpax in the comments:

app.use(async function (ctx, next) {
  return send(ctx, '/index.html', { root: paths.client()
})
.then(() => next()) }) 

The key thing was to specify {root:<some path>}. I think the problem in my case was that for security reasons, send doesn't allow relative paths or paths outside of the project tree. Specifying the root param and then giving a filename relative to that seemed to fix the problem. I guess I expected koa-send to log an error/warning on the node output about this.

Share:
22,294
suricactus
Author by

suricactus

Updated on July 22, 2022

Comments

  • suricactus
    suricactus almost 2 years

    I'm new to koa.js library and I need some help. I'm trying to make simple REST application using koa. I have a static html and javascript files I want to serve on route / and REST API accessing from /api/.

    This is my project directory tree:

    project
    ├── server
    │   ├── node_modules
    │   ├── package.json
    │   └── src
    │       ├── config
    │       ├── resources
    │       └── server.js
    ├── ui
    │   ├── app
    │   ├── bower.json
    │   ├── bower_components
    │   ├── dist
    │   ├── node_modules
    │   ├── package.json
    │   └── test
    

    This is my source:

    var app = require('koa')();
    app.use(mount('/api/places', require('../resources/places')));
    
    // does not work
    var staticKoa = require('koa')();
    staticKoa.use(function *(next){
      yield next;
      app.use(require('koa-static')('../ui/app', {}));
    });
    app.use(mount('/', staticKoa));
    
    // does not work
    app.use(mount('/', function*() {
        app.use(require('koa-static')('../ui/app/', {}));
    }));
    
    // does not work
    app.use(mount('/', function*() {
        app.use(require('koa-static')('.', {}));
    }));
    // GET package.json -> 404 not found
    

    I've tried koa-static, koa-static-folder, koa-static-server libraries and neither works so I'm doing something wrong.

    I've tried this and it works, but I don't have access to my REST api:

    var app = require('koa')();
    app.use(require('koa-static')('../ui/app/', {}));
    
    • James Moore
      James Moore over 8 years
      Does my answer make sense, do you have other questions?
    • suricactus
      suricactus almost 8 years
      I forgot yo upvote your answer. Almost an year later, thank you :)
  • Believe2014
    Believe2014 almost 8 years
    What is the pointer this in the ` this.body = 'hi from get'; `?
  • hoodsy
    hoodsy almost 8 years
    I've been wrestling with this for koa v2, maybe you can provide some insight? app.use(async (ctx, next) => { await send(ctx, path.join(__dirname, '../', 'client/index.html')) }) I get a 404 not found error for some reason... Although with a bit of a hack I can serve the individual html file, if it isn't the folder, I'm not able to load my images, etc.
  • Nurpax
    Nurpax over 7 years
    @hoodsy Did you ever come up with an answer? I tried app.use(async (ctx, next)... and wasn't able to get that to work. Tried various different variants but nothing seems to work.
  • hoodsy
    hoodsy over 7 years
    @Nurpax I've got a really hacky solution from another thread I found here: stackoverflow.com/questions/24024566/…
  • Nurpax
    Nurpax over 7 years
    @hoodsy Through trial and error, I was able to get this working last night: app.use(async function (ctx, next) { return send(ctx, '/index.html', { root: paths.client() }).then(() => next()) }) The key thing was to specify {root:<some path>}. I think the problem in my case was that for security reasons, send doesn't allow relative paths or paths outside of the project tree. Specifying the root param and then giving a filename relative to that seemed to fix the problem. I guess I expected koa-send to log an error/warning on the node output about this.
  • Nurpax
    Nurpax over 7 years
    FWIW, I've run into so many problems with this koa vs koav2 thing, that I'm seriously considering porting all my stuff to express. Koa examples on the net seem to be fragmented among koa and koa v2, making it hard to get any example code working.
  • hoodsy
    hoodsy over 7 years
    @Nurpax nice job! I'm going to have to give this a shot. A lot of the time I find myself referencing Express examples and porting them to Koa. I love the async/await style though, and would really enjoy Koa2 being widely adopted. I feel your frustrations as well.
  • Vadim Boltach
    Vadim Boltach over 7 years
    Have no idea why did you put promises in code. Just use await :) app.use(async (ctx) => { await send(ctx, '/index.html', { root: STATIC_FOLDER_PATH, }); });
  • dKab
    dKab over 7 years
    what is the difference between koa-send and koa-static here? why do we need both of them? Can't we serve files from '/public' with koa-send? Thanks!
  • Rahman Malik
    Rahman Malik about 5 years
    @hoodsy, I am using app.use(async (ctx, next) => await ctx.send(`${__dirname}/public/index.html`)) and it works fine.
  • Jason Aller
    Jason Aller about 4 years
    Code only answers can almost always be improved by adding explanation of how and why they work.