Nginx try_files & rewrite & content type - nginx

I'm currently migrating from lighttpd to nginx.
I've got some weird files (don't ask why):
1. say a file named 'news', which actually should be more like news.txt
2. a file named '.html', which actually should be index.html
With lighttpd, simply rewrite those things would work.
Nginx would still locate those files with try_files or rewrite, but I've got no control of the content type returned. I mean if the file is named '.html', the content type is 'application/octet-stream'.
I know I can use more_set_headers to achieve that, but is there any other way to do that? I mean why does nginx think a file named '.html' not an html file?

I mean why does nginx think a file named '.html' not an html file?
A dot at the beginning in unix-like systems is usually used as the indicator of hidden files. In this case, a part after the dot isn't file extension.
I know I can use more_set_headers to achieve that, but is there any other way to do that?
You should use the default_type directive instead of 3-rd party modules.
For example:
location =/.html {
default_type text/html;
}

Related

nginx .jpg and .jpeg not found in / but are found everywhere else

I'm new to nginx and I like it.
I'm putting up a few scgi feeds, and some static content.
After creating a home page hierarchy under /home, I went to move it to /.
But when I put it there the .jpg and .jpeg images were coming back 404.
sitename.com/test.gif is found just fine.
sitename.com/test.jpg is 404
but creating a a subdirectory, and copying test.jpg work.
sitename.com/subdirectory/jpg is fine.
I'm running with pretty empty config files as they were installed under Ubuntu 18.
I'd REALLY like to know what's going on here, and why top level .jpg/.jpeg files are doing this.
I know I could create a location directive as follows:
location ~ \.(jpg|jpeg)$ {
root /real/location/of/my/home/;
}
But that breaks access to .jpg/jpeg files in the scgi locations served from other roots.
I found it! It wasn't the jpg/jpeg suffix. It was the filename!
I have a /wdc location that is an scgi script.
A file in / that begins wdc for example /wdc-face.jpg goes through to scgi.
Many of the nginx example give locations without trailing slashes. But I think that a trailing slash is what people should be encouraged to use by default

Rewrite rule to add characters to beginning of urls in nginx where they are missing

I'm working on a legacy site where all urls must begin with the single available language code '/en'.
Is it possible with nginx to rewrite urls that do not begin with '/en' so that it is added (the legacy application will then be able to find the content and serve it)?
E.g.
http://www.example.com/ -> http://www.example.com/en/
http://www.example.com/page1 -> http://www.example.com/en/page1
http://www.example.com/en/page1 -> http://www.example.com/en/page1
Yes, this is possible. It's a bit difficult to give you a full solution since you haven't provided the config file, but I'll give it a shot.
You're looking for something along the lines of:
if ($request_uri !~ "^/en.*"){
return 301 $scheme://www.example.com/en$uri;
}
Note: This should appear immediately after your server_name and listen directives and not in a location block (see here).
I hope this helps.

How to add cors to nginx in elasticbeanstalk?

