hapijs / inert

Static file and directory handlers for hapi.js
Other
238 stars 49 forks source link

`redirectToSlash` not being applied #146

Open jungleBadger opened 4 years ago

jungleBadger commented 4 years ago

Support plan

Context

What are you trying to achieve or the steps to reproduce?

I'm defining a custom endpoint named /docs/js which would serve any file in the existent /docs/js directory located at the root path of my project, this is the output of my JSDoc automation routine, so an index.html is served from there and inner CSS/JS should be loaded upon the rendering of that index.

Similarly, I want to do the same to swagger and test coverage, so I would just replicate the same pattern.

Everything works fine, except the redirectToSlash functionality, I did some digging through the plugin source code and if I remove this snippet demonstrated below, the functionality works as expected.

Anotação 2020-07-05 153447

app.js

(async function () {

        const appPort = process.env.APP_PORT || process.env.PORT || process.env.VCAP_APP_PORT || 8080;
    const Hapi = require("@hapi/hapi");
    const vision = require("@hapi/vision");
    const inert = require("@hapi/inert");
    const path = require("path");
    const fs = require("fs");

    let server = Hapi.server(
        {
            "port": appPort,
            "tls": process.env.LOCAL_HTTPS ? {
                "hostname": "localhost",
                "agent": false,
                "key": fs.readFileSync("./root/certificates/local/localhost-privkey.pem"),
                "cert": fs.readFileSync("./root/certificates/local/localhost-cert.pem"),
                "rejectUnauthorized": false
            } : null,
        }
    );

    await server.register(vision);
    await server.register(inert);

    server.route({
        "method": "GET",
        "path": "/docs/js/{param*}",
        "handler": {
            "directory": {
                "path": path.join(__dirname, "/docs", "js"),
                "redirectToSlash": true
            }
        },
    });
}());

Project structure

Anotação 2020-07-05 154015

Equivalent express code

const express = require("express");
const app = express();
let server = require("https").createServer(
    {
        "hostname": "localhost",
        "agent": false,
        "key": fs.readFileSync("./root/certificates/local/localhost-privkey.pem"),
        "cert": fs.readFileSync("./root/certificates/local/localhost-cert.pem"),
        "rejectUnauthorized": false
    },
    app
)

app.use("/docs/js", express.static(__dirname + "/docs/js"));
app.use("/docs/test", express.static(__dirname + "/docs/test/lcov-report"));
app.use("/docs/api", express.static(__dirname + "/docs/api/swagger-ui-dist"));

What was the result you got?

  1. When I access localhost:port/docs/js I got the index.html and extra css/js can't be loaded.
  2. When I access localhost:port/docs/js/ I got the index.html and all extra css/js works smoothly.
  3. When I access localhost:port/docs/js the requests are not redirected to localhost:port/docs/js/

What result did you expect?

  1. Access localhost:port/docs/js and be redirected to localhost:port/docs/js/ since the redirectToSlash option is set to true.

PS: I validated that:

  1. That handler is being executed
  2. No other handler is messing with this one
  3. If I manually insert the / at the end, it works fine
  4. I did some debugging in the directory.js code and if I remove/comment the snippet mentioned above, the slash is appended to the URL as expected.
  5. No change was made to stripTrailingSlash configuration, the defaults are in place
  6. I performed some console.log instructions and here is what I got

inert/lib/directory.js line 123

if (internals.isDirectory(error)) {
     console.log(resource);
     console.log(settings);
     console.log(request.server.settings.router.stripTrailingSlash);
     console.log(hasTrailingSlash);
     // more code below
}

Anotação 2020-07-05 154358

  1. Finally, even though the console.log is showing /docs/js/, the request in the browser (and also using curl) is not being redirected as expected, as demonstrated below.

Anotação 2020-07-05 154930

Anotação 2020-07-05 154938

sholladay commented 4 years ago

I have a suspicion that this may have the same root cause as #145. The reason I'm thinking that is path.resolve() removes trailing slashes, whereas path.join() does not. The path joining was removed in https://github.com/hapijs/inert/commit/4514a5e367aeb03be94fc04294c5b30e509eebef.

cjihrig commented 4 years ago

Does anyone want to open a PR to fix the issue?