Giter VIP home page Giter VIP logo

scully-percent-encoded-routes's Introduction

ScullyRoutesSpace

This project was generated with Angular CLI version 12.2.11.

This project was design to reproduce a bug related to routes containing spaces used with the scully SSG.

Reproducing the problem

Run npm install.

Run ng build.

Run npx scully.

Now visit http://localhost:1668/Page%201.

You should see that the page is not loading.

Now visit http://localhost:1668/Page2.

You should see that this page is loading.

General Setup

The app retrieve information from the route to locate the data used to display the contents.

{
  {
    "name": "Page 1",
    "content": "The route has a space in it."
  },
  {
    "name": "Page2",
    "content": "The route has no space in it."
  }
}

Scully Setup

Steps done to install scully.

Run ng add @scullyio/init.

OUTPUT:
ℹ Using package manager: npm
✔ Found compatible package version: @scullyio/[email protected].
✔ Package information loaded.

The package @scullyio/[email protected] will be installed and executed.
Would you like to proceed? Yes
✔ Package successfully installed.
    Installing ng-lib
    Installing Puppeteer plugin
UPDATE src/app/app.module.ts (540 bytes)
UPDATE src/polyfills.ts (3013 bytes)
UPDATE package.json (1233 bytes)
✔ Packages installed successfully.
CREATE scully.scully-routes-space.config.ts (326 bytes)
UPDATE package.json (1307 bytes)
CREATE scully/tsconfig.json (450 bytes)
CREATE scully/plugins/plugin.ts (305 bytes)

Add this to your scully.<project-name>.config.ts.

export const config: ScullyConfig = {
  puppeteerLaunchOptions: {
      executablePath: '/usr/local/bin/chromium'
  },
  ...
}

Route Discovery

How to teach scully how to find all the different routes:

To do this open your scully.<project-name>.config.js and add the following config in the routes section:

exports.config = {
    ...
    routes: {
        '/:name': {   <-- This must be exactly the path that the angular router uses.
            type: 'dataPaths'
        }
    }
}

This is using the JSON plugin that is doing a lot of stuff for you.

Plugin

This plugin will help scully know about all the dynamic path manually.

Just paste this at the top of your ./scully.<project-name>.config.ts:

import { registerPlugin, HandledRoute } from '@scullyio/scully';

function dataPathPlugin(route: string, config = {}): Promise<HandledRoute[]> {

    return Promise.resolve([
        { "route": "/Page%201" },
        { "route": "/Page2" },
    ]);
}

const validator = async (conf: any) => [];
registerPlugin('router', 'dataPaths', dataPathPlugin, validator);

Troubleshooting

Server Side Solution

This is not a scully bug but instead a normal server behavior.

Web static servers (nginx) treats the URI as escaped. A discussion on the nginx websites states that "Locations are matched on unescaped URIs". This means that if you enter http://www.mysite.com/foo%20bar in your browser it will look for /foo bar by default to find a matching file.

In our case, will the static server is running, ./dist/static/Page%201/ is not found because it tries to look for the folder Page 1. I temporally fix the issue by adding this to my nginx.conf:

server {
  ...
  index index.html index.htm;
  ...
  location / {
    try_files $uri $uri/ $request_uri/index.html /index.html;
  }                         ^       ^       ^
                            |       |       |
                         [      Solution       ]
  ...
}

The index index.html index.htm directive tells to look for a index.html file if the user request a directory path.

The try_files within the location directives tries each path to see if it exist and if not, will re-evaluate with /index.html.

In our example of http://localhost/Page%201

  • $uri is /Page 1 and doesn't exist. Then,
  • $uri/ is /Page 1/ and doesn't exist. Then,
  • $request_uri/index.html is /Page%201 and does exist. So it will serve the /Page%201/index.html file.

Scully Side Solution

You maybe wondering, why just change the scully generated folder to /Page 1 by changing ./scully.scully-routes-space.config.ts configuration file like so:

return Promise.resolve([
    { "route": "/Page%201" }, ---> { "route": "/Page 1" }
    { "route": "/Page2" },
]);

I did and this showed up.

  ⚠ handleUnknownRoute: "/Page%201", 404:""
  ⚠ Route "/Page 1" not provided by angular app
  ✔ Route "/Page 1" rendered into "./dist/static/Page 1/index.html"
  ✔ Route "/" rendered into "./dist/static/index.html"
  ✔ Route "/Page2" rendered into "./dist/static/Page2/index.html"

My guest is that angular seems to provide escaped routes and scully require the routes to fit perfectly those used from the angular app. Coming back to the old approach,

return Promise.resolve([
    { "route": "/Page%201" },
    { "route": "/Page2" },
]);
ts

At least the scully renders was successful.

  ✔ Route "/Page%201" rendered into "./dist/static/Page%201/index.html"
  ✔ Route "/" rendered into "./dist/static/index.html"
  ✔ Route "/Page2" rendered into "./dist/static/Page2/index.html"

In this case, my best shot was to built it this way, and then remove the %20 from the folders name.

Conclusion

To me, to avoid this whole headache of escaped space or non escaped space I would say to never use space in a URI in the first place.


Development server

Run ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.

Build

Run ng build to build the project. The build artifacts will be stored in the dist/ directory.

scully-percent-encoded-routes's People

Watchers

Dominic Racine avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.