[go: up one dir, main page]

0% found this document useful (0 votes)
25 views38 pages

Dev Web

quazar

Uploaded by

fotsoarole
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views38 pages

Dev Web

quazar

Uploaded by

fotsoarole
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
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