Laborator 11 - Servicii web

Prezentare teoretică

Multe din platformele software dezvoltate în zilele noastre se bazează pe date primite de la un server web.

Server web

Un server web este o un program care rulează pe una sau mai multe mașini ce pot fi accesate prin intermediul Internetului. Pe de altă parte, mai mulți clienți pot face cereri către un server, care va răspunde cu informațiile cerute.

Pentru a putea realiza comunicarea între client și server, trebuie ca datele schimbate să urmeze niște reguli clare, numite protocol. În cazul serverelor web, protocolul folosit este HTTP.

Protocolul HTTP

HTTP (Hypertext Transfer Protocol) este un protocol utilizat la scară globală, fiind protocolul din spatele World Wide Web, sau ceea ce știm pur și simplu drept „web”. Majoritatea resurselor web partajate pe Internet sunt transferate prin HTTP.

Când vorbim despre aplicații web, sintagmele „server web” și „client web” sunt folosite frecvent. Prin urmare, putem afirma că HTTP este potrivit pentru un tip de comunicare client-server. În această arhitectură, avem serverul pe de o parte, în așteptarea cererilor la care să răspundă, iar clientul, pe de altă parte, solicită serverului resurse (sau date). Rezultatul este că mesajele transmise sunt perechi solicitare-răspuns (request-response).

Pachetele HTTP

Fiecare pachet HTTP poate fi împărțit în trei componente principale: linia de început, antetul și corpul mesajului. Linia de început conține informații despre mesaj, antetul pachetului conține meta-date, informații despre datele reale, în timp ce corpul conține informațiile efective care trebuie transmise. În timp ce structura generală este aceeași atât pentru mesajele de solicitare (request), cât și pentru răspunsuri(response), cele două diferă ușor atunci când sunt analizate în detaliu.

HTTP Request

Mesajele de tip request sunt trimise de la client către server pentru a cere informații (solicitați resurse serverului). Formatul unui mesaj de solicitare este următorul: {METHOD} {URL} {VERSION} {HEADERS} {BODY}.

  • Metoda - tipul de acțiune solicitată de la server (de exemplu, returnarea datelor, actualizarea datelor, ștergerea datelor etc.);
  • URL - calea către resursa accesată;
  • Versiune - versiunea HTTP utilizată (de ex. HTTP/1.1);
  • Anteturi - informații despre cerere; fiecare antet are formatul tip: valoarea și un mesaj poate avea mai multe anteturi, separate de CRLF (sfârșitul liniei) (de exemplu, conținut tip: application/json);
  • Corp - datele care trebuie transmise; aceasta este opțională, există mesaje care nu conțin corp.
