Sentry AJAX requests get 302 with Nginx and uWSGI - python

I have Sentry setup almost exactly like described here.
My Sentry is available on www.sentry.mysite.com:9000, and everything working fine, except AJAX queries, for example by click on "resolve error" button. AJAX queries uses url without port, and they always get 302 status and they have no effect.
Kindly help.

Related

Django - Wagtail - Heroku: How to troubleshoot intermittent, seemingly random, HTTP 404s?

I'm serving Wagtail pages in a very well tested web app. No errors show up in development.
When in Production (using Heroku and a hobby-tier Postgres db), those pages occasionally return an HTTP 404. If I refresh the browser a couple times, it goes back to serving the Page perfectly again.
Some details:
This happens with multiple pages;
I get emails with the 404 error when this happens, so Django's BrokenLinkEmailsMiddleware is kicking in;
Heroku web Dyno looks healthy based on its metrics;
Heroku Postgres has no logs for the Hobby tier, so I don't know what's going on on the db side;
Server is running behind a Cloudflare proxy server, but I can see the request hitting the origin and returning a 404.
I'm obviously not expecting a solution here since the above info is insufficent for that. But I'm looking for troubleshooting pointers, for example:
If the db has become under-dimensioned (too little RAM, too many simultaneous connections, etc.) - could that result in a Wagtail db query wrongly returning PageNotFound? Or would that return a 500 Server Error?
How can I test DB error-handling locally with Django?
How can I add a full Traceback for the Django 404 error, so I'm able to know exactly what line of code raised it?
What are other potential causes of intermittent HTTP 404 errors?
Any help here is welcome!

How can I handle subdomains with Flask, Cloudflare and Heroku?

I bought a domain, let's say its "mydomain.org".
I connected that domain to Cloudflare and Heroku, and I can access my web app(site) on mydomain.org, handle the flask's route('/') requests.
But when I use, for example, route('/', subdomain="test") and try to return "This is a subdomain", it does nothing, or if it does, it redirects me to the simple route('/') (so basically without the subdomain).
I registered a subdomain on Heroku and created an alias for test.mydomain.org to point to the DNS that Heroku gave me, but I still get redirected to the main page, instead of getting simply the "This is a subdomain" message.
How could I make it work?

Google App Engine Produces 502 Error on Python/Flask API

I've been all over google, and stack and read EVERY article I could find but have not been able to solve me issue. I recently wanted to take my project that is still in development and get it up on GAE so I could test it and make sure it would work as I assumed. After some trail and error I was able to get a Postgres database setup and push my project using
gcloud app deploy app.yaml
My Flask app is using Swagger and Flask-Restplus for the API. I can access the swagger page and perform some requests, however all of those requests come back with
502 Bad Gatway
While reading the live log in the console I can see the data is coming in as I would expect. There are no exceptions, and the GAE error console does not even log the 502 error. In the console I can also see..
[CRITICAL] WORKER TIMEOUT (pid:17)
So I went into the logs and see this NGINX error..
textPayload: "[error] 32#32: *4086 upstream prematurely closed connection while reading response header from upstream, client: 130.211.2.231, server: , request: "POST /auth/login_user HTTP/1.1", upstream: "http://172.17.0.1:8080/auth/login_user", host: "blah-191811.appspot.com", referrer: "http://blah-191811.appspot.com/""
I don't think it is an error connecting to my database because I can connect to the Postgres DB hosted on GAE from my local computer. I also have another API endpoint that just uses a google API to retrieve some info and that also produces a 502 error.
I am at my wits end, and honestly about to throw in the towel and try to get it going on AWS if I can't figure this out. Any help would be much appreciated.
EDIT WITH MORE INFO:
The problem still persists. However, I have two routes on my API that require a valid JWT header. When using these routes with an invalid header token, or no token the API returns the correct response, a 401. When sending the correct token the API again returns a 502. This makes me believe that there is nothing wrong with my code, but that somewhere the response is not getting sent back.
I should add that these are not data intensive calls. The login_user is just two strings, an email and a password. The database has only one entry in it.
When I run locally but CONNECT to the remote Postgres database the API works as expected. I.e if I run a Flask server locally and do; 127.0.0.1:5000/auth/login_user and send the correct information, it is able to read back from my Postgres database on my GAE project. So I don't believe the database is the issue either.
Still looking for any wisdom because this seems to be a very common issue with little resolve.
For anyone else experiencing this issue..I found the solution after much digging. It was in the way I was connecting to the potgres SQL instance on GAE.
I was using this;
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password#remote.ip.addr/database_name'
This code works fine when you are accessing the SQL instance from a whitelisted IP. However this code will not work inside an instance that also runs on GAE. You need to change it to this;
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password#/database_name?
host=/cloudsql/database_instance_id'

