nginx proxy_pass not loading images referenced by a relative link - nginx

I'm running across a strange issue using nginx as a reverse proxy for some apps hosted on github.
The page and referenced JavaScript loads fine, but the images, eg: images/icon.png, are not loading. I'm getting around this for now by using sub_filter to rewrite the relative links to point to the original file address. This is more of a hack than actual fix.
Strangely, the Javascript library is also referenced as a relative link, eg scripts/app.js, and it is loading correctly. I was thinking maybe it's a problem with MIME types, but can't seem to make the images work without the URL rewrite.
Here's the location code snippet:
location ~* /app/data {
rewrite ^/app/data/(.*)$ /app-data/$1 break;
proxy_set_header Host myhost.github.io;
proxy_pass http://myhost.github.io;
gzip on;
gzip_types text/xml;
sub_filter_types text/html;
sub_filter_once off;
sub_filter \"img/ \"http://myhost.github.io/app-data/img/;
}

Related

How to serve static content with multiple websites/paths on Nginx?

I've been following this article trying to host multiple websites on the same machine using IIS and Nginx.
Based on the provided article I produced the following nginx.conf:
http {
server {
listen 80;
server_name localhost;
keepalive_timeout 1;
gzip_types text/css text/plain text/xml application/xml application/javascript application/x-javascript text/javascript application/json text/x-json;
gzip_proxied no-store no-cache private expired auth;
gzip_disable "MSIE [1-6]\.";
# new website
location /bacon/ {
proxy_pass http://127.0.0.1:1500/;
proxy_http_version 1.1;
gzip_static on;
}
# old website
location / {
proxy_pass http://127.0.0.1:8881;
proxy_http_version 1.1;
gzip_static on;
}
}
}
My old website is working just fine.
Yet when I try to access my new website I get the following errors:
Note that my new website works just fine if diretly requested trough http://127.0.0.1:1500/.
What am I missing here?
Url rewrite of proxy_pass directive works only with http request and http redirect in response. That means, that if http://127.0.0.1:1500/; will reply with HTTP 30x Location: http://127.0.0.1:1500/aaaa/, nginx will rewrite it to http://localhost/bacon/aaaa/.
But this rewrite dose not touch response body. Any links in response HTML will be same - <a href="/aaaa/", so no /bacon/ part here.
To fix it there is two ways. First - edit your application. Replace all links with /beacon/ prefix or use relative URL and add <base href="/bacon/"> in head on each file.
If edit of file is not possible, you can rewrite body with ngx_http_sub_module. There is doc of module http://nginx.org/en/docs/http/ngx_http_sub_module.html
In this way you need to add sub_filter for all html constructions where is link used. For example
sub_filter_once off;
sub_filter ' href="/' ' href="/bacon/';
sub_filter ' src="/' ' src="/bacon/';
just need to be careful. You should put all sub_filter to /bacon/ location.
Setup backend application is much preferred but sometimes only sub_filter can help.
Also there is third method but it can be used in some rare cases. If /flutter_servivce_worker.js doesn't exists in 127.0.0.1:8881 backend, you can add custom location for this file and proxy_pass to bacon backend:
location = /flutter_servivce_worker.js {
proxy_pass http://127.0.0.1:1500;
}
Sure this method can help in very limited cases when you are missing only few files and do not use any links.
I believe your first app is loading main.dart.js from the second (at root path) because you forgot to change <base href="/"> to <base href="/bacon/"> in index.html file.
There is nothing to do with NGINX.
For the new site, the request is routed fine and HTML is loaded onto the browser. But the dependant static file references of the application are still pointed to the base location path '/'.
Based on the chosen frontend language, the base route should be changed to /bacon
(or)
create a folder with the name bacon and place the built files in that folder and serve the static content simply using Nginx with webserver configuration
Have you tried?
# new website
location /new/ {
proxy_pass http://127.0.0.1:1500;
proxy_http_version 1.1;
gzip_static on;
}
# old website
location /old/ {
proxy_pass http://127.0.0.1:8881;
proxy_http_version 1.1;
gzip_static on;
}

Odoo13 - Does caching /web/content makes sense?

Typical Odoo installation guide suggests to configure Nginx to cache paths like this:
/web/static
And they are skipping paths that look like this:
/web/image
/website/static
/web_sale/static
I would guess that they should also be cached. But what I'm wondering on is this:
/web/content
This is the path to js and css from assets_common, assets_frontend etc.
Does caching them can lead to some problems? I don't really see why it would be the case.
This is my Nginx config:
location ~* /[0-9a-zA-Z_]*/(static|image|content)/ {
proxy_cache_valid 200 90m;
proxy_buffering on;
expires 864000;
proxy_pass http://odoo;
}

NGINX proxy resource loading issue

