236 lines
12 KiB
Plaintext
236 lines
12 KiB
Plaintext
модуль хттп
|
||
|
||
импорт "исх/строка"
|
||
импорт "исх/вперед-назад"
|
||
импорт "исх/сеть/тцп"
|
||
|
||
фн сериализовать хттп ответ*(р: ХттпОтвет): Строка {
|
||
пусть ответ := строка.собрать(строка.ф("$стр $цел $стр\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
|
||
|
||
если строка.извлечь цел(заглавие.значение, номер байта, новый размер контента) {
|
||
размер контента := новый размер контента
|
||
}
|
||
}
|
||
|
||
ответ.заглавия.добавить(заглавие)
|
||
}
|
||
}
|
||
} иначе {
|
||
ответ.туловище := строка.соединить(ответ.туловище, данные)
|
||
}
|
||
}
|
||
|
||
вернуть ответ
|
||
}
|