How can I send a GET request from my flask app to another site?

Originally, I tried to post an ajax request from my client side to a third party url, but it seems that the browser have security issues with that. I thought about sending an ajax to the server side, from there to send a GET request to the third party, get the response and send it back to the client side. How can I do that with flask?
Install the requests module (much nicer than using urllib2) and then define a route which makes the necessary request - something like:
import requests
from flask import Flask
app = Flask(__name__)
#app.route('/some-url')
def get_data():
return requests.get('http://example.com').content
Depending on your set up though, it'd be better to configure your webserver to reverse proxy to the target site under a certain URL.
Flask alone does not have this capability, but it is a simple matter to write a request handler that makes a request to another server using an HTTP client library and then return that response.
# third-party HTTP client library
import requests
# assume that "app" below is your flask app, and that
# "Response" is imported from flask.
#app.route("/proxy-example")
def proxy_example():
r = requests.get("http://example.com/other-endpoint")
return Response(
r.text,
status=r.status_code,
content_type=r.headers['content-type'],
)
However, this will not achieve exactly the same result as you might expect from a client-side request. Since your server cannot "see" any cookies that the client browser has stored for the target site, your proxied request will be effectively anonymous and so, depending on the target site, may fail or give you a different response than you'd get requesting that resource in the browser.
If you have a relationship with the third-party URL (that is, if you control it or are able to work with the people who do) they can give access for cross-domain requests in the browser using CORS (which is only supported in modern browsers) or JSON-P (an older workaround that predates CORS).
The third-party provider could also give you access to the data you want at an endpoint that is designed to accept requests from other servers and that provides a mechanism for you to authenticate your app. The most popular protocol for this is OAuth.
As the other answers have stated using the requests module for python would be the best way to tackle this from the coding perspective. However as the comments mentioned (and the reason I came to this question) this can give an error that the request was denied. This error is likely cause by SELinux.
To check if this is the issue first make sure SELinux is enabled with this command:
sestatus
If 'Current Mode' is 'enforcing' then SELinux is enabled.
Next get the current bool values that apply directly to apache with this command:
getsebool -a | grep httpd
Look for the setting 'httpd_can_network_connect' this determines if apache is allowed to make TCP requests out to the network. If it is on then all apache TCP requests will be allowed. To turn it on run the following as root:
setsebool -P httpd_can_network_connect 1
If you only need database access (I had this problem before which is why I suspected SELinux here) then it would probably be better to only turn on 'httpd_cna_network_connect'.
The purpose of this policy is that if a hacker was to hijack your apache server they would not be able to get out through the server to the rest of your internal network.
This probably would've been better as a comment but I don't have enough rep..
Sources:
https://tag1consulting.com/blog/stop-disabling-selinux
https://wiki.centos.org/TipsAndTricks/SelinuxBooleans

How to properly redirect to another site without breaking the browser back button?

I am trying to make a redirection from a python app to another site. I am currently doing it in the controller which works just fine but breaks the back browser button.
I know that a redirection with meta refresh or js, will allow me to add a delay so the user will have time to go back but I read everywhere that these techniques are deprecated and better be avoided.
Any thoughts or ideas?
Thanks
The correct way is sending HTTP status code 302 instead of 200 and adding Location: <url> to response headers. How to do this depends on the WEB framework you are running your Python app on.

Categories