0% found this document useful (0 votes)
17 views

Dev Web

quazar

Uploaded by

fotsoarole
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

Dev Web

quazar

Uploaded by

fotsoarole
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 38

Web Application Development

INF3048 – S6

HTTP and RESTful Communication between


Web Clients and Servers

Jacques Robin and Camilo Correa © 2023-2024


Outline
The request-response communication pattern between a web
front-end client and a web back-end server
The HyperText Transfer Protocol (HTTP)
The REpresentational State Transfer (REST)
REST(ful) API
The Fetch browser API to request resource from a web client
to a web server
json-server: a simple tool to fake a REST API
postman: a simple tool to fake a REST API client and debug
the REST API server
The Request-Response Pattern
All front-end back-end communications are initiated from the front-end
(a.k.a., pull only)
The front-end sends a request object for a resource available from the
back-end
The server answers to the request by sending a response object which
payload contains the requested resource
The Request-Response Pattern
The requested resource can be anything:
A server-side generated (a.k.a., prerendered) HTML page
A CSS style sheet
A JavaScript module
JSON data
A static media file (image, audio, video)
The code of a 2D or 3D graphic or animation to be executed by the
front-end, etc.
It can be:
Persistently stored in the back-end, or
Dynamically generated by the back-end from other resources accessible
to the server
The Request-Response Pattern

Figure source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview


The HyperText Transfer Protocol (HTTP)
An application layer protocol
Basic version is simple
But extensible through headers
Using HTTP, the interaction
between:
 The browser (or more generally user
agents) where the frontend of a web
app is running, and
 The web server
(software and hardware), where the
backend of the web app is running  Figure source:
 Can be mediated by multiple intervining https://developer.mozilla.org/en-US/docs/Web/HTTP/Ov
erview
machines and software called web
proxies
 That perform functions like:
 Content caching to improve content load speed
 Load balancing
 Authentication
 Content filtering (for security, parental control, etc.)
 Logging
 etc.
HTTP Messages
Reminder: URL structure
Reminder: URL Examples
HTTP Messages
HTTP Methods (a.k.a. verbs)
GET to fetch a resource at a given URL
The response to a GET request contains the resource in its body property
POST to create a new resources at a given URL
The body of a POST request contains the resource to create on the server
at the given URL
The resource has been typically created by the user filling an HTML form
The default MIME type of the body is:
application/x-www-form-urlencoded
It can be more legibly separated by using the alternative
multipart/form-data MIME type
Examples:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST#example
The choice between the two can be indicated in:
The enctype attribute of a <form> element
The formenctype attribute of an <input> or <button> element
HTTP Methods
PUT to either:
Update an existing resources with a new value at the given URL, or
Create a new resources if there was non on the server at the given URL
The response to a creation PUT is 201 (Created)
The response to a update PUT is 200 (OK)
Example:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PU
T#example

PUT differs from POST by being idempotent:


After successive PUT requests sent with the same URL and payload the
server is in the same state than after a single such request
After successive POST requests sent with the same URL and payload,
creates multiple copies of the resource on the server
HTTP Methods
DELETE to delete a resource from a given URL
HEAD to prefetch only the headers that would come with a
GET request at a given URL
Useful for GET request conditional upon the header content
GET, DELETE and HEAD are idempotent
REpresentational Stateless Transfer (REST)

Scientifically:
Architecture pattern from Roy Fielding’s 2000 PhD thesis
Independent of the web
Specialization of client-server pattern
Maximize decoupling between client and server to allow a wide
heterogeneity of different clients to use the same service
Request-Response client-server interaction
Request content by name independently of type and underlying
implementation
Response is a textual representation of the resource
Stateless: client state not stored on server but sent by client in each
request needing it to be properly processed by the server
REpresentational Stateless Transfer (REST)

Vernacularly for web development:


