Фиристодани маълумот
Чаро маълумот мефиристем
Хондани API танҳо нисфи кор аст. Bot дархост месозад, сомона фикру мулоҳиза қабул мекунад, барнома суроғаи расониданро иваз мекунад. Барои ин муштарӣ маълумотро дар бадани дархост мефиристад ва методи HTTP-ро интихоб мекунад. Ба сервер ҳам муҳтаво ва ҳам формат муҳим аст: як луғати Python-ро бо чанд роҳи номувофиқ фиристодан мумкин аст.
Дар REST API суроға одатан манбаъ ё маҷмӯаро ифода мекунад. Метод амалро мегӯяд: GET мехонад, POST одатан месозад ё коркардро оғоз мекунад, PATCH қисмеро тағйир медиҳад, PUT намоиши пурраи манбаъро иваз мекунад, DELETE нест мекунад. Ин қоидаҳои умумӣ ҳастанд; API-и мушаххас шартномаи дақиқро муайян мекунад.
Муҳите, ки маълумоти фиристодашударо нишон медиҳад
Барои дидани дархостҳои воқеӣ бе сомонаи беруна сервери маҳаллии echo месозем. Он бадани POST-ро хонда, формат ва муҳтавояшро бармегардонад. Блокҳоро бо тартиб дар як раванди Python иҷро кунед. Сервер коди ёрирасон аст: диққати асосӣ ба фарохониҳои requests баъди он равона шавад.
import json
import os
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import requests
os.environ["NO_PROXY"] = "127.0.0.1,localhost"
class Handler(BaseHTTPRequestHandler):
def log_message(self, *args):
pass
def do_POST(self):
body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
data = json.dumps({"type": self.headers.get("Content-Type"),
"body": body.decode("utf-8")}).encode("utf-8")
self.send_response(201)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
base = f"http://127.0.0.1:{server.server_port}"
print(Handler.do_POST.__name__)
Барориш:
do_POST
Content-Length дарозии баданро бо байт мегӯяд. Коркардкунанда маҳз ҳамон миқдор байтро мехонад, на то баста шудани пайваст. Рамзи 201 махсус интихоб шудааст: сохтани муваффақ аксар вақт ҳамин рамзро дорад, на 200. Ин муҳит маълумотро нишон медиҳад, вале чизе нигоҳ намедорад.
JSON: луғат ба бадан табдил меёбад
Сериализатсия табдили объектҳо ба формати интиқол аст. Аргументи json= луғатро ба JSON табдил дода, Content-Type: application/json илова мекунад. Нохунакҳо дуруст escape мешаванд, False ба false, None ба null табдил меёбад. Таҳлили баръакси JSON дар сервер сохторро барқарор мекунад.
r = requests.post(base + "/echo", json={"label": 'A "B"', "visible": False},
timeout=5)
print(r.status_code, r.ok)
print(r.json()["type"])
print(json.loads(r.json()["body"]))
Барориш:
201 True
application/json
{'label': 'A "B"', 'visible': False}
Нохунакҳои дохили label дархостро вайрон накарданд: сериализатор онҳоро дуруст коркард кард. Echo-и мо баданро ҳамчун сатр медиҳад, бинобар ин r.json() ҷавоби берунӣ ва json.loads(...) сатри дохилии JSON-и фиристодашударо таҳлил мекунад. API-и одӣ одатан таҳлили дуюмро намехоҳад: сохтори ҷавобашро бинед.
json= тарзи рамзгузориро муайян мекунад, вале қабули майдонҳоро кафолат намедиҳад. Сервер метавонад майдони ҳатмӣ, маҳдудияти дарозӣ ё манъи калидҳои номаълум дошта бошад. Санҷиши ин қоидаҳо валидация ном дорад; хатояш аксар вақт бо рамзи 400 ё 422 нишон дода мешавад.
Форма: бастабандии дигари ҳамон қиматҳо
Формаи HTML одатан ҷуфтҳои ном=қимат-ро бо формати application/x-www-form-urlencoded мефиристад. Барои луғати майдонҳо data= истифода баред. Қиматҳо ба матн табдил ва рамзгузорӣ мешаванд; амперсанди аслӣ дар дохили ном набояд ҷудокунандаи майдонҳо шавад.
r = requests.post(base + "/echo", data={"name": "Mira & Co", "rating": 4},
timeout=5)
print(r.json()["type"])
print(r.json()["body"])
Барориш:
application/x-www-form-urlencoded
name=Mira+%26+Co&rating=4
Сервер номи Mira & Co-ро мебинад, на ду майдони ҷудоро. data= бо луғат ва data= бо сатр фарқ мекунанд: китобхона сатри тайёрро худкор ба формаи дуруст намесозад. Онро бо & дастӣ ҷамъ накунед.
Accept ба ҷавоби дилхоҳ, Content-Type ба формати бадани фиристодашаванда дахл дорад. Барои json= ва луғат дар data= requests сарлавҳаи мувофиқи Content-Type мегузорад. Танҳо сарлавҳаи application/json формаи луғатро ба JSON табдил намедиҳад. json= ва data=-ро ҳамзамон надиҳед, то гӯё сервер якеашро интихоб кунад.
Параметрҳои URL ва бадан мустақиланд
params=-ро бо POST низ истифода бурдан мумкин аст: онҳо ҳамоно ба URL мераванд. Бадан алоҳида фиристода мешавад. Дархости омодашуда инро бе фиристодан нишон медиҳад.
req = requests.Request("POST", base + "/echo", params={"page": 2},
json={"color": "blue"}).prepare()
print(req.url.rsplit("/", 1)[1])
print(req.body.decode("utf-8"))
Барориш:
echo?page=2
{"color": "blue"}
Агар сервер майдонро дар бадан интизор бошад, ба params кӯчондани он ҷойгузин нест. Ин ба баста дар почта монанд аст: қайд дар лифофа ва ҳуҷҷати дохили он метавонанд маълумоти гуногун дошта бошанд.
PATCH, PUT ва DELETE
Барои тағйири қисмӣ одатан майдонҳои тағйирёфта кифояанд. Барои PUT API одатан намоиши пурраро талаб мекунад: майдонҳои партофташуда метавонанд гум шаванд ё сабаби радкунӣ гарданд. DELETE аксар вақт бадани JSON намехоҳад. Дар ин ҷо танҳо се дархост ба профилро омода мекунем, бе тағйири маълумоти воқеӣ.
for method, data in [("PATCH", {"color": "blue"}),
("PUT", {"name": "Mira", "color": "blue"}),
("DELETE", None)]:
req = requests.Request(method, base + "/profiles/7", json=data).prepare()
print(req.method, req.body.decode("utf-8") if req.body else None)
Барориш:
PATCH {"color": "blue"}
PUT {"name": "Mira", "color": "blue"}
DELETE None
Методҳои requests ҳаммонанд интихоб мешаванд: requests.patch, requests.put, requests.delete. Несткунии муваффақ метавонад 204 бе бадан диҳад; дар он json()-ро фаро нахонед. Рамзи 202 метавонад маънои қабули амал ва ҳанӯз идома доштани иҷрояшро диҳад. Натиҷаи интизориро аз ҳуҷҷатҳои API хонед.
Ҳангоми ҳамоҳангсозӣ аввал маълумотро муқоиса карда, баъд тағйиротро нақша мегиранд. Дархост ба сабти аллакай мувофиқ метавонад беҳуда огоҳинома фиристад, вақти тағйирро нав кунад ё маҳдудияти дархостҳоро сарф намояд. Мавҷуд будани PATCH маънои истифодаи он барои ҳар сабтро надорад.
Баъди форма: равонасозӣ
Сомона метавонад POST-ро қабул карда, 303 бо сарлавҳаи Location диҳад. Ин маъно дорад: натиҷаро аз суроғаи дигар бинед. requests одатан ба чунин равонасозӣ бо GET мегузарад. Аз ин рӯ r.status_code-и ниҳоӣ аксар вақт 200 аст, вале 303-и миёна дар r.history мемонад.
Мисоли хурди нав танҳо объекти ҷавоб месозад ва шинохтани равонасозиро нишон медиҳад; дар шабака гузарише нест.
from urllib.parse import urljoin
response = requests.Response()
response.status_code = 303
response.headers["Location"] = "/receipt/7"
response.url = "https://example.test/form"
print(response.is_redirect)
print(urljoin(response.url, response.headers["Location"]))
Барориш:
True
https://example.test/receipt/7
allow_redirects=False дар POST имкон медиҳад, ки ҷавоби миёна омӯзем. Он гоҳ r.text метавонад холӣ бошад — ин ҳанӯз саҳифаи натиҷа нест. Қоидаи 303-ро ба ҳамаи равонасозиҳо татбиқ накунед: 307 ва 308 метод ва баданро нигоҳ медоранд.
Дар дохил чӣ рӯй медиҳад
requests баданро бо тарзи интихобшуда рамзгузорӣ мекунад, сарлавҳаҳоро гузошта, метод, роҳ ва баданро мефиристад. Сервер коркардкунандаро интихоб мекунад, форматро месанҷад, маълумотро таҳлил ва майдонҳоро тасдиқ карда, амалро иҷро мекунад. Танҳо баъд ҷавоб меояд. Рамзи 415 одатан формати дастгиринашавандаи бадан аст, на мушкили шабака. 422 аксар вақт маъно дорад, ки формат фаҳмо, вале қиматҳо номувофиқанд.
Пас аз мисолҳо серверро мебандем; -1 маънои socket-и бастаро дорад.
server.shutdown()
server.server_close()
print(server.fileno())
Барориш:
-1
Хатоҳои маъмул ва ислоҳи онҳо
data=payloadбарои API-и интизори JSON. Форма меравад ва шояд 415 мегиред.json=payloadдиҳед.data='{"name": "' + name + '"}'. Нохунак ё backslash дарnameJSON-ро мешиканад. Луғатро боjson=диҳед.- Танҳо
status_code == 200муваффақ дониста мешавад. Ҷавоби 201 хато рад мешавад. Рамзро аз рӯйи қоидаи API санҷед. requests.put(..., json={"color": "blue"})барои тағйири қисмӣ. Майдонҳои ҳатмӣ метавонанд гум шаванд. Барои тағйири қисмӣ PATCH-и пешбиникардаи API-ро истифода баред.json()дар ҷавоби 204 ё 303-и холӣ. Таҳлил хато медиҳад. Аввал рамз, гузаришҳо ва мавҷудияти баданро ба назар гиред.
Ёддошт
| Вазифа | Восита |
|---|---|
| Фиристодани объекти JSON | requests.post(url, json=payload, timeout=5) |
| Фиристодани майдонҳои форма | requests.post(url, data=fields, timeout=5) |
| Иловаи параметр ба URL | params=..., мустақил аз бадан |
| Тағйири қисмӣ / иваз / несткунӣ | patch / put / delete |
| Дидани равонасозиҳо | r.history, r.url |
| Истодан пеш аз гузариш | allow_redirects=False |
Дархости дуруст метод, суроға, формат ва майдонҳои дурустро якҷо мекунад. Ислоҳи як сарлавҳа кофӣ нест, агар худи бадан дар формати дигар монда бошад.