HW3 Part A is due tonight (lock date also tonight)
Any questions?
Web service: software functionality that can be invoked through the internet using common protocols
It's like a remote function(s) you can call. Done by contacting a program on a web server
Merriam-Webster Dictionary API
NASA APOD API
CSE154 web services:
GET, POST, PUT, DELETE
By default, fetch makes a GET request
POST is commonly used to make a request to submit some data
PUT and DELETE are less common, and we won't use them in this class.
GET
POST
These POST examples are commonly used with forms!
We've used the analogy of a customer (client) ordering from a waiter at a restaurant (server). In this analogy, what might a customer ask for from "GET" request? What might a "POST" request be?
Image source (a wonderful reading to explain front-end vs. back-end/server relationships)
When no security is needed, sending query parameters using a "GET" request (Parameters passed visibly in the URL bar or request header) is acceptable.
function requestMenu() {
let url = CAFE_URL + "?menu=cafe-menu";
//fetch by default is a GET request
fetch(url)
.then(checkStatus)
.then(resp => resp.json())
.then(handleResponse)
.catch(handleError);
}
JS
function adminLogin() {
let url = CAFE_URL;
// Create a new "FormData" object
let params = new FormData();
// Add the various parameters to the FormData object
params.append("username", "cse154");
params.append("password", "coffee");
// Fetch now with a method of POST and the param data in the body
fetch(url, {method: "POST", body: params})
.then(checkStatus)
.then(resp => resp.json())
.then(updateResults)
.catch(handleError);
}
JS
There are two ways you'll commonly see forms used with POST
<form id="input-form" method="post" action="submitter.php">
City: <input name="city" type="text"/ >
State: <input name="state" type="text" />
ZIP: <input name="zip" type="number" />
<button id="submit-btn">Submit!</button>
</form>
HTML
As soon as the submit button is clicked on this page, the data is sent to the web service (submitter.php) and the page is refreshed with the response (sometimes redirecting).
This is becoming less common because we lose the asynchronous features of requests.
<form id="input-form">
City: <input name="city" type="text"/ >
State: <input name="state" type="text" />
ZIP: <input name="zip" type="number" />
<button id="submit-btn">Submit!</button>
</form>
HTML
let url = "submitter.php";
let params = new FormData(id("input-form"));
fetch(url, { method : "POST", body : params })
.then(checkStatus)
.then(...)
.catch(...)
JS
Compare this new submit behavior here.
What do you think are the trade-offs between the two approaches?
When an input is in a form along with a button, clicking the button automatically verifies the input and does a POST request.
If you do not want the page to refresh, you need to use preventDefault to override default form submission behavior (used in previous example).
function init() {
id("input-form").addEventListener("submit", function(e) {
// Fires when submit event happens on form
// If we've gotten in here, all HTML5 validation checks have passed
e.preventDefault(); // prevent default behavior of submit (page refresh)
submitRequest(); // do more validation with JS and then fetch with FormData
});
// rest of code
JS
Many websites offer features that allow users to interact with the page and request/submit data to servers. Unfortunately, not all users will behave as expected.
Take a look at your handout and talk with your neighbors to answer the questions (handout also provided here).
User input validation is the process of ensuring that any user input is well-formed and correct (valid).
Q: What are some examples of input validation you came up with?
Validation can be performed:
Prioritizing validation is important as web developers so that the websites we build are:
If you're interested in learning more, MDN has a good quick introduction to web security, and OWASP is a fantastic resource for all things related to web security. You can also find a good article on how to write user-friendly form UIs here.
The takeaway? There are many ways to perform validation, but MDN/OWASP both are great resources to refer to based on the context of your websites
Most importantly, don't trust that users will provide correct/safe input!
<form>
<label for="city-input">City: </label>
<input name="city" type="text" />
<label for="state-input">State: </label>
<input name="state" type="text" />
<label for="zip-input">ZIP: </label>
<input name="zip" type="number" />
<button id="submit-btn">Submit!</button>
</form>
HTML
output
We can validate this input in a few different ways:
We've already seen some ways to use HTML5 tags to require certain types of input by
adding attributes to your <input> tags to help with validation
<input type="number">
HTML
We can limit the up and down arrows with min (and max if we choose)
<input type="number" min=0>
HTML
To insist that there is a value in the input field we can add required
<input type="number" required>
HTML
To prevent a user from being able to type in erroneous values, we can add a
regular expression to the required attribute
<input type="number" required="\d+">
HTML
form<form>
<label for="city-input">City: </label>
<input name="city" type="text" required/>
<label for="state-input">State: </label>
<input name="state" type="text" size="2" maxlength="2" required/>
<label for="zip-input">ZIP: </label>
<input name="zip" type="number" size="5" min=10000 max=99999 required/>
<button id="submit-btn">Submit!</button>
</form>
HTML
Forms are HTML elements that can be used to "package" user input values based on the name attribute, often used with POST requests. There are many neat ways to perform validation with the right choice of form elements!
Solution code (try adding more validation methods on your own!):
<form id="input-form">
<div>
<label for="name-input">Name: </label>
<input id="name-input" name="student-name" type="text" required/>
</div>
<div>
<label for="email-input">E-mail (@uw.edu): </label>
<input id="email-input" name="email" type="email" required/>
</div>
<div>
<label for="sid-input">Student Number: </label>
<!--
A valid student number is 7 digits; demo considering students between 2010 (min) and 2019
(max) to demonstrate min/max
-->
<input id="sid-input" name="sid" type="number" min=1000000 max=1999999 />
</div>
<div id="minute-options">
<label>2-Minute Question <input type="radio" name="minutes" value=2 /></label>
<label>10-Minute Question <input type="radio" name="minutes" value=10 /></label>
</div>
<textarea name="question" minlength=20 rows=10 placeholder="Enter your question..."></textarea>
<button id="submit-btn" type="submit">Enter Queue!</button>
</form>
HTML
/**
* Override the default submission behavior for the form's submit event.
*/
function init() {
id("input-form").addEventListener("submit", function(evt) {
// if we've gotten in here, all HTML5 validation checks have passed
evt.preventDefault();
submitRequest();
});
}
wpl.js
/**
* Send form data to the WPL web service. Note that this function
* is called only after all HTML5 validation constraints
* (e.g. required attributes) have passed!
*/
function submitRequest() {
// Solution 1: Can use form DOM element as parameter to FormData!
let params = new FormData(id("input-form"));
// Note that unlike GET requests, no url parameters passed in a POST request!
fetch(URL, { method : "POST", body : params })
.then(checkStatus) // The wpl.php will return text for this demo, no JSON
.then(resp => resp.json())
.then(showResponse)
.catch(handleError);
}
wpl.js
This submitRequest() function is called in the overriden submit behavior
(from previous slide).
/**
* Send form data to the WPL web service.
*/
function submitRequest() {
let params = new FormData();
// Build the 4 parameters for our POST request
params.append("sid", qs("input[name='sid']").value);
params.append("name", qs("input[name='name']").value);
params.append("minutes", qs("textarea").value);
params.append("question", qs("input[name='minutes']:checked").value);
fetch(URL, { method : "POST", body : params })
.then(checkStatus)
.then(resp => resp.json())
.then(showResponse)
.catch(handleError);
}
wpl.js
We can also use the append method to append parameters one at a time (in this example, wpl.php only expects the 4 POST parameters)
While this is a bit more work, we don't always need to send all form elements in an API request, and it also gives us more control over validation checks in JS (for properties you can't check with HTML5 attributes) before the fetch.