I'm using Eve to create a REST API for MongoDB.
It's all working fine, except for the fact that I can't reach the API from any other computer (in the same network), or even a different URL (e.g.: if I set SERVER_NAME = 'localhost:29000', I will not be able to reach the API with 127.0.0.1 and vice versa).
I've been looking around for hours, and I can't seem to find an answer. I also tried other REST API's for MongoDB like Kule, and they seem to work just fine, but they don't have as many options as Eve has.
Eve's SERVER_NAME seems to be based on the configuration variable by the same name from Flask: See "More on server name" below the table in the Flask Configuration docs. So it's really just for the name (hostname / subdomain handling) - the actual network interfaces it binds to therfore are probably determined by the server that runs the WSGI application.
If you're just doing the
app = Eve()
app.run()
from the quickstart example, try
app.run(host='0.0.0.0')
instead and leave the server name empty (SERVER_NAME = '').
I've never used Eve, but from what I understand about how it's built that should work
Related
I wrote a Flask web application for a system that our company uses. However, we have another web application, which is running on Node.JS. The "problem" is that my colleague writes everything on node, while I write everything in Python.
We want to implement both applications on one webpage - for example:
My application will run on example.com/assistant
His application will run on example.com/app1 and example.com/app2
How can we do this? Can we somehow implement the templates that I use with his templates and vice-versa?
Thank you in advance!
V
Serving different apps from the same domain
You can use haproxy for directing requests to specific service based on ACL rules.
You could use path_beg rule, to direct any request beginning with specific path to be directed to corresponding server. See example below.
/etc/haproxy/haproxy.cfg
# only relevant part of the config file
# assumes all apps are on one machine
frontend http-in
bind *:80
acl py_app1 path_beg /assistant
acl node_app1 path_beg /app1
acl node_app2 path_beg /app2
default_backend main_servers
backend py_app1
server flask_app 127.0.0.1:5000
backend node_app1
server nodejs1 127.0.0.1:4001
backend node_app2
server nodejs2 127.0.0.1:4002
backend main_servers
server other1 127.0.0.1:3000 # nginx, apache, or whatever
Sharing template code between apps
This would be harder, as you would need to both agree on some kind of format, which needs to be language and framework-agnostic, and probably logic-less.
Mustache claims to be "framework-agnostic way to render logic-free views". I used it sparringly a few years ago so this one is first that came to mind, however you should do more research on this, maybe there is some better fit.
Python implementation
JS implementation
The problem would be to actually keep the templates always in sync with apps, and not break functionality of the views. If a template changes then you would need to test all apps that use this template file. Also, you probably will block one another from updating your apps at different times, because if one of you change the template files, then you must come to a consensus, update all relevant apps, and deploy them at one time.
I am going through some CTF challenges at https://recruit.osiris.cyber.nyu.edu/challenges.
I got to one for Template Programming where the task is to "Read /flag.txt from the server. http://recruit.osiris.cyber.nyu.edu:2000"
I am not asking for a solution, but I would like some better understanding of what is going on below:
What is this code doing?
Should I be worried about running out of Debugging mode and/or using host="0.0.0.0"?
What are some resources that could help me understand this? I tried reading through the Flask documentation and the tutorialspoint page, but I am unclear as to how this doesn't just set up a local server for testing as opposed to accessing a remote server...
If I ctrl+C do I need to worry about leaving a server still running on an open port when I am not in Debugging mode?
#!/usr/bin/env python3
from flask import Flask, request, abort, render_template_string
import os.path
app = Flask(__name__)
#app.route('/', methods=['GET'])
def index():
name = request.args.get('name')
if name is not None:
return render_template_string(open('templates/hello.html').read().format(name=name))
return render_template_string(open('templates/index.html').read())
if __name__ == "__main__":
app.run(host="0.0.0.0")
I think I can answer most of these.
As you probably already figured out, Flask is a fairly basic web framework. By the look of things, what you have there is a copy of the code running at the CTF site. It displays just two pages; one that contains the initial web form (templates/index.html) and another that uses a query string variable to greet the user (templates/hello.html) when a name has been provided.
You don't really have to run this code yourself. The 0.0.0.0 host address is catch-all that matches all IPv4 addresses on the local machine, which would include local addresses like 192.168.0.1 and 127.0.0.1 as well as the IP address used for incoming connections to the server.
Like I said, this is the code running on the remote server.
I think what you need to do is find some way of crafting a request to this web service in such a way that it reveals the contents of /flag.txt instead of (or perhaps in addition to) just saying hello. A quick search for something like "flask include file vulnerability" should give you some idea of how to attack this problem.
From this page:
UPLOADS_DEFAULT_URL
If you have a server set up to serve from
UPLOADS_DEFAULT_DEST, then set the server’s base URL here. Continuing
the example above, if /var/uploads is accessible from
http://localhost:5001, then you would set this to
http://localhost:5001/ and URLs for the photos set would start with
http://localhost:5001/photos. Include the trailing slash.
However, you
don’t have to set any of the _URL settings - if you don’t, then they
will be served internally by Flask. They are just there so if you have
heavy upload traffic, you can have a faster production server like
Nginx or Lighttpd serve the uploads.
I do not understand how Flask uses UPLOADS_DEFAULT_URL. The text says that if you don't specify it the uploads will be served internally by flask. Questions:
On what url are they going to be served by flask if I don't specify the url?
If I do specify URL what flask is going to do with it? How is it going to use it?
So it's easier to answer my question: I don't know how exactly python interacts with a web server such as apache or nginx. I do understand that in principle you want these web servers to front/proxy you python app for scalability/load but I don't know exact details on how this is done. May be if I knew that, the information above would be more obvious to me.
From practical perspective: I have someone else's python/flask app, and not a lot of experience with python. The parameter above needs to be specified in the config files. I got the app up and running, I did not specify this particular parameter, the uploads are working fine. I'm wondering what else could I have possibly broken by not specifying the URL.
On what url are they going to be served by flask if I don't specify the url?
From the doc i understand that if you set like this
UPLOADS_DEFAULT_DEST = '/var/uploads/'
UPLOADS_DEFAULT_URL = 'http://localhost:5000/'
Then when you upload a set named photos will store its uploads in /var/uploads/photos.Lets assume it as /var/uploads/photos/test.jpg.Then flask will serve the image as
http://localhost:5000/photos/test.jpg.
If I do specify URL what flask is going to do with it? How is it going to use it?
Let if
UPLOADED_PHOTOS_DEST = '/var/mypics/'
UPLOADED_PHOTOS_URL = 'http://localhost:5000/'
Then when you upload a set named photos will store its uploads in /var/mypics/.Lets assume it as /var/mypics/test.jpg.Then flask will serve the image as
http://localhost:5000/test.jpg.
But we do not use this in production.In production images, statics should be served by nginx or apache
I have a website developed in flask running on an apache2 server that responds on port 80 to two URLs
Url-1 http://www.example.com
Url-2 http://oer.example.com
I want to detect which of the two urls the user is coming in from and adjust what the server does and store the variable in a config variable
app.config['SITE'] = 'OER'
or
app.config['SITE'] = 'WWW'
Looking around on the internet I can find lots of examples using urllib2 the issue is that you need to pass it the url you want to slice and I cant find a way to pull that out as it may change between the two with each request.
I could fork the code and put up two different versions but that's as ugly as a box of frogs.
Thoughts welcome.
Use the Flask request object (from flask import request) and one of the following in your request handler:
hostname = request.environ.get('HTTP_HOST', '')
url = urlparse(request.url)
hostname = url.netloc
This will get e.g. oer.example.com or www.example.com. If there is a port number that will be included too. Keep in mind that this ultimately comes from the client request so "bad" requests might have it set wrong, although hopefully apache wouldn't route those to your app.
I'm currently working on a project using Flask and Google App Engine. Calling get_flashed_messages() returns empty when I flash a message then use a redirect():
#views.route('/todo/add', methods=["POST"])
def add_todo():
flash('hey')
return redirect(url_for('todo_list'))
However, if I comment out
# SERVER_NAME = 'localhost'
then it seems to work fine. My problem is that I have to use subdomains so I need SERVER_NAME to be set.
What is the deal?
I got it!
The trick is to set server name to something with dots.
So 'localhost' became 'app.local' and app.local should be added to /etc/hosts, pointing to the same address as localhost.
From the docs:
Please keep in mind that not only
Flask has the problem of not knowing
what subdomains are, your web browser
does as well. Most modern web browsers
will not allow cross-subdomain cookies
to be set on a server name without
dots in it. So if your server name is
'localhost' you will not be able to
set a cookie for 'localhost' and every
subdomain of it. Please chose a
different server name in that case,
like 'myapplication.local' and add
this name + the subdomains you want to
use into your host config or setup a
local bind.
did you set up cookies to work across all subdomains?
by default they are only readable on the domain that set them