Exemplu de pachet HTTP request
POST / HTTP/1.1
Ocp-Apim-Subscription-Key: 414574517b91467ea8e565ea19720650
Content-Type: application/json
cache-control: no-cache
Postman-Token: 4fb8e75e-ba74-4cac-b9ec-8ee1a81f1e94
User-Agent: PostmanRuntime/7.1.1
Accept: */*
Host: localhost:8000
accept-encoding: gzip, deflate
content-length: 37
Connection: keep-alive
 
{"name": "Harry Potter",
 "age": 10
}

HTTP Response

Mesajul de răspuns, trimis de la server către client, are următorul format generic: {VERSION} {STATUS} {REASON} {HEADERS} {BODY}.

  • Versiune - versiunea HTTP utilizată (de ex. HTTP/1.1);
  • Status - un număr care reprezintă ceea ce s-a întâmplat cu solicitarea (de exemplu, 200 pentru succes);
  • Motiv - o scurtă explicație a codului de stare (de ex. 200 OK, 404 Not Found);
  • Anteturi - informații despre cerere; fiecare antet are formatul tip: valoarea și un mesaj poate avea mai multe anteturi, separate de CRLF (sfârșitul liniei) (de exemplu, conținut tip: application/json);
  • Corp - datele care trebuie transmise; aceasta este opțională, există mesaje care nu conțin corp.
Exemplu de pachet HTTP response
HTTP/1.1 200 OK
status: 200
content-type: text/html
connection: close
 
<html><button>response</button></html>

URL

Atunci când lucrăm cu protocolul HTTP, care a fost special conceput pentru web, putem să considerăm că prin fiecare cerere pe care o facem serverului, în principiu, accesăm o resursă pe serverul respectiv, fie că este vorba de fișiere reale sau numai de date. Pentru fiecare resursă la care putem avea acces, există o modalitate de a ajunge la ea. Localizatorul de resurse uniform (URL) este un șir care indică o resursă specifică de pe web (de exemplu, http://www.wyliodrin.com/projects/app;user=lcss123?id=1234abcd).

Schema generală a unei adrese URL este următoarea: protocol://host:port/path;params?query#fragment.

Nu toate componentele URL sunt necesare, în majoritatea cazurilor vom folosi doar protocol, host și path.

Metode HTTP

După cum am stabilit deja, HTTP funcționează cu mesaje de tip request-reponse. Aceasta înseamnă că clientul trebuie să trimită o solicitare pentru a obține o resursă, iar acest lucru se face prin URL. Cu toate acestea, putem face tipuri diferite de cereri. Acesta este motivul pentru care, o solicitare este definită printr-o metodă împreună cu adresa URL, astfel încât să putem avea diferite solicitări în funcție de scopul lor (regăsirea datelor, modificarea datelor, ștergerea datelor etc.). Unele dintre cele mai utilizate metode HTTP disponibile sunt GET și POST.

Este important să înțelegem că metodele sunt convenții simple și utilizarea acestora depinde de modul în care este implementat serverul. Pentru fiecare cerere, indiferent de tipul metodei, serverul trebuie să emită un răspuns. Prin urmare, fiecare server poate implementa metodele diferit.

Antetul mesajului HTTP

După cum am menționat anterior, una dintre principalele părți ale unui mesaj HTTP este antetul. Aceasta conține informații importante despre cerere sau răspuns.

Unele informații sunt generice și pot fi găsite atât în mesajele de solicitare cât și în răspunsuri, în timp ce alte proprietăți sunt specifice uneia dintre ele. De exemplu, puteți găsi proprietatea Date în ambele mesaje și stochează data și ora la care a fost generat mesajul. Pe de altă parte, avem proprietatea Accept, care este utilizată într-o solicitare pentru a specifica serverului cu ce tip de fișiere media ar trebui să răspundă.

Codurile de stare

Codul de stare al unui răspuns informează clientul despre rezultatul cererii sale. Codurile de stare sunt împărțite în cinci categorii și, pe baza acestora, putem deduce rezultatul cererii trimise. Cele mai importante coduri sunt:

  • 200 - 299 - Coduri de succes - cererile au reușit;
  • 400 - 499 - Coduri de eroare ale clientului - solicitarea nu poate fi procesată de server, nu este în conformitate cu ce poate prelucra serverul;
  • 500 - 599 - Coduri de eroare server - solicitarea nu poate fi procesată deoarece serverul nu funcționează corect.

Corpul mesajului HTTP

Corpul unui mesaj HTTP reprezintă datele brute care trebuie transmise. Deoarece nu toate cererile sau răspunsurile necesită transmiterea datelor, corpul este opțional în cadrul unui mesaj.

Datele pot fi structurate sub diferite formate (de exemplu, structura JSON, structura XML, text). Acesta este motivul pentru care la trimiterea datelor adăugăm la mesaj antetul de tip Conținut, astfel încât să specificăm modul în care sunt structurate datele.

În prezent, majoritatea serviciilor web HTTP funcționează cu structuri JSON.

Mai multe detalii despre mesajele HTTP sunt disponibile la următorul link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages.

JSON

Cel mai folosit mod de reprezentare a datelor este JSON.

JavaScript Object Notation (JSON) este o sintaxă folosită pentru stocarea și transmisia de date. Acest format a fost dezvoltat pentru a fi ușor de parsat și generat, fiind în același timp ușor de înțeles de către oameni.

Formatul JSON se bazează pe două structuri:

  • O coleție de perechi cheie-valoare, similar cu un dicționar;
  • O listă de valori.
my_json = {"first_name": "Harry",
"last_name": "Potter",
"age": 10,
"hobbies" : ["reading", "magic"]}

Pentru a extra o valoare dintr-o variabilă de tip JSON, se specifică cheia acesteia: my_json[“age”].

În Python se pot genera și manipula elemente JSON folosind modulul json. Acesta expune două funcții importante:dumps și loads.

Funcția dumps() transformă un obiect Python într-un string JSON.

import json
 
# a Python object (dict):
x = {
  "name": "John",
  "age": 30,
  "city": "New York"
}
 
# convert into JSON:
y = json.dumps(x)
 
# the result is a JSON string:
print(y) 

Funcția loads() transformă un string de forma JSON într-un obiect Python.

import json
 
# some JSON:
x =  '{ "name":"John", "age":30, "city":"New York"}'
 
# parse x:
y = json.loads(x)
 
# the result is a Python dictionary:
print(y["age"]) 

Exerciţii de laborator

Scopul acestui laborator este de a realiza un server web minimal pornind de la scheletul de cod de mai jos.

import socket
 
buffersize = 3072
 
s = socket.socket (family=socket.AF_INET, type=socket.SOCK_STREAM)
s.bind (("0.0.0.0", 8000))
s.listen (0)
 
while True:
    conn, addr = s.accept ()
 
    data = conn.recv(buffersize)
 
    msg = data.decode("utf-8") 
    print ('received')
    print (msg)
 
    conn.send (('HTTP/1.0 200 OK\r\nContent-type:text/html\r\nConnection: close\r\n\r\nbody').encode('ascii'))
 
    conn.close()

În acest exemplu am creat un server TCP care primeste date de la un client, le afișează, după care răspunde cu mesajul:

HTTP/1.0 200 OK - protocolul HTTP versiunea 1.0, cod de eroare 200 OK
Connection: close - inchidem conexiunea dupa trimiterea raspunsului catre client
 
response

In acest mesaj, primele două linii fac parte din antet, iar ultima linie este corpul mesajului.

Mesajele HTTP trimise de la server sau de la client vor avea următorul format:

linie antet
linie antet
...
linie antet
 
mesaj

Exercițiul 1 - GET message

  • Rulați exemplul de mai sus și accesați adresa localhost:8000 din browser. Observați răspunsul primit în browser și inspectați mesajul primit de server.
  • Accesați adresa localhost:8000/hello/world.

Exercițiul 2 - HTML response

Modificați serverul anterior astfel încât acesta să răspundă cu o pagină html. Mesajul trimis de server trebuie să arate astfel:

HTTP/1.0 200 OK
Content-type: text/html
Connection: close
 
<html>...</html>

Exercițiul 3 - POST message

Descărcați aplicația postman și folosiți-o pentru a trimite un mesaj de tip POST serverului (la secțiunea Body selectați raw, text). Timiteți un mesaj scurt în corpul mesajului folosind Postman și inspectați tot mesajul primit de server.

Exercițiul 4 - POST response

Modificați serverul astfel încât acesta să citească corpul mesajului primit, iar în funcție de acesta să trimită un alt răspuns, astfel:

  • la mesajul age să răspundă cu un număr;
  • la mesajul name să răspundă cu un număr;
  • la mesajul country să răspundă cu o țară.

Exercițiul 5 - JSON response

Adăugați la server opțiunea ca la o cerere de tipul GET, pe ruta localhost:8000/person acesta să răspundă cu JSON de forma:

{
"name" : "Harry Potter",
"age" : 10,
"country" : "UK"
}

Exercițiul 6 - Form server

Creați un server web care va stoca datele unor persoane, primite de la clienți și care va răspunde cu aceste informații. Comportamentul serverului este următorul:

  • la un request POST la adresa localhost:8000/insert primește în body un JSON precum cel de mai jos și întoarce codul 200 în cazul în care datele au fost salvate sau 500, daca ceva nu a funcționat.
{
"name" : "Harry Potter",
"age" : 10,
"country" : "UK"
}
  • la un request GET la adresa localhost:8000întoarce un JSON cu toate datele stocate, de forma celui de mai jos:
[{
"age" : int_value1,
"name" : "nume_persoana1",
"country" : "tara persoana1"
},
{
"age" : int_value2,
"name" : "nume_persoana2",
"country" : "tara persoana2"
},....]

Exercitiu 7 - Form client

Creați un client Python care să trimită mesaje serverului în locul lui Postman. În acest caz puteți simplifica mesajul astfel încât antetul să conțină doar informațiile necesare în prelucrearea pachetului.

Bonus - Form client

Modificați programul creat anterior astfel încât acesta să răspundă cu o pagină web ce conține 3 input-uri și care trimite aceste date prin apăsarea unui buton, după care acesta va afișa informațiile primite.

sde/laboratoare/11_ro_python.txt · Last modified: 2020/05/19 11:26 by alexandru.radovici
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0