GitHub pages leads to 404 error for URLs with forward slash - github-pages

I was able to deploy a single page site (index.html + vanilla JavaScript) with custom URL on GitHub pages but my URLs with forward slash / display 404 - File not found.
https://example.org - works as expected and my site gets displayed.
https://example.org/home - here /home results in 404.
After running a few tests I found copying index.html into a folder docs/home/index.html resolves this but this is going to be difficult to maintain for many nested URLs. I will have to create multiple folders for each URL.
This can also be fixed using # instead of / so my url becomes https://example.org#home but this might not be good for search engines.
Another option is that I prefix /?/ for all urls which works but seems a bit hacky
https://example.org/?/home
https://example.org/?/home/page1
https://example.org/?/home/page1/page2
Another option that I haven't tried is have a 404.html with the same content as index.html but this is not a proper use of 404.
I really don't know how to fix this. How do I make my URLs with forward slash / work GitHub pages?

Related

How to exclude the images directory in a redirect source in NextJS

I followed this tutorial which is perfect for my NextJS website.
The problem is my unsupported.html file has images in it. The images 404 because according to the redirects everything except unsupported.html will redirect (including the images).
So here is Chrome vs IE. So Chrome works because I manually went there and it won't redirect anything because it's not IE.
How can I add to this part source: '/:path((?!unsupported.html$).*)', to say don't redirect unsupported.html AND anything in the /public/images/ folder?
Thanks
This feels close
source: '/:path((?!unsupported.html|.*images*$).*)',
Does this work for your site?
source: '/:path((?!unsupported\.html$|images/).*)',
The key bit is dropping the $ anchor from after images, so it doesn't have to (not) match the actual image name

Prepend URL to all URLs in Django

Was wondering if there was a way to prepend all URLs with a particular URL. I'll explain the challenge, perhaps I'm going about it all wrong:
Imagine I have three sites all built using Django that are run using nginx and within separate docker containers: main_site, project1 and project2.
When navigating to https://main_site, this should load the pages in main_site as normal.
But when navigating to https://main_site/projects/project_1/,
This should navigate to project 1.
And similarly, when navigating to https://main_site/projects/project_2/, this should load the pages from project 2.
I've managed to make this somewhat work using nginx and docker.
I have rules something along the lines of:
location / {
proxy_pass http://main_site;
}
location /projects/project_1 {
proxy_pass http://project_1;
}
location /projects/project_2 {
proxy_pass http://project_2;
}
This works perfectly for the homepage (minus the static assets).
But, whenever we use template tags in Django, the links in creates is always relative to root (/something/), whenever on any link, it takes me back to the main_site.
I get why this is happening, because everything is happening on the same port.
Question is, is there a way to prepend a URL to all the URLs (static assets as well) without fundamentally having to add reverse or something. I don't want to have to manually add the link to all pages.
Or, does anyone know of a better way to overcome this challenge?

Next.js: How to make links work with exported sites when hosted on AWS Cloudfront?

