How to Handle Incomplete Django/Nginx File Server URLs? - django

I have a Django website that uses Nginx on a separate file server to serve up images uploaded by my users. When any user views another user's photos, the link to the photo will have this structure:
https://fs01.mysite.com/media/photos/<username>_<photo-id>.jpg
When the page is rendered, the user's photo is served up by the file server (fs). But what is the Nginx way of handling incomplete (one could also say incorrect) requests to subdirectories of the above URL? For example, if a user enters this URL:
https://fs01.mysite.com
...they see Nginx's default "Welcome to nginx on ..." page. If they enter this URL:
https://fs01.mysite.com/media
...they'll get the Nginx "404 Not Found" page. And if they enter this URL:
https://fs01.mysite.com/media/photos
...they'll get the Nginx "403 Forbidden" page.
How do you handle these situations in Nginx?

They see welcome page, because the nginx matches default vhost entry instead of yours. You should probably delete the default one (/etc/nginx/conf.d/default or /etc/nginx/sites-enabled/default, depending on the linux distribution you use) and make sure that server_name line matches your url (i.e. no slash at the end).
Looks like your location block matckes only media/ (with the slash at the end). Thats why you get 404 error - it matches different location block and is probably handled by Django.
You are not allowed to list the directory, so you get the Forbidden error.
I think that it is up to you how such cases are handled, just make them consistent. Make sure that you understand nginx configuration and the pathways different requests take. To avoid 403 error, you can put empty index.html file in that directory.

Related

How to stop Apache redirecting to index.html

I have a Django app that I am serving with Apache using uwsgi.
When I go to
http://www.myserver.com/
Apache redirects me to
http://www.myserver.com/index.html/
Which then gives me an error "page not found" (the site does not use an index.html page).
The other URLs work fine, eg http://www.myserver.com/mystuff - is correctly served.
How can I stop Apache redirecting the start site to index.html
There are 2 places to look for the problem:
httpd.conf, .htaccess - both are apache web server configuration files.
301 redirects(if you used any before). If you had any, you won't get to your root url unless you purge browser url routing cache(clearing browser data on chrome doesn't help, for example). How to do that - depends on your browser. To read more on that topic http://getluky.net/2010/12/14/301-redirects-cannot-be-undon/

website be opened with redirection from stranger domaine

my problem is:
I own a website developed with django framework and uploaded in heroku.
my domain is "OnlyMyDomain.com", but "StrangeDomaine.com" calls my website with a redirect. in other words when you go to StrangeDomaine.com, my website is opened even if the address change to OnlyMyDomain.com.
I tried in my settings.py:
DEBUG = False
ALLOWED_HOSTS = ['OnlyMyDomain.com']
Please can someone explain to me where the problem is coming from? and how can I avoid it?
There is no problem. It seems that you define a permanent redirection (301) from StrangeDomain.com to OnlyMyDomain.com. Then request url will be updated, then StrangeDomain.com becomes OnlyMyDomain.com. If you want to avoid that, just remove this redirection.
The HTTP response status code 301 Moved Permanently is used for
permanent URL redirection, meaning current links or records using the
URL that the response is received for should be updated. The new URL
should be provided in the Location field included with the response.
Wiki : HTTP 301

How to deploy static website connecting to Django RESTful API?