I spent days now in researching on how to add some headers to nginx. All I try to do is adding these lines:
location ~ ^/(assets)/ {
add_header Access-Control-Allow-Origin *;
}
What is the best way to put these lines into the nginx.conf?
Is there also a way to not overwrite the standard nginx.conf just in case beanstalk updates the settings so I wont miss it?
The default elastic beanstalk nginx.conf seems to have this line toward the end :
include /etc/nginx/conf.d/*.conf;
(Well, I can tell you that's what the file looks like for the docker solution stack versions 1.4.1 and 2.0.4, no idea if that's guaranteed across all solution stacks).
So I think one way would be to to drop a file named whatever.conf into the /etc/nginx/conf directory using the ebextensions mechanism .

conditional rewrite or try_files with NGINX?

I'm having trouble setting up a conditional rewrite, and I've been trying to use the if directive (despite all sources indicating it's "evil") with the -f switch to check for the presence of a file, but it's not working. I believe the issue/case is best explained by example, so here goes:
Directory structure
workspace/
myapp/
webroot/
index.php
assets/
baz.js
hello/
foo.js
modules/
hello/
assets/
foo.js
bar.js
Expected results
/ => /workspace/myapp/webroot/index.php
/assets/hello/foo.js => /workspace/myapp/webroot/assets/hello/foo.js
/assets/hello/bar.js => /workspace/myapp/modules/hello/assets/foo.js
/assets/baz.js => /workspace/myapp/webroot/assets/baz.js
In summary:
foo.js is only present in the modules/hello/assets folder and gets delivered from there.
bar.js is present both in webroot/assets/hello and modules/hello/assets and gets delivered from webroot.
(it hides/overrides the file in modules)
baz.js is only present in webroot/assets and gets delivered from there.
The part that doesn't work right now, is this:
location /assets/ {
if (-f $uri) {
break;
}
root /workspace/myapp/modules;
rewrite ^/assets/([^/]+)/(.*)$ /$1/assets/$2 break;
}
Namely the if directive, doesn't seem to have any affect - the bar.js file gets delivered from modules rather than webroot.
Should I be using if or not?
Is there any way I can solve this problem with try_files instead? I can't seem to grasp how this would work together with rewrite which I can't seem to get around.
Please do not suggest reorganizing the assets using a deploy script or something - it's not an option, for various other reasons.
I have used this pattern with Apache before, and NGINX seems more capable in most respects, so I'm sure this must be possible?
One requirement that isn't absolute, is I don't have to be able to override modules/hello/assets/foo.js with webroot/assets/hello/foo.js - serving scripts from webroot/assets/* is however a requirement.
The answer is divided into two parts: the first part explains why your configuration does not work and the second one provides examples of how to solve your problem. If you are only interested in the solution, go straight to the second part.
The problem
First of all, note that the positon of the root directive in a location block is not important. It does not matter if you put it at the very top or at the bottom of a location, it will affect the whole location anyway. Also, keep in mind that break in the end of the rewrite line tells Nginx to stay within the current location even if the URI has been successfully rewrited.
Having said that, let's take a look at your configuration and see how every request from the Expected results is processed and why nothing works as expected.
Let's presume that there is no other suitable location with a higher priority in your configuration. Since every request from Expected results starts with /assets, all of them will be handled according to the rules presented in your location. So:
/assets/hello/foo.js
The root is set to /workspace/myapp/modules. The if directive will be evaluated to false, because /assets/hello/foo.js does not exist and so break will not be executed. Finally, the last rewrite will change the requested URI from /assets/hello/foo.js to /hello/assets/foo.js and the following break will tell Nginx to stay within the current location. As a consequence /workspace/myapp/modules/hello/assets/foo.js will be served.
/assets/hello/bar.js
This request is processed exactly the same way as the previous one, so /workspace/myapp/modules/hello/assets/bar.js will be served.
/assets/baz.js
Yet again the root is set to /workspace/myapp/modules and the if is evaluated to false. But this time the final rewrite will not change the URI, because the request does not match the regular expression. As a consequence Nginx will try to serve /workspace/myapp/modules/assets/baz.js and since there is no such file exists, will return 404.
As you can see your configuration cannot possibly work as you want it to for several reasons:
if is always evaluated to false, because you try to check URIs and not files;
the request stays within the location because you tell it to stay there with break in the rewrite line;
root is always set to /workspace/myapp/modules in this location so no file can be served from anywhere else.
The solutions
The easiest solution would be to use try_files:
root /workspace/myapp/webroot;
location /assets/ {
try_files $uri #modules;
}
location #modules {
root /workspace/myapp/modules;
rewrite ^/assets/([^/]+)/(.*)$ /$1/assets/$2 break;
}
This configuration tells Nginx to look for a file in the webroot folder first and if nothing is found then go to the modules folder in another location. This approach is considered most preferable.
On the other hand, using if would allow you to solve the problem within one location:
location /assets/ {
root /workspace/myapp; # The parent folder
if (-f $document_root/webroot/$uri) {
rewrite ^(.*)$ /webroot/$1 break;
}
rewrite ^/assets/([^/]+)/(.*)$ /modules/$1/assets/$2 break;
}
However, this approach is considered outdated is not recommended for use.

Config for Enabling SSI nginx?

I want to do server side include and i have nginx server installed in my machine and i cant find a way to enable ssi in nginx.conf file?
all i can find from the internet is
syntax: ssi on | off;
default:
ssi off;
context: http, server, location, if in location
Enable ssi on the location context. In my case i want it on root
location / {
ssi on;
}
It looks like you were having the same problem I was having; finding a crystal clear explanation of how to enable SSI on NGINX. Crystal Clear entails not just which syntax to use, but the format, and exactly where to include it. I figured it out and it's not that difficult, but the lack of clear instructions on the internet was frustrating.
You'll need to open up the nginx.conf file and look for the section that is formatted as follows (I've included the 'ssi on' syntax as well):
location / {
root E:\website\FinalJRLWeb;
index index.html index.shtml;
ssi on;
}
It took me a bit to realize the location, but it's really as simple as adding the line 'ssi on' right underneath the specified index file names (and it should be able to really go anywhere you'd like, I don't imagine the order matters, just as long as it's within the two brackets {}).
After that, to verify that SSI is working on your NGINX server, add the following line anywhere in the 'body' tag of a blank html page
<!--#echo var="DATE_LOCAL" -->
and save it with the extension .shtml in your web server's root directory.
You should see the server's local date and time displayed upon visiting your page. I realize this is almost a year old, but after my frustration trying to find clear instructions, I wanted to do my best to try and provide clear instructions for anyone else that may need them. So hopefully this will help someone out!
Here's NGINX's documentation page on SSI (which honestly was not helping me as much as I would have liked, but it nonetheless is useful, and can only become more and more useful)
http://nginx.org/en/docs/http/ngx_http_ssi_module.html#ssi_last_modified
By default ssi is only apply to the text/html MIME Type; which might offer you frustration, though clearly documented here http://nginx.org/en/docs/http/ngx_http_ssi_module.html#ssi_types
you may need to add
ssi on;
ssi_types *; # Or something more specific
Enabling SSI on NGINX for a single domain
To enable SSI for just one domain (limiting possible security holes), you can add it as follows to the .conf file for that domain - in Debian these are (controversially for some) stored in the Apache-like system under "etc/nginx/sites-available".
server {
server_name mydomain.com;
root /home/username/html;
index index.html index.shtml;
location / {
ssi on;
...otherstuffhere
}
}
The crucial parts:
index index.html index.shtml;
ssi on;

Resources