In the introductory post about remote laboratories, a general set of tools to create a framework and handle its various aspects was also introduced. In this blog post, we will explore the implementation of several aspects of the backend app designed with python-flask, and the frontend based on EmberJS. A clear separation of the frontend and backend facilitates minimal disruption of either sections due to the other.
Implementing API methods in Python-Flask
In the Flask web server, page requests are handled via ‘routes’ , which are essentially URLs linked to a python function. Routes are also capable of handling payloads such as POST data, and various return types are also supported.
We shall use an example to demonstrate how a Sign-Up request sent from the sign-up form in the remote lab frontend for PSLab is handled.
@app.route('/signUp',methods=['POST']) def signUp(): """Sign Up for Virtual Lab POST: Submit sign-up parameters. The following must be present: inputName : The name of your account. does not need to be unique inputEmail : e-mail ID used for login . must be unique. inputPassword: password . Returns HTTP 404 when data does not exist. """ # read the posted values from the UI _name = request.form['inputName'] _email = request.form['inputEmail'] _password = request.form['inputPassword'] # validate the received values if _name and _email and _password: _hashed_password = generate_password_hash(_password) newUser = User(_email, _name,_hashed_password) try: db.session.add(newUser) db.session.commit() return json.dumps({'status':True,'message':'User %s created successfully. e-mail:%s !'%(_name,_email)}) except Exception as exc: reason = str(exc) return json.dumps({'status':False,'message':str(reason)})
In this example, the first line indicates that all URL requests made to <domain:port>/signUp will be handled by the function signUp . During development, we host the server on localhost, and use the default PORT number 8000, so sign-up forms must be submitted to 127.0.0.1:8000/signUp .
For deployment on a globally accessible server, a machine with a static IP, and a DNS record must be used. An example for such a deployment would be the heroku subdomain where pslab-remote is automatically deployed ; https://pslab-stage.herokuapp.com/signUp
A closer look at the above example will tell you that POST data can be accessed via the request.form dictionary, and that the sign-up routine requires inputName,inputEmail, and inputPassword. A password hash is generated before writing the parameters to the database.
Testing API methods using the Postman chrome extension
The route described in the above example requires form data to be submitted along with the URL, and we will use a rather handy developer tool called Postman to help us do this. In the frontend apps , AJAX methods are usually employed to do such tasks as well as handle the response from the server.
The above screenshot shows Postman being used to submit form data to /signUp on our API server running at localhost:8000 . The fields inputName, inputDescription, and inputPassword are also posted along with it.
In the bottom section, one can see that the server returned a positive status variable, as well as a descriptive message.
Submitting the sign up form via an Ember controller.
- Setting up a template
We first need to set up a template that we shall call sign-up.hbs , and add the following form to it. This form contains the details essential for signing up , and its submit action is linked to an action called `signMeUp` . This action will be defined in the controller which we shall explore shortly
<form class="form-signin" {{action "signMeUp" on="submit"}} > <label for="inputName" class="sr-only">Your Name</label> {{input value=inputName type="text" name="inputName" id="inputName" class="form-control" placeholder="name" required=true autofocus=true}} <label for="inputEmail" class="sr-only">Email address</label> {{input value=inputEmail type="email" name="inputEmail" id="inputEmail" class="form-control" placeholder="Email address" required=true autofocus=true}} <label for="inputPassword" class="sr-only">Password</label> {{input value=inputPassword type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required=true autofocus=true}} <button class="btn btn-lg btn-primary btn-block" type="submit">Sign Up</button> </form>
- Defining the controller
The controller contains the actions and variables that the template links to. In this case, we require an action called signMeUp. The success, failure, and error handlers are hidden for clarity.
import Ember from 'ember'; export default Ember.Controller.extend({ actions:{ signMeUp() { var request = Ember.$.post("/signUp", this.getProperties("inputName","inputEmail","inputPassword"),this,'json'); request.then(this.success.bind(this), this.failure.bind(this), this.error.bind(this)); }, }, });
The signMeUp action submits the contents of the form to the signUp route on the API server, and the results are handled by functions called success, failure, or error depending on the type of response from the backend server.
Resources:
- Introduction to remote access for PSLab
- Remote execution of function strings via the PSLab web-app
- Postman chrome extension and API testing tool
- Python-Flask : An extensible web microframework for building webapps with Python
- EmberJS : A framework for creating web applications