First of all, google or SO search didn't help me: lots of tips regarding django's staticfiles, which I believe are not relevant here.
I have inherited a project consisting of:
Django backend in form of API returning JSON responses only;
standard Swampdragon deployment pushing realtime updates to frontend; very little configuration has been done here;
Frontend webapp built on Backbone and marionette.js, compiled and minified by Grunt.
My problem is: the frontend needs to know addresses for swampdragon and django servers; right now those values are hardcoded, so there is for example a Backbone model with lines like:
url: function() {
return App.BACKEND_URL+'settings/map';
}
Why hardcoded: backend can be served on any port or have a subdomain to itself; frontend is static and normally would be simply thrown into /var/www (for Apache) or would use some very simple nginx config. Both will be served from the same place, but there is no guarantee the port numbers or subdomains would match.
Idea number 1: try to guess what BACKEND_URL is from javascript, by taking window.location.host and appending standard port. That's hackish and error prone.
Idea number 2: move frontend to Django and make it ask for swampdragon credentials (they would be sent in the context of home view). Problem with that is, the frontend files are compiled by grunt. So where Django would kindly expect something like:
<script src="{% static 'scripts/vendor/modernizr.js' %}"></script>
I actually have
<script src="scripts/vendor/a8bcb0b6.modernizr.js"></script>
Where 'a8bcb0b6' is grunt's hash/version number and will be regenerated during next minification/build. Do I need to add additional logic to get rid of such stuff and copy grunt's output directory to django's static and template dirs?
Or is there another way to make this work, the right one, I am missing?
Your architecture is already clean, no need to make Django know about grunt or serve static files, and no need to use JS hacks to guess port numbers
Reverse Proxy
Use a reverse proxy like nginx or any other web server you like as a front end to both the static files and the REST API.
In computer networks, a reverse proxy is a type of proxy server that
retrieves resources on behalf of a client from one or more servers.
These resources are then returned to the client as though they
originated from the proxy server itself. (Wikipedia)
I will outline the important aspects without going into too much detail:
URL for the REST API
We make configs so that nginx will forward the API requests to Django
location /api {
proxy_pass http://127.0.0.1:8000; # assumes Django listens here
proxy_set_header Host $http_host; # preserve host info
}
So the above assumes your Django REST is mapped to /api and runs on port 8000 (e.g. you can run gunicorn on that port, or any other server you like)
http://nginx.org/en/docs/http/ngx_http_proxy_module.html
URL for our front end app
Next nginx will serve the static files that come out of grunt, by simply pointing it to the static folder
location / { alias /app/static/; }
The above assumes your static resources are in /app/static/ folder (like index.html, your CSS, JS etc). So this is primarily to load your BackboneJS app.
Django static files
Next step is not required, but if you have static files that you use with the Django app (static files that are generated with ./manage.py collectstatic, e.g. the django admin or the UI of Django REST Framework etc), simply map according to your Django settings.py STATIC_URL and STATIC_ROOT
location /static { alias /app/django_static_root/; }
/static and django_static_root being the STATIC_URL and STATIC_ROOT respectively
To sum up
So e.g. when you hit example.com/, nginx simply serves up the static files, then when a JS script makes REST call to /api, it gets trapped in the /api nginx location and gets forwarded to Django
End result is, example.com/ and example.com/api both hit the same front end web server, which proxies them to the right places
So there you have it, reserve proxying solves your ports and subdomain issues (and many others, like slow static files from Django and same-origin policies in web browsers and firewalls not liking anything besides default HTTP and HTTPS ports)

ember cli url not working on server with manual return key (versus link-to)

An ember cli site was deployed onto a server and it works fine. Links via {{link-to}} all work beautifully.
BUT, when a user (me that is) manually enters a url and hits return. then the site is not found.
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
even changing a parameter of a working url (initially navigated to thru link-to)
http://site/start/0/length/30
and simply backspacing, changing the 30 to 20 and hit return
http://site/start/0/length/20
its a no go
localhost:4200 doesn't have this issue.
has anyone observed this vicious behaviour.
i actually need it for a callback redirect for oauth. but then noticed than any manually entered urls dont function.
It is because your server (IIS?) is trying to access the full path requested by your browser (eg /start/0/length/30), and not finding a valid file on disk returns a 404.
So, you need to configure your web server to proxy/rewrite the requests to the proper location. Assuming you are deploying your application in your "root" directory, the proper location is /index.html (the file ember-cli creates).
Unfortunately, I can't help you with IIS, but I can provide you with the proper configuration for nginx:
location / {
try_files $uri $uri/ /index.html;
}
This says "If the requested URI doesn't exist, instead respond with the /index.html file".
When you are using ember server on localhost:4200 you don't have the same problem because it is automatically doing something similar transparently.
If you are serving this up from any web server that isn't the built in Ember, ie non local server, you need to have a wildcard rule that returns your Ember app's index.html file for anything below your websites base url. If you only have your base url return the index.html file, then your webserver is confused by the unrecognized url and thinks it has nothing to return. If your rule, though,
for baseUrl/* returns index.html, your Ember app will then run the correct route hooks to establish the app context
this is a dupe and the question is
How to run emberJS application in IIS?
the easy answer is set locationType: hash in ember-cli's environment.config file (copied from accepted answer)
that will introduce a '#' in the url but doesnt require an IIS change.
var ENV = {
...
locationType: 'hash'
... };

Why is my picture not displaying after upload with Django-Userena?

When I go to edit a user profile and upload a new profile pic it does not show up. Instead I see a broken link with the following error.
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/site_media/media/mugshots/4cfb402cad.jpg
Using the URLconf defined in dealr.urls, Django tried these URL patterns, in this order:
^$
^admin/
^accounts/
The current URL, site_media/media/mugshots/4cfb402cad.jpg, didn't match any of these.
What is strange about this is that inside my project folder I actually have /site_media/media/mugshots/ and the exact file that was uploaded (with the same filename), so I'm not sure why it is not displaying the picture. Do I need to do something to my URLS.PY to allow for the viewing of this file? That's the only thing I can think of.
It seems your server cannot find your files. Make sure you have configured your static and media roots in your settings.py (for manage.py runserver).
If you are using a production server you will need to tell it where those directories are.
As an example if you are working with nginx:
server {
[...]
location /static/ {
alias /path/to/my/staticfiles/;
}
}