Communication protocol is HTTP
Requested content name is a URL
Textual response representation uses a mark-up language
HTML, JSON, YAML, XML, etc.
HTTP verbs are loosely matched to CRUD DB operations for requests that
are direct DB access with no mediating calls to complex business logic
functions:
POST → Create resource (not idempotent)
GET → Read resource
PUT→ Update resource
DELETE → Delete resource
Upsert DB operation and resource nesting (e.g., collections of items structured as
attribute sets) make the difference between Create and Update not very crisp
Hence, usage of POST vs. PUT in RESTful API is rarely strictly followed
Resource structural nesting can be reflected by URL route nesting
With PUT item id must be sent by the client
While with POST it can be created by the server and returned in the response
Session information in URL and cookies are not strictly RESTful
HTTP Status Codes
https://www.restapitutorial.com/httpstatuscodes.html
The Fetch API of web browsers
Built-in API of web browsers to communicate with a remote
web service over the network using HTTP requests and
responses
Asynchronous since based on JavaScript promises
The fetch() window method takes as argument either:
Just the URL of a web resource in case of a simple GET request
Since GET is the default HTTP method when none is specified
or both URL and an HTTP request object, which can be constructed
using new and specifies the HTTP method and many other optional
properties
or just a request object which must then include the resource URL as a
property
Since a URL can be a local file path, fetch can be used to retrieve and
update data locally
In such case, the promise returned always resolves with a response since
no network is involved and hence no network error can occur
The Fetch API of web browsers
A call to fetch() returns a promise which:
Resolves into another promise which resolves into an HTTP Response
object which includes the resource fetched by the method at that URL
The json() method of the response object returns the response body in
textual form
Rejects into a network error if one occurs
To be safe, fetch calls should thus appear into:
A try-catch structure with async-await
or a raw promise then-catch structure without async-await
fetching a resource at a non-existing URL does not rejects the returned
promise, but resolves it with a response with a status property such as
404 Not Found
Example of simplest fetch(url) call
const getTodos = async () => {
const response = await fetch('todos/luigi.json')
const data = await response.json()
return data
}

getTodos()
.then(data => console.log('resolved:', data))
.catch(err => console.log('rejected:', err.message))

Source: the Net Ninja YouTube channel: Asychronous JS #11


Example of fetch(url, request) call
async function putData(url = "", data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: "PUT", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, *cors, same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: "follow", // manual, *follow, error
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}