I am quite new to NGINX and within this topic it is still very hard for me to find the right buzzwords to have more successful search results. That is why I try to descibe my problem here and maybe some of you can point me in the right direction. For my own personal project I want to set up a website which is composed from several micro services (which have all their own frontend).
My idea was to have one NGINX sever running serving as web server to deliver some kind of HTML which then includes the content of the micro services via server side includes (SSI).
Since the SSI can only include files and local folders as I understand I added some proxy_pass to my local server configuration:
http {
server {
listen 80;
ssi on;
root /usr/share/nginx/html;
location /led-todo {
proxy_pass http://led-todo-frontend:3000/;
}
}
}
So since I have the NGINX and my micro services in the same docker-compose running the URL: http://led-todo-frontend:3000 works.
The issue I am facing now is that when access my index.html page:
<html>
<head>
</head>
<body>
<!--# include virtual="test.html"-->
<!--# include virtual="/led-todo/"-->
</body>
</html>
The index.html content of my micro service is actually included into the above shown html site.
The issue arises when the script tags within my included html content are resolved:
<script src="/static/js/bundle.js">
The browser tries to load them from:
http://localhost:8080/static/js/bundle.js
Instead of:
http://localhost:8080/led-todo/static/js/bundle.js
Which then would again trigger the proxy pass to the correct micro service.
I feel like there should be some parameters to define the root or something so that /static/js/bundle.js is not loaded from localhost:8080 but from localhost:8080/led-todo in the following part of the NGINX configuration:
location /led-todo {
proxy_pass http://led-todo-frontend:3000/;
}
I tried several things I found in the internet here but somehow I am missing the words to describe this issue so that I can find results...
Anyone know how to solve this issue, or know at least some buzzwords I can search for?
This isn't a very elegant solution, but you can try to on-the-fly rewriting that tags content with the ngx_http_sub_module, something like this could work:
location /led-todo/ {
proxy_pass http://led-todo-frontend:3000/;
sub_filter_once off;
# uncomment to do substitution inside CCS or JS content too
# sub_filter_types text/css application/javascript;
sub_filter 'href="/' 'href="/led-todo/';
sub_filter "href='/" "href='/led-todo/";
sub_filter 'src="/' 'src="/led-todo/';
sub_filter "src='/" "src='/led-todo/";
}

Renaming next's output folder from "_next" to "next"

I came across use-case today where I was trying to get my nextjs app working in android webview, unfortunately android doesn't resolve paths that begin with _next and most of my chunk files are under _next/static when I build my app.
Is there a way to to rename this folder from _next to next or anything else?
This issue will give extra context about how android works in this regard Android project is not resolving any static assets
I handled this issue via Nginx Routing.
What i assumed while making this Nginx Routing is that every file will have unique hash and file name combination.
This is the snippet of code of Nginx Routing which i used.
location /static/ {
try_files $uri #server1;
}
location #server1{
proxy_pass http://192.168.1.1$uri;
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 = #server2;
}
location #server2{
proxy_pass http://192.168.1.2$uri;
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 = #server3;
}
location #server3{
proxy_pass http://192.168.1.3$uri;
}
What the above code does is, whenever Nginx encounters /_next/ it will first try that URL with #server1, if that Server responds with 404, the Nginx then transfers the request to #server2 as mentioned in error_page param.
This example works like:
try_files $uri #server1 #server2 #server3
This worked for me as i had 2 apps which were developed on Next and both has _next route.
Let me know if this solves your problem.

Rewriting paths in CSS & JS via nginx's sub_filter

I'm having a problem with nginx's sub_filter rewrite rules not working with CSS files. I'm serving content on a path (/site) and need all URLs in JS & CSS to be prefixed correctly.
I've specified the mime type when linking in the CSS. From the template:
<link href="/static/css/site.css" type="text/css" rel="stylesheet" />
nginx has sub filters enabled and I've explicitly specified to include text/css:
location /site {
access_log /opt/logs/test/nginx-access-site.log combined if=$loggable;
error_log /opt/logs/test/nginx-errors-site.log error;
rewrite ^(/site)$ $1/;
rewrite ^/site(.+) $1 break;
sub_filter "test.domain.tld" "test.domain.tld/site";
sub_filter "'/" "'/site/";
sub_filter '"/' '"/site/';
sub_filter "http:" "https:";
sub_filter_types text/html text/css text/javascript;
sub_filter_once off;
include proxy_params;
proxy_pass http://site_test$1$is_args$args;
proxy_redirect http://test.domain.tld/ https://test.domain.tld/site/;
}
The reference to the CSS file is rewritten correctly. From the HTML output:
<link href="/site/static/css/site.css" type="text/css" rel="stylesheet" />
The issue is it's not rewriting within the CSS file, so image paths are incorrect:
.sortable th .asc {
background-image: url("/static/img/up_arrow.gif");
}
I've tried being overly permissive without any difference:
sub_filter_types *;
Have I misunderstood the use of sub_filter? I assumed that because the CSS was being served directly by nginx it would also be rewritten.
I found the solution after some searching and wasted some time trying some that didn't work so hopefully this helps someone else searching and found this post.
Apparently, by default sub_filter works only for text/html. I tried various other options to enable for text/javascript text/css like this, but which didn't work:
sub_filter_types text/xml text/css text/javascript;
Finally got it working by filtering all types like this:
sub_filter_once off;
sub_filter_types *;
Remember to restart nginx and remember to clear cache on your browser.

Resources