Go тілі: нөлден өз блогыңызға дейін 19-сабақ (барлығы 50)
HTTP шындығында: әдіс, жол, тақырыптар және жауап коды
Go курсының он тоғызыншы сабағы және веб туралы модульдің басы. Сұраныс — оқуға болатын құрылым: әдіс, жол, тақырыптар, параметрлер. Жауап бір бағытта кетеді: тақырыптар, код, дене — дәл осы ретпен. 404 пен 405 неге екі бөлек жауап және superfluous WriteHeader деген хабар нені білдіреді.
Не үшін керек
Бірінші сабақта HTTP-ге сырттан, curl пәрменімен қарадыңыз. Үшіншісінде бір жолмен жауап беретін сервер жаздыңыз. Осы екеуінің арасында қалғанының бәрі қалды: сұранысты қалай оқу керек және жауапты барлық жағдайға бір жолмен емес, саналы түрде қалай құрастыру керек.
Нағыз блог осы жерден басталады. Сервер өзінен не сұрағанын ажыратпайынша, оның беттері де, тілдері де, қателері де бола алмайды.
Бірден тұтас
Жаңа қалта, go mod init sabaq17, main.go:
package main
import (
"fmt"
"log"
"net/http"
)
func handle(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.Header().Set("Allow", "GET")
w.WriteHeader(http.StatusMethodNotAllowed)
fmt.Fprintln(w, "тек GET")
return
}
if r.URL.Path != "/" {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintln(w, "мұндай бет жоқ:", r.URL.Path)
return
}
lang := r.URL.Query().Get("lang")
if lang == "" {
lang = "kz"
}
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
fmt.Fprintln(w, "әдіс:", r.Method)
fmt.Fprintln(w, "жол:", r.URL.Path)
fmt.Fprintln(w, "тіл:", lang)
fmt.Fprintln(w, "браузер:", r.Header.Get("User-Agent"))
}
func main() {
http.HandleFunc("/", handle)
log.Println("http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
go run . жіберіп, браузерден localhost:8080 ашыңыз. Содан кейін жауапты толық қараңыз — -i жалаушасы тақырыптарды көрсетеді:
curl -i "http://localhost:8080/?lang=ru"
Төменге қарамас бұрын — қандай жауап коды келетінін дауыстап айтыңыз. Содан кейін салыстырыңыз:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Sat, 05 Sep 2026 04:38:30 GMT
Content-Length: 60
әдіс: GET
жол: /
тіл: ru
браузер: curl/8.4
Енді жоқ бетті және бөтен әдіспен сұраңыз:
curl -i http://localhost:8080/kokek
curl -i -X POST http://localhost:8080/
HTTP/1.1 404 Not Found
...
мұндай бет жоқ: /kokek
HTTP/1.1 405 Method Not Allowed
Allow: GET
Талдау
Сұраныс — құрылым, оны бұрын да көргенсіз
r *http.Request — сілтегіштер сабағындағы сол жұлдызша. Сізге сұраныстың көшірмесі емес, мекенжайы беріледі: сұраныс үлкен, оны әр шақыруда көшіру ысырапшылық болар еді.
Ішінде — кез келген құрылымдағыдай нүкте арқылы жүгінетін өрістер:
r.Method // "GET"
r.URL.Path // "/kokek"
r.Header // барлық тақырыптар
Мұнда тілде жаңа ештеңе жоқ. Жаңасы — тек өріс аттары.
Елестетіп көріңіз. Толтырылған бланк. Жоғарыда не істеу сұралатыны (әдіс) және немен (жол) жазылған, төменде егжей-тегжейлі бағандар (тақырыптар), соңында — қосымша, егер бар болса (дене). Сіз бланкіні оқисыз, болжамайсыз.
Әдіс пен жол
Әдіс не істеу керегін айтады: GET — көрсет, POST — қабылда. Жол немен екенін айтады.
Оларды өзіңіз тексеруіңіз керек. / жолына тіркелген өңдеуші басқа ешкім алмаған барлық жолды қабылдайды — /kokek те соның ішінде. Сондықтан бағдарламада r.URL.Path != "/" деген нақты тексеру тұр, әйтпесе жоқ бет 200 кодымен және басты беттің мазмұнымен жауап берер еді.
Әдіс аттарын тұрақтылардан алған жөн — "GET" емес, http.MethodGet: жолдағы қатені компилятор ұстамайды, ал тұрақты атындағыны ұстайды.
Тақырыптар: оқу және қою
r.Header.Get("User-Agent") // оқу
w.Header().Set("Content-Type", "text/plain") // қою
Оқу — сұраныстан, жазу — жауапқа, оларды шатастыруға болмайды: сұраныста Header — өріс, жауапта Header() — әдіс.
Content-Type қоймасаңыз, Go оны дененің алғашқы байттарынан болжайды. Біздің 404-те ешнәрсе қоймадық — сонда да жауапта Content-Type: text/plain; charset=utf-8 пайда болды. Ыңғайлы, бірақ болжауға сүйенбеген жөн: HTML-ді ол таниды, ал сіздің өз пішіміңізді — жоқ.
Күй коды және рет
Сабақтың басты ережесі осы, әрі оны қолмен тексеріп көруге тұрарлық.
w.Header().Set("Content-Type", "application/json") // 1. тақырыптар
w.WriteHeader(http.StatusNotFound) // 2. күй коды
fmt.Fprintln(w, "{}") // 3. дене
Тек осы ретпен. Жауап сіз жазған сайын желіге кетіп жатады, ал жіберілгенді кері қайтару мүмкін емес.
Алғашқы екі жолдың орнын ауыстырыңыз — тақырып кетпейді: жауапта сіздікі емес, Go болжаған түр болады. Денені WriteHeader-ден бұрын жазыңыз — код мәңгі 200 болып қалады, ал сервер журналына мынау түседі:
http: superfluous response.WriteHeader call from main.main.func3 (main.go:22)
Елестетіп көріңіз. Пошта жәшігіндегі конверт. Конверт қолыңызда тұрғанда — үстіне қалағаныңызды жазыңыз. Жәшікке салдыңыз — жазуға кеш, кері алу да мүмкін емес.
Бөлек ескертемін: мұны httptest.NewRecorder арқылы тестпен тексерсеңіз, кеш қойылған тақырып онда көрінеді. Жазып алушы тақырыптарды кәдімгі картада сақтап, соңында береді, ал нағыз байланыс олай істемейді. Мұны тірі серверде тексеру керек.
Дене: w — бұл интерфейс
fmt.Fprintln(w, …) жұмыс істейді, себебі w байт қабылдай алады. Бұл io.Writer — келісімдер сабағындағы интерфейс, әрі сол функция файлға да, буферге де, желіге де айырмасын білмей жаза береді.
Тіл модулінде қолданған тәсіліміз де осыдан: логиканы io.Writer-ге жазатындай етіп жазады — сонда оны ештеңе іске қоспай тестпен тексеруге болады.
Сұраныс параметрлері
lang := r.URL.Query().Get("lang")
? белгісінен кейінгінің бәрі — параметрлер. Query() оларды картаға жинайды, Get атымен алады және параметр болмаса бос жол қайтарады. Ешқандай қате де, panic де жоқ — сондықтан әдепкі мәнді өзіңіз қоясыз.
Бұл сайтта мақаланың тілі дәл солай таңдалады: ?lang=kz.
404 пен 405 — бөлек жауаптар
Оларды шатастырады, ал айырмасы қарапайым. 404 — ондай бет мүлде жоқ. 405 — бет бар, бірақ онымен олай болмайды: тек GET қабылдайтын жерге POST жібердіңіз.
Ал 405-тің міндеті бар: не істеуге болатынын тізетін Allow тақырыбы. Оны жоғарыдағы жауаптан көрдіңіз — бұл әшекей емес, хаттаманың бөлігі.
Елестетіп көріңіз. Жабық есік пен басқа есік. «Ондай кабинет жоқ» пен «кабинет бар, бірақ қабылдау сәрсенбіде» — бөлек жауаптар, адам оларға қарап әртүрлі әрекет етеді.
Сабақ картасы
Өз сөзіңізбен айтыңыз
Қарамай, дауыстап немесе қағазға жазып жауап беріңіз. Жауаптары — сабақтың соңында.
/жолына тіркелген өңдеуші неге жолды өзі тексеруге міндетті?- Тақырыпты
w.WriteHeader-ден кейін қойсаңыз не болады? - 404-ті қашан, 405-ті қашан береді?
Тапсырма
Міндетті. Серверді үш жолға жауап беретін етіп толықтырыңыз: / — сәлемдесу, /about — өзіңіз туралы жол, қалғанының бәрі — түсінікті мәтіні бар 404. /about үшін тек GET рұқсат етіңіз, қалғанына Allow тақырыбымен 405 беріңіз. Барлық жағдайды curl -i арқылы тексеріп, кодтардың дәл ойлағаныңыздай екеніне көз жеткізіңіз.
Қалауыңызша.
?lang=қосыңыз:kz,ruжәнеenүшін өз тілінде жауап беріңіз, белгісіз мәнге — түсіндірмесі бар 400.- Өз
X-Powered-Byтақырыбыңызды қойып, оныcurl -iжауабынан табыңыз. - Денені
WriteHeader-ден бұрын жазып, сервер журналындағы жолды өз көзіңізбен көріңіз.
Блогта қайда тұрады
Бұл сабақ — модульдің іргетасы. Келесісінде жолдар өңдеушілерге бөлініп кетеді де, r.URL.Path-ты қолмен тексерудің қажеті болмайды. Одан кейін үлгілер пайда болады, жауаптың денесіне жол емес, HTML кетеді. Бірақ рет — тақырыптар, код, дене — курстың соңына дейін сол күйінде қалады.
Жауаптар
Жауаптарды көрсету
- Себебі стандартты бағыттауышта
/дегені «басқа ешкім алмағанның бәрі» деген сөз. Тексерусіз кез келген жоқ бет 200 кодын және басты беттің мазмұнын алар еді, ал іздеу жүйесі сайтта бірдей мыңдаған бет бар деп ойлар еді. - Ештеңе болмайды — бәле де сонда. Тақырыптар кодпен бірге кетіп қойған, кеш қойылған
Setтек жадыдағы картаны өзгертеді. Жауапта Go өзі болжағаны болады. - 404 — ондай мекенжай мүлде жоқ болғанда. 405 — мекенжай бар, бірақ ол үшін әдіс рұқсат етілмегенде; 405-пен бірге рұқсат етілген әдістер тізімі бар
Allowтақырыбын міндетті түрде береді.
Пікірлер (0)
Пікір қалдыру үшін кіріңіз →
Әзірге пікір жоқ. Бірінші болыңыз.