I'm trying to get a prototype Next.js project up by doing a Static html export (i.e. next export) and then copying the generated output to AWS S3 and serving it via Cloudfront.
I've got the following two pages in the /pages directory:
index.tsx
Pricing.tsx
Then, following along from the routing doco I added a Link to the pricing page from the index page, like so:
<Link href="/Pricing">
<a>Pricing</a>
</Link>
This results in a link that looks like example.com/Pricing (when you hover over it and when you click the link, the page does change to the pricing page and the browser shows example.com/Pricing in the URL bar).
The problem is, that link is not real - it cannot be bookmarked or navigated to directly via the url bar.
The problem seems to be that when I do a next export, Next.js generates a .html file for each page, but the router doesn't use those .html suffixes.
So when using the site, if the user tries to bookmark example.com/Pricing; loading that bookmark later will fail because Cloudfront will return a 404 (because CF only knows about the .html file).
I then tried changing my Link to look like:
<Link href="/Pricing.html">
<a>Pricing</a>
</Link>
That causes the router to use example.com/Pricing.html and that works fine with Cloudfront - but it actually causes a 404 during local development (i.e. using next dev)!
Other workarounds I could try are renaming all the .html files and removing the extension before I upload them to S3 (and make sure they get a content-type: text/html header) - or introducing a Cloudfront lambda that does the renaming on the fly when .html resources are requested. I don't really want to do the lambda thing, but the renaming before uploading shouldn't be too difficult.
But it feels like I'm really working uphill here. Am I doing something wrong at a basic level? How is Next.js linking supposed to work with a static html export?
Next.js version: 9.5.3-canary.23
Alternate answer if you want your URLs to be "clean" and not have .html on the end.
To get Next.js default URL links working properly with S3/Cloudfront, you must configure the "add a trailing slash" option in your next.config.js:
module.exports = {
trailingSlash: true,
}
As per the documentation
export pages as index.html files and require trailing slashes, /about becomes /about/index.html and is routable via /about/. This was the default behavior prior to Next.js 9.
So now you can leave your Link definition as:
<Link href="/Pricing">
<a>Pricing</a>
</Link>
This causes Next.js to do two things:
use the url example.com/Pricing/ - note the / on the end
generate each page as index.html in it's own directory - e.g. /Pricing/index.html
Many HTML servers, in their default configuration, will serve up the index.html from inside the matching directory if they see a trailing / character in the URL.
S3 will do this also, if you have it set up to serve as a website and IFF you access the URL through the website endpoint, as opposed to the REST endpoint.
So your Cloudfront distribution origin must be configured as a Origin type = Custom Origin pointing at a domain something like example.com.s3-website.us-east-1.amazonaws.com, not as an S3 Origin.
If you have your Cloudfront/S3 mis-configured, when you hit a "trailing slash" style URL - you will probably see your browser download a file of type binary/octet-stream containing 0 bytes.
Edit: Beware pages with . characters, as per issue 16617.
Followup to Shorn's self-answer of using the as field in the next/link component. This worked for me, however it would fail if I refreshed the page I was on.
Instead, I used exportPathMap to link my pages to a page.html equivalent that would be created when running next export.
The downside of this approach is that when running next start, those .html files will not be created or accessible. They will, however, from next dev. As I am creating a purely static website, I've now just been using next dev.
While making this change I was validating by manually copying my built assets from next export into S3 and hosting in CloudFront as Shorn was doing -- I no longer do this to validate and haven't had issues so far.
If anyone knows, let me know what I else may be missing by ignoring next start as part of development. This solution has worked for me so far though.
After writing this question, I found a reasonable workaround - though I'm not sure if it's the "right" answer.
Change the Link to:
<Link href="/Pricing" as="/Pricing.html">
<a>Pricing</a>
</Link>
This seems to work in both local dev and for bookmarking the site as served by Cloudfront. Still feels kind of wonky though. I kind of like those non .html urls better too. Oh well, maybe I'll do the renaming workaround instead.

Make django handle subdomain suffix

We're hosting several dockerized web-apps on our webserver, let's call it group.example.com. Our subdomains are handled via nginx as suffixes though, which translates to something like group.example.com/app1/ group.example.com/app2/ as root urls.
When using Django, we run into problems though, as all its urls generated by url in the templates such as home will be relative links, so rendered to home. This relative link will not be interpreted correctly, leading to the main, non-app page group.example.com.
So the goal is to have an app based prefix such as /app1/ for all links. I can hardcode these for static links, but there has to be a more elegant way. Also this leads to problem for the used forms submitting to the wrong page - redirecting again back to the main, non-app page group.example.com.
I tried adding /app1/ to all registered urls as prefix, but that doesn't seem to work either - that way the app is running but user would need to visit group.example.com/app1/app1/ to get to the index, and the relative links still don't work correctly.
In the app docker-container we're running the web-app with nginx and uwsgi. It works fine when using correct subdomains such as app1.example2.com - but we don't have that capability on our new faster webserver we want to host the app on.
Is there a way to resolve this using the app containers nginx, uwsgi or django / middleware config to get the links to resolve to group.example.com/app1/ as root?
As far as I know, there is two ways to resolve it.
One use SCRIPT_NAME in the NGINX configuration. For example, based on this server fault answer:
location /app1/ {
SCRIPT_NAME /app1;
# rest of the config
}
Two You can add FORCE_SCRIPT_NAME in your settings.py:
FORCE_SCRIPT_NAME = '/app1'
FYI, I would prefer using first solution.

Django: Site-Wide URL Prefix

I've built a Django site that will live at the root when it's live. Right now it's functioning perfectly at the IP address. For testing purposes, the client has pointed a proxy url at it, but the url has /folder/path in it, so none of the URL patterns match. I put (/folder/path)? into all the url patterns so they now respond, but all of the links are broken because I'm using the {% url %} tag and while the url patterns will match the optional path, they don't include it in that tag.
Clearly I can just hard-code /folder/path into all of my urls (well, into all of the url includes) until testing is complete, but is there a better way to do this?
You manage this when you deploy your application, by correctly setting the WSGIScriptAlias in your Apache configuration (assuming you're using mod_wsgi, which you should be doing). This is passed on to Django, which then automatically prefixes all URL reverse lookups with the correct value. You shouldn't need to do any manual mucking about with prefixes.
For this purpouse I use URL_PREFIX in settings.py and add it in each include in urls.py. I also add it at the beginning of MEDIA_URL, for all images/css/js links to work. But I would also like to hear about some more tricky solution?
if WSGIScriptAlias doesn't work or you can't set it up for some reason, remember that the include() function in a urlconf adds the prefix to all URLs. you can create an urlconf which includes your current root urlconf and mount it at the prefix, and then point your settings.py file to that urlconf.
Disclaimer: haven't tried this myself, but it should work.