Files
srab/исх/сеть/хттп/парсер.tri
2025-11-26 21:32:41 +03:00

236 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
модуль хттп
импорт "исх/строка"
импорт "исх/вперед-назад"
импорт "исх/сеть/тцп"
фн сериализовать хттп ответ*(р: ХттпОтвет): Строка {
пусть ответ := строка.собрать(строка.ф("$стр $цел $стр\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
если строка.извлечь цел(заглавие.значение, номер байта, новый размер контента) {
размер контента := новый размер контента
}
}
ответ.заглавия.добавить(заглавие)
}
}
} иначе {
ответ.туловище := строка.соединить(ответ.туловище, данные)
}
}
вернуть ответ
}