init here
This commit is contained in:
57
исх/сеть/тцп/сервер.tri
Normal file
57
исх/сеть/тцп/сервер.tri
Normal file
@@ -0,0 +1,57 @@
|
||||
модуль тцп
|
||||
|
||||
// c:include "suckit.h"
|
||||
|
||||
фн create_socket_fd(port: Цел64): Цел64 @внеш
|
||||
фн accept_socket(fd: Цел64): Цел64 @внеш
|
||||
фн read_to_string(fd: Цел64, bytes: Цел64): Строка @внеш
|
||||
фн close_socket(socket: Цел64) @внеш
|
||||
фн write_string(socket: Цел64, data: Строка) @внеш
|
||||
фн connect_socket(host: Строка, port: Цел64): Цел64 @внеш
|
||||
|
||||
тип ТцпСервер* = класс {
|
||||
фд: Цел64 = 0
|
||||
}
|
||||
|
||||
тип ТцпСоединение* = класс {
|
||||
фд: Цел64 = 0
|
||||
}
|
||||
|
||||
фн создать сервер*(порт: Цел64): ТцпСервер {
|
||||
пусть фд = create_socket_fd(порт)
|
||||
|
||||
вернуть ТцпСервер{
|
||||
фд: фд
|
||||
}
|
||||
}
|
||||
|
||||
фн (с: ТцпСервер) принять чертово соединение*(): ТцпСоединение {
|
||||
пусть фд = accept_socket(с.фд)
|
||||
|
||||
вернуть ТцпСоединение{
|
||||
фд: фд
|
||||
}
|
||||
}
|
||||
|
||||
фн (с: ТцпСоединение) прочитать*(сколько: Цел64): Строка {
|
||||
вернуть read_to_string(с.фд, сколько)
|
||||
}
|
||||
|
||||
фн (с: ТцпСоединение) записать*(данные: Строка) {
|
||||
write_string(с.фд, данные)
|
||||
}
|
||||
|
||||
фн (с: ТцпСоединение) закрыть*() {
|
||||
close_socket(с.фд)
|
||||
}
|
||||
|
||||
фн (с: ТцпСервер) закрыть*() {
|
||||
close_socket(с.фд)
|
||||
}
|
||||
|
||||
фн подключиться*(хост: Строка, порт: Цел64): ТцпСоединение {
|
||||
пусть фд = connect_socket(хост, порт)
|
||||
вернуть ТцпСоединение{ фд: фд }
|
||||
}
|
||||
|
||||
|
||||
140
исх/сеть/хттп/клиент.tri
Normal file
140
исх/сеть/хттп/клиент.tri
Normal file
@@ -0,0 +1,140 @@
|
||||
модуль хттп
|
||||
|
||||
импорт "стд::вывод"
|
||||
импорт "исх/строка"
|
||||
импорт "исх/сеть/тцп"
|
||||
|
||||
фн сериализовать хттп-запрос(хост: Строка, обращение: ХттпОбращение): Строка {
|
||||
пусть метод := обращение.метод
|
||||
если метод = "" {
|
||||
метод := "GET"
|
||||
}
|
||||
|
||||
пусть путь := обращение.путь
|
||||
если путь = "" {
|
||||
путь := "/"
|
||||
}
|
||||
|
||||
пусть первая := строка.ф("$стр $стр HTTP/1.1\r\n", метод, путь)
|
||||
пусть есть длина := ложь
|
||||
пусть выход := первая
|
||||
|
||||
цикл [номер]заглавие среди обращение.заглавия {
|
||||
если заглавие.имя = "Content-Length" { есть длина := истина }
|
||||
выход := строка.собрать(выход, строка.ф("$стр: $стр\r\n", заглавие.имя, заглавие.значение))
|
||||
}
|
||||
|
||||
выход := строка.собрать(выход, строка.ф("Host: $стр\r\n", хост))
|
||||
|
||||
если ~ есть длина {
|
||||
выход := строка.собрать(выход, строка.ф("Content-Length: $цел\r\n", длина(обращение.туловище(:Строка8))))
|
||||
}
|
||||
|
||||
выход := строка.собрать(выход, "\r\n")
|
||||
|
||||
если длина(обращение.туловище) > 0 { выход := строка.собрать(выход, обращение.туловище) }
|
||||
|
||||
вернуть выход
|
||||
}
|
||||
|
||||
фн послать далеко и надолго*(хост: Строка, порт: Цел64, обращение: ХттпОбращение): ХттпОтвет {
|
||||
пусть соединение = тцп.подключиться(хост, порт)
|
||||
пусть данные = сериализовать хттп-запрос(хост, обращение)
|
||||
|
||||
соединение.записать(данные)
|
||||
|
||||
вывод.ф("Ждем хттп ответ\n")
|
||||
пусть ответ = разобрать хттп ответ(соединение)
|
||||
соединение.закрыть()
|
||||
вывод.ф("Дождались\n")
|
||||
|
||||
вернуть ответ
|
||||
}
|
||||
|
||||
фн послать на три буквы*(хост: Строка, порт: Цел64, путь: Строка): ХттпОтвет {
|
||||
вернуть послать далеко и надолго(хост, порт, ХттпОбращение{ метод: "GET", путь: путь })
|
||||
}
|
||||
|
||||
тип Урл* = класс {
|
||||
хост*: Строка := ""
|
||||
порт*: Цел64 := 0
|
||||
путь*: Строка := ""
|
||||
}
|
||||
|
||||
фн парсить урл*(стр: Строка, оплошность := Строка): Урл {
|
||||
оплошность := ""
|
||||
|
||||
пусть с = строка.обрезать пробельные символы(стр)
|
||||
если с = "" {
|
||||
оплошность := "пустой урл"
|
||||
вернуть Урл{}
|
||||
}
|
||||
|
||||
пусть схема := "http"
|
||||
пусть ост := с
|
||||
если строка.разделить(с, "://", схема, ост) {
|
||||
схема := строка.обрезать пробельные символы(схема)
|
||||
} иначе {
|
||||
// без схемы считаем http
|
||||
схема := "http"
|
||||
ост := с
|
||||
}
|
||||
|
||||
// отделяем authority и путь
|
||||
пусть № слеша = строка.индекс(ост, 0, "/")
|
||||
пусть авторитет := ""
|
||||
пусть путь := ""
|
||||
если № слеша >= 0 {
|
||||
пусть ост8 = ост(:Строка8)
|
||||
авторитет := строка.извлечь(ост, 0, № слеша)
|
||||
путь := строка.извлечь(ост, № слеша, длина(ост8) - № слеша)
|
||||
} иначе {
|
||||
авторитет := ост
|
||||
путь := ""
|
||||
}
|
||||
|
||||
авторитет := строка.обрезать пробельные символы(авторитет)
|
||||
если авторитет = "" {
|
||||
оплошность := "пустой хост в урл"
|
||||
вернуть Урл{}
|
||||
}
|
||||
|
||||
// парсим хост и порт
|
||||
пусть хост := авторитет
|
||||
пусть порт: Цел64 := 0
|
||||
пусть № двоеточия = строка.индекс(авторитет, 0, ":")
|
||||
если № двоеточия >= 0 {
|
||||
пусть ав8 = авторитет(:Строка8)
|
||||
хост := строка.извлечь(авторитет, 0, № двоеточия)
|
||||
пусть порт строка := строка.извлечь(авторитет, № двоеточия + 1, длина(ав8) - (№ двоеточия + 1))
|
||||
порт строка := строка.обрезать пробельные символы(порт строка)
|
||||
|
||||
пусть порт значение := 0
|
||||
пусть № байта := 0
|
||||
если ~ строка.извлечь цел(порт строка, № байта, порт значение) {
|
||||
оплошность := "некорректный порт в урл"
|
||||
вернуть Урл{}
|
||||
}
|
||||
если порт значение <= 0 | порт значение > 65535 {
|
||||
оплошность := "порт вне диапазона в урл"
|
||||
вернуть Урл{}
|
||||
}
|
||||
порт := порт значение
|
||||
} иначе {
|
||||
если схема = "https" {
|
||||
порт := 443
|
||||
} иначе {
|
||||
порт := 80
|
||||
}
|
||||
}
|
||||
|
||||
хост := строка.обрезать пробельные символы(хост)
|
||||
если хост = "" {
|
||||
оплошность := "пустой хост в урл"
|
||||
вернуть Урл{}
|
||||
}
|
||||
|
||||
если путь = "" { путь := "/" }
|
||||
|
||||
вернуть Урл{ хост: хост, порт: порт, путь: путь }
|
||||
}
|
||||
120
исх/сеть/хттп/маршрутизатор/маршутизатор.tri
Normal file
120
исх/сеть/хттп/маршрутизатор/маршутизатор.tri
Normal file
@@ -0,0 +1,120 @@
|
||||
модуль маршрутизатор
|
||||
|
||||
импорт "стд::контейнеры/словарь/стр-стр"
|
||||
импорт "исх/строка"
|
||||
импорт "исх/сеть/хттп"
|
||||
импорт "исх/массивы"
|
||||
|
||||
тип Обращение* = класс (хттп.ХттпОбращение) {
|
||||
запрос-в-пути*: стр-стр.Словарь := стр-стр.Словарь{}
|
||||
}
|
||||
|
||||
тип ОбработчикМаршрута = фн (путь: Строка, параметры: массивы.Строки, обращение: Обращение): хттп.ХттпОтвет
|
||||
|
||||
тип Маршрут = класс {
|
||||
путь: Строка := "/"
|
||||
обработчик: ОбработчикМаршрута := позже
|
||||
методы: массивы.Строки := массивы.Строки[]
|
||||
}
|
||||
|
||||
фн (м: Маршрут) подходит по пути(обращение: хттп.ХттпОбращение, параметры := массивы.Строки): Лог {
|
||||
пусть части пути по запросу = строка.разобрать(обращение.путь, "?")
|
||||
пусть части пути обращения = строка.разобрать(части пути по запросу[0], "/")
|
||||
пусть части пути маршрута = строка.разобрать(м.путь, "/")
|
||||
|
||||
цикл [номер]часть пути маршрута среди части пути маршрута {
|
||||
если часть пути маршрута = "*" {
|
||||
пусть ай := номер
|
||||
|
||||
пока ай < длина(части пути обращения) {
|
||||
параметры.добавить(части пути обращения[ай])
|
||||
ай++
|
||||
}
|
||||
|
||||
вернуть истина
|
||||
}
|
||||
|
||||
если номер >= длина(части пути обращения) {
|
||||
вернуть ложь
|
||||
}
|
||||
|
||||
пусть часть пути обращения = части пути обращения[номер]
|
||||
|
||||
если часть пути маршрута = "$" {
|
||||
параметры.добавить(часть пути обращения)
|
||||
} иначе если часть пути маршрута # часть пути обращения {
|
||||
вернуть ложь
|
||||
}
|
||||
}
|
||||
|
||||
вернуть длина(части пути маршрута) = длина(части пути обращения)
|
||||
}
|
||||
|
||||
фн (м: Маршрут) подходит по методу(обращение: хттп.ХттпОбращение): Лог {
|
||||
цикл [номер]метод среди м.методы {
|
||||
если метод = обращение.метод {
|
||||
вернуть истина
|
||||
}
|
||||
}
|
||||
|
||||
вернуть ложь
|
||||
}
|
||||
|
||||
фн (м: Маршрут) подходит для*(обращение: хттп.ХттпОбращение, параметры := массивы.Строки): Лог {
|
||||
вернуть м.подходит по пути(обращение, параметры) & м.подходит по методу(обращение)
|
||||
}
|
||||
|
||||
тип Маршруты = []Маршрут
|
||||
|
||||
тип Маршрутизатор* = класс {
|
||||
маршруты: Маршруты := Маршруты[]
|
||||
обработчик_404: ОбработчикМаршрута := обработчик_404
|
||||
}
|
||||
|
||||
фн (м: Маршрутизатор) добавить маршрут*(путь: Строка, методы: массивы.Строки, обработчик: ОбработчикМаршрута) {
|
||||
м.маршруты.добавить(Маршрут{путь: путь, обработчик: обработчик, методы: методы})
|
||||
}
|
||||
|
||||
фн (м: Маршрутизатор) обработать обращение*(обращение: хттп.ХттпОбращение): хттп.ХттпОтвет {
|
||||
пусть обращение маршрутизатора = Обращение{
|
||||
метод: обращение.метод,
|
||||
путь: обращение.путь,
|
||||
версия: обращение.версия,
|
||||
заглавия: обращение.заглавия,
|
||||
туловище: обращение.туловище,
|
||||
запрос-в-пути: разобрать-запрос-в-пути(обращение.путь)
|
||||
}
|
||||
|
||||
цикл [номер]маршрут среди м.маршруты {
|
||||
пусть параметры := массивы.Строки[]
|
||||
|
||||
если маршрут.подходит для(обращение, параметры) {
|
||||
вернуть маршрут.обработчик(обращение.путь, параметры, обращение маршрутизатора)
|
||||
}
|
||||
}
|
||||
|
||||
вернуть м.обработчик_404(обращение.путь, массивы.Строки[], обращение маршрутизатора)
|
||||
}
|
||||
|
||||
фн разобрать-запрос-в-пути(путь: Строка): стр-стр.Словарь {
|
||||
пусть части = строка.разобрать(путь, "?")
|
||||
|
||||
если длина(части) < 2 {
|
||||
вернуть стр-стр.Словарь{}
|
||||
}
|
||||
|
||||
пусть параметры = строка.разобрать(части[1], "&")
|
||||
пусть словарь = стр-стр.Словарь{}
|
||||
|
||||
цикл [номер]параметр среди параметры {
|
||||
пусть пара = строка.разобрать(параметр, "=")
|
||||
|
||||
если длина(пара) = 2 {
|
||||
словарь.добавить(пара[0], пара[1])
|
||||
} иначе если длина(пара) = 1 {
|
||||
словарь.добавить(пара[0], "")
|
||||
}
|
||||
}
|
||||
|
||||
вернуть словарь
|
||||
}
|
||||
8
исх/сеть/хттп/маршрутизатор/обработчики.tri
Normal file
8
исх/сеть/хттп/маршрутизатор/обработчики.tri
Normal file
@@ -0,0 +1,8 @@
|
||||
модуль маршрутизатор
|
||||
|
||||
импорт "исх/массивы"
|
||||
импорт "исх/сеть/хттп"
|
||||
|
||||
фн обработчик_404*(путь: Строка, параметры: массивы.Строки, обращение: Обращение): хттп.ХттпОтвет {
|
||||
вернуть хттп.ответ_404()
|
||||
}
|
||||
118
исх/сеть/хттп/ответ.tri
Normal file
118
исх/сеть/хттп/ответ.tri
Normal file
@@ -0,0 +1,118 @@
|
||||
модуль хттп
|
||||
|
||||
фн ответ_201*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 201,
|
||||
состояние: "Created",
|
||||
туловище: "Тварь успешно создана.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_204*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 204,
|
||||
состояние: "No Content",
|
||||
туловище: "Пожалуйста, оставайтесь на месте. За вами уже выехали.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_400*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 400,
|
||||
состояние: "Bad Request",
|
||||
туловище: "Некорректный запрос. Пожалуйста, проверьте правильность запроса и повторите попытку.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_401*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 401,
|
||||
состояние: "Unauthorized",
|
||||
туловище: "Требуется аутентификация. Пожалуйста, предоставьте свои паспортные данные и повторите запрос.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_402*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 402,
|
||||
состояние: "Payment Required",
|
||||
туловище: "Доступ к запрашиваемому ресурсу требует оплаты. Пожалуйста, свяжитесь с администратором для получения дополнительной информации.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_403*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 403,
|
||||
состояние: "Forbidden",
|
||||
туловище: "Вы были репрессированы. Пожалуйста, перейдите по ссылке: http://сибирь.рф",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_422*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 422,
|
||||
состояние: "Unprocessable Entity",
|
||||
туловище: "Неперевариваемая тварь.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_404*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 404,
|
||||
состояние: "Not Found",
|
||||
туловище: "Запрашиваемый ресурс не найден на сервере.",
|
||||
}
|
||||
}
|
||||
|
||||
фн ответ_500*(): ХттпОтвет {
|
||||
вернуть ХттпОтвет{
|
||||
код: 500,
|
||||
состояние: "Internal Server Error",
|
||||
туловище: "Просим быть внимательными и бдительными. Оглядывайтесь вверх и по сторонам. Что-то произошло непонятное.",
|
||||
}
|
||||
}
|
||||
|
||||
фн создать ответ*(база: ХттпОтвет, расширение: ХттпОтвет): ХттпОтвет {
|
||||
пусть пустой ответ = ХттпОтвет{}
|
||||
пусть ответ = ХттпОтвет{}
|
||||
|
||||
если расширение.код # пустой ответ.код {
|
||||
ответ.код := расширение.код
|
||||
} иначе {
|
||||
ответ.код := база.код
|
||||
}
|
||||
|
||||
если расширение.состояние # пустой ответ.состояние {
|
||||
ответ.состояние := расширение.состояние
|
||||
} иначе {
|
||||
ответ.состояние := база.состояние
|
||||
}
|
||||
|
||||
цикл [номер]заглавие среди база.заглавия {
|
||||
ответ.заглавия.добавить(заглавие)
|
||||
}
|
||||
|
||||
цикл [номер]заглавие среди расширение.заглавия {
|
||||
пусть нашлось := ложь
|
||||
|
||||
цикл [уемер]существующее среди ответ.заглавия {
|
||||
если заглавие.имя = существующее.имя {
|
||||
существующее.значение := заглавие.значение
|
||||
нашлось := истина
|
||||
прервать
|
||||
}
|
||||
}
|
||||
|
||||
если ~нашлось {
|
||||
ответ.заглавия.добавить(заглавие)
|
||||
}
|
||||
}
|
||||
|
||||
если расширение.туловище # "" {
|
||||
ответ.туловище := расширение.туловище
|
||||
} иначе {
|
||||
ответ.туловище := база.туловище
|
||||
}
|
||||
|
||||
вернуть ответ
|
||||
}
|
||||
235
исх/сеть/хттп/парсер.tri
Normal file
235
исх/сеть/хттп/парсер.tri
Normal file
@@ -0,0 +1,235 @@
|
||||
модуль хттп
|
||||
|
||||
импорт "исх/строка"
|
||||
импорт "исх/вперед-назад"
|
||||
импорт "исх/сеть/тцп"
|
||||
|
||||
фн сериализовать хттп ответ*(р: ХттпОтвет): Строка {
|
||||
пусть ответ := строка.собрать(строка.ф("$стр $цел $стр\r\n", р.версия, р.код, р.состояние))
|
||||
|
||||
пусть есть размер контента := ложь
|
||||
|
||||
цикл [номер]заглавие среди р.заглавия {
|
||||
если заглавие.имя = "Content-Length" { есть размер контента := истина }
|
||||
ответ := строка.собрать(ответ, строка.ф("$стр: $стр\r\n", заглавие.имя, заглавие.значение))
|
||||
}
|
||||
|
||||
если ~ есть размер контента {
|
||||
ответ := строка.собрать(ответ, строка.ф("Content-Length: $цел\r\n", длина(р.туловище(:Строка8))))
|
||||
}
|
||||
|
||||
ответ := строка.собрать(ответ, "\r\n")
|
||||
|
||||
если длина(р.туловище) > 0 {
|
||||
ответ := строка.собрать(ответ, р.туловище)
|
||||
}
|
||||
|
||||
вернуть ответ
|
||||
}
|
||||
|
||||
фн отправить хттп ответ*(с: тцп.ТцпСоединение, р: ХттпОтвет) {
|
||||
пусть данные := сериализовать хттп ответ(р)
|
||||
с.записать(данные)
|
||||
}
|
||||
|
||||
фн разобрать хттп обращение*(с: вперед-назад.Крипипаста): ХттпОбращение {
|
||||
пусть сколько читаем = 1024
|
||||
пусть прочитано := 0
|
||||
пусть обращение = ХттпОбращение{}
|
||||
пусть данные := ""
|
||||
пусть первая линия := ""
|
||||
пусть добрались до тела := ложь
|
||||
пусть размер контента: Цел64 := -1
|
||||
|
||||
пока истина {
|
||||
пусть сколько прочитать: Цел64 := -1
|
||||
если размер контента > 0 & добрались до тела {
|
||||
сколько прочитать := размер контента - прочитано
|
||||
}
|
||||
|
||||
если сколько прочитать = 0 {
|
||||
вернуть обращение
|
||||
}
|
||||
|
||||
пусть новые данные = с.прочитать(сколько читаем)
|
||||
прочитано := прочитано + длина(новые данные)
|
||||
если длина(новые данные) = 0 {
|
||||
вернуть обращение
|
||||
}
|
||||
|
||||
данные := строка.собрать(данные, новые данные)
|
||||
|
||||
если ~ добрались до тела {
|
||||
пока длина(данные) > 0 {
|
||||
пусть конец строки = строка.индекс(данные, 0, "\n")
|
||||
|
||||
если конец строки = -1 {
|
||||
прервать
|
||||
}
|
||||
|
||||
пусть линия = строка.обрезать пробельные символы(строка.извлечь(данные, 0, конец строки))
|
||||
данные := строка.извлечь(данные, конец строки + 1, длина(данные(:Строка8)) - конец строки)
|
||||
|
||||
если линия = "" {
|
||||
если размер контента > 0 {
|
||||
пусть индекс переноса = строка.индекс(данные, 0, "\n")
|
||||
|
||||
добрались до тела := истина
|
||||
данные := строка.извлечь(данные, индекс переноса + 1, длина(данные(:Строка8)) - индекс переноса)
|
||||
прочитано := длина(данные(:Строка8))
|
||||
обращение.туловище := данные
|
||||
данные := ""
|
||||
|
||||
прервать
|
||||
} иначе {
|
||||
вернуть обращение
|
||||
}
|
||||
}
|
||||
|
||||
если первая линия = "" {
|
||||
первая линия := линия
|
||||
|
||||
пусть части = строка.разобрать(первая линия, " ")
|
||||
|
||||
если длина(части) >= 1 { обращение.метод := части[0] }
|
||||
если длина(части) >= 2 {
|
||||
цикл [номер]часть среди части {
|
||||
если номер > 0 & номер < длина(части) - 1 {
|
||||
если номер > 1 {
|
||||
обращение.путь := строка.собрать(обращение.путь, " ")
|
||||
}
|
||||
|
||||
обращение.путь := строка.собрать(обращение.путь, часть)
|
||||
}
|
||||
}
|
||||
}
|
||||
если длина(части) >= 3 { обращение.версия := части[длина(части) - 1] }
|
||||
} иначе {
|
||||
пусть заглавие = ХттпЗаглавие{}
|
||||
|
||||
строка.разделить(линия, ":", заглавие.имя, заглавие.значение)
|
||||
|
||||
заглавие.имя := строка.обрезать пробельные символы(заглавие.имя)
|
||||
заглавие.значение := строка.обрезать пробельные символы(заглавие.значение)
|
||||
|
||||
если размер контента < 0 & заглавие.имя = "Content-Length" {
|
||||
пусть новый размер контента := 0
|
||||
пусть номер байта := 0
|
||||
|
||||
если строка.извлечь цел(заглавие.значение, номер байта, новый размер контента) {
|
||||
размер контента := новый размер контента
|
||||
}
|
||||
}
|
||||
|
||||
обращение.заглавия.добавить(заглавие)
|
||||
}
|
||||
}
|
||||
} иначе {
|
||||
обращение.туловище := строка.соединить(обращение.туловище, данные)
|
||||
}
|
||||
}
|
||||
|
||||
вернуть обращение
|
||||
}
|
||||
|
||||
фн разобрать хттп ответ*(с: тцп.ТцпСоединение): ХттпОтвет {
|
||||
пусть сколько читаем = 1024
|
||||
пусть прочитано := 0
|
||||
пусть ответ = ХттпОтвет{}
|
||||
пусть данные := ""
|
||||
пусть первая линия := ""
|
||||
пусть добрались до тела := ложь
|
||||
пусть размер контента: Цел64 := -1
|
||||
|
||||
пока истина {
|
||||
пусть сколько прочитать: Цел64 := -1
|
||||
если размер контента > 0 & добрались до тела {
|
||||
сколько прочитать := размер контента - прочитано
|
||||
}
|
||||
|
||||
если сколько прочитать = 0 {
|
||||
вернуть ответ
|
||||
}
|
||||
|
||||
пусть новые данные = с.прочитать(сколько читаем)
|
||||
прочитано := прочитано + длина(новые данные)
|
||||
если длина(новые данные) = 0 {
|
||||
вернуть ответ
|
||||
}
|
||||
|
||||
данные := строка.собрать(данные, новые данные)
|
||||
|
||||
если ~ добрались до тела {
|
||||
пока длина(данные) > 0 {
|
||||
пусть конец строки = строка.индекс(данные, 0, "\n")
|
||||
|
||||
если конец строки = -1 {
|
||||
прервать
|
||||
}
|
||||
|
||||
пусть линия = строка.обрезать пробельные символы(строка.извлечь(данные, 0, конец строки))
|
||||
данные := строка.извлечь(данные, конец строки + 1, длина(данные(:Строка8)) - конец строки)
|
||||
|
||||
если линия = "" {
|
||||
если размер контента > 0 {
|
||||
добрались до тела := истина
|
||||
прочитано := длина(данные(:Строка8))
|
||||
ответ.туловище := данные
|
||||
данные := ""
|
||||
|
||||
прервать
|
||||
} иначе {
|
||||
вернуть ответ
|
||||
}
|
||||
}
|
||||
|
||||
если первая линия = "" {
|
||||
первая линия := линия
|
||||
|
||||
пусть части = строка.разобрать(первая линия, " ")
|
||||
|
||||
если длина(части) >= 1 { ответ.версия := части[0] }
|
||||
если длина(части) >= 2 {
|
||||
пусть новый код := 0
|
||||
пусть номер байта := 0
|
||||
если строка.извлечь цел(части[1], номер байта, новый код) {
|
||||
ответ.код := новый код
|
||||
}
|
||||
}
|
||||
если длина(части) >= 3 {
|
||||
цикл [номер]часть среди части {
|
||||
если номер >= 2 {
|
||||
если номер > 2 {
|
||||
ответ.состояние := строка.собрать(ответ.состояние, " ")
|
||||
}
|
||||
ответ.состояние := строка.собрать(ответ.состояние, часть)
|
||||
}
|
||||
}
|
||||
}
|
||||
} иначе {
|
||||
пусть заглавие = ХттпЗаглавие{}
|
||||
|
||||
строка.разделить(линия, ":", заглавие.имя, заглавие.значение)
|
||||
|
||||
заглавие.имя := строка.обрезать пробельные символы(заглавие.имя)
|
||||
заглавие.значение := строка.обрезать пробельные символы(заглавие.значение)
|
||||
|
||||
если размер контента < 0 & заглавие.имя = "Content-Length" {
|
||||
пусть новый размер контента := 0
|
||||
пусть номер байта := 0
|
||||
|
||||
если строка.извлечь цел(заглавие.значение, номер байта, новый размер контента) {
|
||||
размер контента := новый размер контента
|
||||
}
|
||||
}
|
||||
|
||||
ответ.заглавия.добавить(заглавие)
|
||||
}
|
||||
}
|
||||
} иначе {
|
||||
ответ.туловище := строка.соединить(ответ.туловище, данные)
|
||||
}
|
||||
}
|
||||
|
||||
вернуть ответ
|
||||
}
|
||||
24
исх/сеть/хттп/типы.tri
Normal file
24
исх/сеть/хттп/типы.tri
Normal file
@@ -0,0 +1,24 @@
|
||||
модуль хттп
|
||||
|
||||
тип ХттпЗаглавие* = класс {
|
||||
имя*: Строка := ""
|
||||
значение*: Строка := ""
|
||||
}
|
||||
|
||||
тип ХттпЗаглавия* = []ХттпЗаглавие
|
||||
|
||||
тип ХттпОбращение* = класс {
|
||||
метод*: Строка := ""
|
||||
путь*: Строка := ""
|
||||
версия*: Строка := ""
|
||||
заглавия*: ХттпЗаглавия := ХттпЗаглавия[]
|
||||
туловище*: Строка := ""
|
||||
}
|
||||
|
||||
тип ХттпОтвет* = класс {
|
||||
версия*: Строка := "HTTP/1.1"
|
||||
код*: Цел64 := 200
|
||||
состояние*: Строка := "OK"
|
||||
заглавия*: ХттпЗаглавия := ХттпЗаглавия[]
|
||||
туловище*: Строка := ""
|
||||
}
|
||||
Reference in New Issue
Block a user