putData("https://example.com/answer", { answer: 42 }).then((data) => {


console.log(data); // JSON data parsed by `data.json()` call
JSON Server
NPM package that makes data formatted as JSON files
locally stored on one's computer folder
to be accessible through REST requests
from the front-end side of a web application
It wraps the JSON files containing the data with a local
development web server and a REST API endpoint
allowing testing the REST requests made from the front-end
of a web application
before or independently from the back-end development
JSON Server: installation and
data structure convention
To install it: npm install -g json-server
To simulate a database, structure your JSON files with:
Each top-level key corresponding to a table name in a relational
database or a collection name in a document database
Each top-level value being an array of nested JSON objects, each one
representing a record (a.k.a, row) in a relational database table or a
document in a document database collection
Each such nested JSON object must have a special "id" property that
uniquely identifies it
JSON server: example JSON file following
conventional structure
{
"posts": [
{
"id": 1,
"likes": 30,
"title": "Welcome to the new blog",
"body": "Hello world"
},
{
"id": 2,
"likes": 15,
"title": "How to be a Net Ninja",
"body": "Hi word!"
},
{
"title": "New Quasabase course coming soon!",
"body": "Hello Quasabase!",
"likes": 20,
"id": 3
},
{
"title": "Mario Kart Live review",
"body": "Hello Mario!",
"likes": 69,
"id": 4
}
],
"polls": [
{
"id": 1,
"question": "Do you prefer Vue or React?",
"answerA": "Vue",
"answerB": "React"
}
]
}
JSON server: listening to HTTP requests
In root project folder, running:
json-server --watch <JSON File Path>
makes json-server responds to requests at URL:
http://localhost:3000/<Top Level JSON File Key>
To fetch a specific collection in the file just do:
fetch(http://localhost:3000/<Top Level JSON File Key> + id)
For a POST request of a JSON object without an id property,
json-server adds a new id property automatically to the record
being posted, as a remote web server would do
JSON Server: sorting GET request example
const container = document.querySelector('.blogs')
const renderPosts = async (term) => {
let uri = 'http://localhost:3000/posts?_sort=likes&_order=desc'
const res = await fetch(uri)
const posts = await res.json()
let template = ''
posts.forEach(post => {
template += `
<div class="post">
<h2>${post.title}</h2>
<p><small>${post.likes} likes</small></p>
<p>${post.body.slice(0, 200)}...</p>
<a href="/details.html?id=${post.id}">Read more</a>
</div>
`
})

window.addEventListener('DOMContentLoaded', () => renderPosts());

Source: the Net Ninja YouTube channel: Up & Running with JSON Server
JSON Server: text search request example
const container = document.querySelector('.blogs')
const searchForm = document.querySelector('.search')
const renderPosts = async (term) => {
let uri = 'http://localhost:3000/posts?_sort=likes&_order=desc'
if (term) {uri += `&q=${term}`}
const res = await fetch(uri)
const posts = await res.json()
let template = ''
posts.forEach(post => {
template += `
<div class="post">
<h2>${post.title}</h2>
<p><small>${post.likes} likes</small></p>
<p>${post.body.slice(0, 200)}...</p>
<a href="/details.html?id=${post.id}">Read more</a>
</div>
`
})

window.addEventListener('DOMContentLoaded', () => renderPosts());


Source: the Net Ninja YouTube channel: Up & Running with JSON Server
JSON Server: POST request example
const form = document.querySelector('form')

const createPost = async (e) => {


e.preventDefault()
const doc = {
title: form.title.value,
body: form.body.value,
likes: 0,
}

await fetch('http://localhost:3000/posts', {
method: 'POST',
body: JSON.stringify(doc),
headers: { 'Content-Type': 'application/json' }
})

window.location.replace('/')
}

Source: the Net Ninja YouTube


form.addEventListener('submit', channel: Up & Running with JSON Server
createPost);
JSON Server: DELETE request example
const id = new URLSearchParams(window.location.search).get('id')
const container = document.querySelector('.details')
const deleteBtn = document.querySelector('.delete')
const renderDetails = async () => {
const res = await fetch('http://localhost:3000/posts/' + id)
if (!res.ok) {window.location.replace("/")}
const post = await res.json()
const template = `
<h1>${post.title}</h1>
<p>${post.body}</p>
`
container.innerHTML = template;
}

deleteBtn.addEventListener('click', async () => {


const res = await fetch('http://localhost:3000/posts/' + id, {
method: 'DELETE'
});
window.location.replace("/");
})

Source: the Net Ninja YouTube channel: Up & Running with JSON Server
window.addEventListener('DOMContentLoaded', renderDetails);
HTTP Cross-Origin Resource Sharing (CORS)

 Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
CORS
Origin of a web resource: the triple (scheme, domain, port) of its URL
By default, web browsers enforce the same-origin security policy
restricting JavaScript code loaded from one origin to make HTTP
request to another origin, to prevent cross-site scripting attacks
e.g., the JavaScript inside the HTML page initially requested to server
with origin O1, contains a call to Fetch making a request to another
server of origin O2 to get some JSON data
e.g., access public API from dev server
HTTP CORS headers are meant to allow cross-origin requests
overriding the same-origin default
They require value modifying requests such as PUT and DELETE
coming from another origin to be preceded by so-called preflight
OPTION request
The CORS headers in the response to the OPTION request will tell
the client what URL is allowed to modify the resource with what
method
CORS
Example: clone the jsonServerWebStoragePersistent branch of
GitLab calcquasarstudents repository,
https://gitlab.esiea.fr/webdev/calcquasarstudents/-/tree/JsonS
erverWebStoragePersistent?ref_type=heads

Launch the calculator app using "quasar dev" or "npm run


dev" on one terminal
On another terminal launch json-server using
"npm run json-serve"
In the browser running the calculator app, open More Tools /
Developer Tools and then the Network tab and in it the All
subtab
Then click on a GET button of the app: only one get request
appears
CORS
Check the Headers tab, then the
properties:
 General /
Referrer Policy property
 Response Headers /
Access-Contol-Allow-Methods
 Response Headers /
Access-Contol-Allow-Origin
 Request Headers /
Host
 Request Headers /
Origin
 Request Headers /
Referer
and the Response tab
CORS
The Response Headers:
Access-Control-Allow-Methods: GET, HEAD, PUT, PATCH, POST, DELETE
Access-Control-Allow-Origins: *
are set in such permissive way by json-server, because it is a tool to fake
a real API for HTTP Request testing during development
For security reasons, these values should not be used in
production
Now click on a PUT button on the app
This time 2 new requests appear on the All subtab
One OPTIONS request with no Payload and an empty
Response containing only the specification of the CORS policy
in the Response Headers
One PUT request containing the Payload with the new value
to update
CORS
OPTIONS Request:
Headers: 
Response: 

Note that the preflight


OPTIONS Request was sent
automatically by the browser,
not programmed manually
using Fetch
CORS
PUT Request:
Headers: 
Response: 
More on HTTP
HTTP cookie:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
HTTP Cross-Origin Resource Sharing (CORS):
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
HTTP authentication:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authenti
cation
HTTP authorization headers:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
/Authorization

HTTP caching:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
HTTP security policy headers:
Postman
A tool to test a REST API without a front-end app
Converse of json-server
Together they allow defining and testing a REST interface
through which the front-end and back-end shall interact,
independently of the implementation of both ends
Provides a GUI to specify HTTP requests to an URL and get
their responses
Download here: https://www.postman.com/downloads/
Postman

You might also like